winlin

refine flv codec, rename fast encoder to flv vod stream decoder

... ... @@ -304,7 +304,7 @@ int SrsHttpVhost::response_flv_file2(SrsSocket* skt, SrsHttpMessage* req, string
return ret;
}
SrsFlvFastDecoder ffd;
SrsFlvVodStreamDecoder ffd;
// open fast decoder
if ((ret = ffd.initialize(&fs)) != ERROR_SUCCESS) {
... ...
... ... @@ -225,18 +225,123 @@ int SrsFlvEncoder::write_tag(char* header, int header_size, char* tag, int tag_s
return ret;
}
SrsFlvFastDecoder::SrsFlvFastDecoder()
SrsFlvDecoder::SrsFlvDecoder()
{
_fs = NULL;
tag_stream = new SrsStream();
}
SrsFlvDecoder::~SrsFlvDecoder()
{
srs_freep(tag_stream);
}
int SrsFlvDecoder::initialize(SrsFileReader* fs)
{
int ret = ERROR_SUCCESS;
_fs = fs;
return ret;
}
int SrsFlvDecoder::read_header(char header[9])
{
int ret = ERROR_SUCCESS;
if ((ret = _fs->read(header, 9, NULL)) != ERROR_SUCCESS) {
return ret;
}
char* h = header;
if (h[0] != 'F' || h[1] != 'L' || h[2] != 'V') {
ret = ERROR_SYSTEM_FLV_HEADER;
srs_warn("flv header must start with FLV. ret=%d", ret);
return ret;
}
return ret;
}
int SrsFlvDecoder::read_tag_header(char* ptype, int32_t* pdata_size, u_int32_t* ptime)
{
int ret = ERROR_SUCCESS;
char th[11]; // tag header
// read tag header
if ((ret = _fs->read(th, 11, NULL)) != ERROR_SUCCESS) {
if (ret != ERROR_SYSTEM_FILE_EOF) {
srs_error("read flv tag header failed. ret=%d", ret);
}
return ret;
}
// Reserved UB [2]
// Filter UB [1]
// TagType UB [5]
*ptype = (int)(th[0] & 0x1F);
// DataSize UI24
char* pp = (char*)pdata_size;
pp[2] = th[1];
pp[1] = th[2];
pp[0] = th[3];
// Timestamp UI24
pp = (char*)ptime;
pp[2] = th[4];
pp[1] = th[5];
pp[0] = th[6];
// TimestampExtended UI8
pp[3] = th[7];
return ret;
}
int SrsFlvDecoder::read_tag_data(char* data, int32_t size)
{
int ret = ERROR_SUCCESS;
if ((ret = _fs->read(data, size, NULL)) != ERROR_SUCCESS) {
if (ret != ERROR_SYSTEM_FILE_EOF) {
srs_error("read flv tag header failed. ret=%d", ret);
}
return ret;
}
return ret;
}
int SrsFlvDecoder::read_previous_tag_size(char ts[4])
{
int ret = ERROR_SUCCESS;
// ignore 4bytes tag size.
if ((ret = _fs->read(ts, 4, NULL)) != ERROR_SUCCESS) {
if (ret != ERROR_SYSTEM_FILE_EOF) {
srs_error("read flv previous tag size failed. ret=%d", ret);
}
return ret;
}
return ret;
}
SrsFlvVodStreamDecoder::SrsFlvVodStreamDecoder()
{
_fs = NULL;
tag_stream = new SrsStream();
}
SrsFlvFastDecoder::~SrsFlvFastDecoder()
SrsFlvVodStreamDecoder::~SrsFlvVodStreamDecoder()
{
srs_freep(tag_stream);
}
int SrsFlvFastDecoder::initialize(SrsFileReader* fs)
int SrsFlvVodStreamDecoder::initialize(SrsFileReader* fs)
{
int ret = ERROR_SUCCESS;
... ... @@ -245,7 +350,7 @@ int SrsFlvFastDecoder::initialize(SrsFileReader* fs)
return ret;
}
int SrsFlvFastDecoder::read_header(char** pdata, int* psize)
int SrsFlvVodStreamDecoder::read_header(char** pdata, int* psize)
{
*pdata = NULL;
*psize = 0;
... ... @@ -268,7 +373,7 @@ int SrsFlvFastDecoder::read_header(char** pdata, int* psize)
return ret;
}
int SrsFlvFastDecoder::read_sequence_header(int64_t* pstart, int* psize)
int SrsFlvVodStreamDecoder::read_sequence_header(int64_t* pstart, int* psize)
{
*pstart = 0;
*psize = 0;
... ... @@ -361,7 +466,7 @@ int SrsFlvFastDecoder::read_sequence_header(int64_t* pstart, int* psize)
return ret;
}
int SrsFlvFastDecoder::lseek(int64_t offset)
int SrsFlvVodStreamDecoder::lseek(int64_t offset)
{
int ret = ERROR_SUCCESS;
... ... @@ -386,108 +491,3 @@ int SrsFlvFastDecoder::lseek(int64_t offset)
return ret;
}
SrsFlvDecoder::SrsFlvDecoder()
{
_fs = NULL;
tag_stream = new SrsStream();
}
SrsFlvDecoder::~SrsFlvDecoder()
{
srs_freep(tag_stream);
}
int SrsFlvDecoder::initialize(SrsFileReader* fs)
{
int ret = ERROR_SUCCESS;
_fs = fs;
return ret;
}
int SrsFlvDecoder::read_header(char header[9])
{
int ret = ERROR_SUCCESS;
if ((ret = _fs->read(header, 9, NULL)) != ERROR_SUCCESS) {
return ret;
}
char* h = header;
if (h[0] != 'F' || h[1] != 'L' || h[2] != 'V') {
ret = ERROR_SYSTEM_FLV_HEADER;
srs_warn("flv header must start with FLV. ret=%d", ret);
return ret;
}
return ret;
}
int SrsFlvDecoder::read_tag_header(char* ptype, int32_t* pdata_size, u_int32_t* ptime)
{
int ret = ERROR_SUCCESS;
char th[11]; // tag header
// read tag header
if ((ret = _fs->read(th, 11, NULL)) != ERROR_SUCCESS) {
if (ret != ERROR_SYSTEM_FILE_EOF) {
srs_error("read flv tag header failed. ret=%d", ret);
}
return ret;
}
// Reserved UB [2]
// Filter UB [1]
// TagType UB [5]
*ptype = (int)(th[0] & 0x1F);
// DataSize UI24
char* pp = (char*)pdata_size;
pp[2] = th[1];
pp[1] = th[2];
pp[0] = th[3];
// Timestamp UI24
pp = (char*)ptime;
pp[2] = th[4];
pp[1] = th[5];
pp[0] = th[6];
// TimestampExtended UI8
pp[3] = th[7];
return ret;
}
int SrsFlvDecoder::read_tag_data(char* data, int32_t size)
{
int ret = ERROR_SUCCESS;
if ((ret = _fs->read(data, size, NULL)) != ERROR_SUCCESS) {
if (ret != ERROR_SYSTEM_FILE_EOF) {
srs_error("read flv tag header failed. ret=%d", ret);
}
return ret;
}
return ret;
}
int SrsFlvDecoder::read_previous_tag_size(char ts[4])
{
int ret = ERROR_SUCCESS;
// ignore 4bytes tag size.
if ((ret = _fs->read(ts, 4, NULL)) != ERROR_SUCCESS) {
if (ret != ERROR_SYSTEM_FILE_EOF) {
srs_error("read flv previous tag size failed. ret=%d", ret);
}
return ret;
}
return ret;
}
... ...
... ... @@ -49,8 +49,9 @@ public:
virtual ~SrsFlvEncoder();
public:
/**
* initialize the underlayer file stream,
* user can initialize multiple times to encode multiple flv files.
* initialize the underlayer file stream.
* @remark user can initialize multiple times to encode multiple flv files.
* @remark, user must free the fs, flv encoder never close/free it.
*/
virtual int initialize(SrsFileWriter* fs);
public:
... ... @@ -85,62 +86,66 @@ private:
};
/**
* decode flv fast by only decoding the header and tag.
* decode flv file.
*/
class SrsFlvFastDecoder
class SrsFlvDecoder
{
private:
SrsFileReader* _fs;
private:
SrsStream* tag_stream;
public:
SrsFlvFastDecoder();
virtual ~SrsFlvFastDecoder();
SrsFlvDecoder();
virtual ~SrsFlvDecoder();
public:
/**
* initialize the underlayer file stream,
* user can initialize multiple times to encode multiple flv files.
* initialize the underlayer file stream
* @remark user can initialize multiple times to decode multiple flv files.
* @remark, user must free the fs, flv decoder never close/free it.
*/
virtual int initialize(SrsFileReader* fs);
public:
/**
* read the flv header and size.
*/
virtual int read_header(char** pdata, int* psize);
/**
* read the sequence header and size.
*/
virtual int read_sequence_header(int64_t* pstart, int* psize);
public:
/**
* for start offset, seed to this position and response flv stream.
*/
virtual int lseek(int64_t offset);
virtual int read_header(char header[9]);
virtual int read_tag_header(char* ptype, int32_t* pdata_size, u_int32_t* ptime);
virtual int read_tag_data(char* data, int32_t size);
virtual int read_previous_tag_size(char ts[4]);
};
/**
* decode flv file.
* decode flv fast by only decoding the header and tag.
* used for vod flv stream to read the header and sequence header,
* then seek to specified offset.
*/
class SrsFlvDecoder
class SrsFlvVodStreamDecoder
{
private:
SrsFileReader* _fs;
private:
SrsStream* tag_stream;
public:
SrsFlvDecoder();
virtual ~SrsFlvDecoder();
SrsFlvVodStreamDecoder();
virtual ~SrsFlvVodStreamDecoder();
public:
/**
* initialize the underlayer file stream,
* user can initialize multiple times to decode multiple flv files.
* initialize the underlayer file stream
* @remark user can initialize multiple times to decode multiple flv files.
* @remark, user must free the fs, flv decoder never close/free it.
*/
virtual int initialize(SrsFileReader* fs);
public:
virtual int read_header(char header[9]);
virtual int read_tag_header(char* ptype, int32_t* pdata_size, u_int32_t* ptime);
virtual int read_tag_data(char* data, int32_t size);
virtual int read_previous_tag_size(char ts[4]);
/**
* read the flv header and size.
*/
virtual int read_header(char** pdata, int* psize);
/**
* read the sequence header and size.
*/
virtual int read_sequence_header(int64_t* pstart, int* psize);
public:
/**
* for start offset, seed to this position and response flv stream.
*/
virtual int lseek(int64_t offset);
};
#endif
... ...
... ... @@ -26,88 +26,7 @@ using namespace std;
#include <srs_kernel_error.hpp>
#include <srs_kernel_codec.hpp>
VOID TEST(KernelCodecTest, IsKeyFrame)
{
int8_t data;
data = 0x10;
EXPECT_TRUE(SrsFlvCodec::video_is_keyframe(&data, 1));
EXPECT_FALSE(SrsFlvCodec::video_is_keyframe(&data, 0));
data = 0x20;
EXPECT_FALSE(SrsFlvCodec::video_is_keyframe(&data, 1));
}
VOID TEST(KernelCodecTest, IsH264)
{
int8_t data;
EXPECT_FALSE(SrsFlvCodec::video_is_h264(&data, 0));
data = 0x17;
EXPECT_TRUE(SrsFlvCodec::video_is_h264(&data, 1));
data = 0x07;
EXPECT_TRUE(SrsFlvCodec::video_is_h264(&data, 1));
data = 0x08;
EXPECT_FALSE(SrsFlvCodec::video_is_h264(&data, 1));
}
VOID TEST(KernelCodecTest, IsSequenceHeader)
{
int16_t data;
char* pp = (char*)&data;
EXPECT_FALSE(SrsFlvCodec::video_is_sequence_header((int8_t*)pp, 0));
EXPECT_FALSE(SrsFlvCodec::video_is_sequence_header((int8_t*)pp, 1));
pp[0] = 0x17;
pp[1] = 0x00;
EXPECT_TRUE(SrsFlvCodec::video_is_sequence_header((int8_t*)pp, 2));
pp[0] = 0x18;
EXPECT_FALSE(SrsFlvCodec::video_is_sequence_header((int8_t*)pp, 2));
pp[0] = 0x27;
EXPECT_FALSE(SrsFlvCodec::video_is_sequence_header((int8_t*)pp, 2));
pp[0] = 0x17;
pp[1] = 0x01;
EXPECT_FALSE(SrsFlvCodec::video_is_sequence_header((int8_t*)pp, 2));
}
VOID TEST(KernelCodecTest, IsAAC)
{
int8_t data;
EXPECT_FALSE(SrsFlvCodec::audio_is_aac(&data, 0));
data = 0xa0;
EXPECT_TRUE(SrsFlvCodec::audio_is_aac(&data, 1));
data = 0xa7;
EXPECT_TRUE(SrsFlvCodec::audio_is_aac(&data, 1));
data = 0x00;
EXPECT_FALSE(SrsFlvCodec::audio_is_aac(&data, 1));
}
VOID TEST(KernelCodecTest, IsAudioSequenceHeader)
{
int16_t data;
char* pp = (char*)&data;
EXPECT_FALSE(SrsFlvCodec::audio_is_sequence_header((int8_t*)pp, 0));
EXPECT_FALSE(SrsFlvCodec::audio_is_sequence_header((int8_t*)pp, 1));
pp[0] = 0xa0;
pp[1] = 0x00;
EXPECT_TRUE(SrsFlvCodec::audio_is_sequence_header((int8_t*)pp, 2));
pp[0] = 0x00;
EXPECT_FALSE(SrsFlvCodec::video_is_sequence_header((int8_t*)pp, 2));
pp[0] = 0xa0;
pp[1] = 0x01;
EXPECT_FALSE(SrsFlvCodec::video_is_sequence_header((int8_t*)pp, 2));
}
#include <srs_kernel_flv.hpp>
MockSrsFileWriter::MockSrsFileWriter()
{
... ... @@ -194,3 +113,92 @@ int MockSrsFileReader::read(void* buf, size_t count, ssize_t* pnread)
int ret = ERROR_SUCCESS;
return ret;
}
VOID TEST(KernelCodecTest, IsKeyFrame)
{
int8_t data;
data = 0x10;
EXPECT_TRUE(SrsFlvCodec::video_is_keyframe(&data, 1));
EXPECT_FALSE(SrsFlvCodec::video_is_keyframe(&data, 0));
data = 0x20;
EXPECT_FALSE(SrsFlvCodec::video_is_keyframe(&data, 1));
}
VOID TEST(KernelCodecTest, IsH264)
{
int8_t data;
EXPECT_FALSE(SrsFlvCodec::video_is_h264(&data, 0));
data = 0x17;
EXPECT_TRUE(SrsFlvCodec::video_is_h264(&data, 1));
data = 0x07;
EXPECT_TRUE(SrsFlvCodec::video_is_h264(&data, 1));
data = 0x08;
EXPECT_FALSE(SrsFlvCodec::video_is_h264(&data, 1));
}
VOID TEST(KernelCodecTest, IsSequenceHeader)
{
int16_t data;
char* pp = (char*)&data;
EXPECT_FALSE(SrsFlvCodec::video_is_sequence_header((int8_t*)pp, 0));
EXPECT_FALSE(SrsFlvCodec::video_is_sequence_header((int8_t*)pp, 1));
pp[0] = 0x17;
pp[1] = 0x00;
EXPECT_TRUE(SrsFlvCodec::video_is_sequence_header((int8_t*)pp, 2));
pp[0] = 0x18;
EXPECT_FALSE(SrsFlvCodec::video_is_sequence_header((int8_t*)pp, 2));
pp[0] = 0x27;
EXPECT_FALSE(SrsFlvCodec::video_is_sequence_header((int8_t*)pp, 2));
pp[0] = 0x17;
pp[1] = 0x01;
EXPECT_FALSE(SrsFlvCodec::video_is_sequence_header((int8_t*)pp, 2));
}
VOID TEST(KernelCodecTest, IsAAC)
{
int8_t data;
EXPECT_FALSE(SrsFlvCodec::audio_is_aac(&data, 0));
data = 0xa0;
EXPECT_TRUE(SrsFlvCodec::audio_is_aac(&data, 1));
data = 0xa7;
EXPECT_TRUE(SrsFlvCodec::audio_is_aac(&data, 1));
data = 0x00;
EXPECT_FALSE(SrsFlvCodec::audio_is_aac(&data, 1));
}
VOID TEST(KernelCodecTest, IsAudioSequenceHeader)
{
int16_t data;
char* pp = (char*)&data;
EXPECT_FALSE(SrsFlvCodec::audio_is_sequence_header((int8_t*)pp, 0));
EXPECT_FALSE(SrsFlvCodec::audio_is_sequence_header((int8_t*)pp, 1));
pp[0] = 0xa0;
pp[1] = 0x00;
EXPECT_TRUE(SrsFlvCodec::audio_is_sequence_header((int8_t*)pp, 2));
pp[0] = 0x00;
EXPECT_FALSE(SrsFlvCodec::video_is_sequence_header((int8_t*)pp, 2));
pp[0] = 0xa0;
pp[1] = 0x01;
EXPECT_FALSE(SrsFlvCodec::video_is_sequence_header((int8_t*)pp, 2));
}
VOID TEST(KernelFlvTest, IsAudioSequenceHeader)
{
MockSrsFileWriter fs;
SrsFlvEncoder enc;
ASSERT_TRUE(ERROR_SUCCESS == enc.initialize(&fs));
}
... ...