winlin

complete the normal kernel flv utest. 0.9.147

... ... @@ -312,14 +312,12 @@ int SrsHttpVhost::response_flv_file2(SrsSocket* skt, SrsHttpMessage* req, string
}
// save header, send later.
char* flv_header = NULL;
int flv_size = 0;
char flv_header[13];
// send flv header
if ((ret = ffd.read_header(&flv_header, &flv_size)) != ERROR_SUCCESS) {
if ((ret = ffd.read_header_ext(flv_header)) != ERROR_SUCCESS) {
return ret;
}
SrsAutoFree(char, flv_header);
// save sequence header, send later
char* sh_data = NULL;
... ... @@ -328,7 +326,7 @@ int SrsHttpVhost::response_flv_file2(SrsSocket* skt, SrsHttpMessage* req, string
if (true) {
// send sequence header
int64_t start = 0;
if ((ret = ffd.read_sequence_header(&start, &sh_size)) != ERROR_SUCCESS) {
if ((ret = ffd.read_sequence_header_summary(&start, &sh_size)) != ERROR_SUCCESS) {
return ret;
}
if (sh_size <= 0) {
... ... @@ -350,7 +348,7 @@ int SrsHttpVhost::response_flv_file2(SrsSocket* skt, SrsHttpMessage* req, string
std::stringstream ss;
res_status_line(ss)->res_content_type_flv(ss)
->res_content_length(ss, (int)(flv_size + sh_size + left));
->res_content_length(ss, (int)(sizeof(flv_header) + sh_size + left));
if (req->requires_crossdomain()) {
res_enable_crossdomain(ss);
... ... @@ -363,7 +361,7 @@ int SrsHttpVhost::response_flv_file2(SrsSocket* skt, SrsHttpMessage* req, string
return ret;
}
if (flv_size > 0 && (ret = skt->write(flv_header, flv_size, NULL)) != ERROR_SUCCESS) {
if ((ret = skt->write(flv_header, sizeof(flv_header), NULL)) != ERROR_SUCCESS) {
return ret;
}
if (sh_size > 0 && (ret = skt->write(sh_data, sh_size, NULL)) != ERROR_SUCCESS) {
... ...
/*
The MIT License (MIT)
Copyright (c) 2013-2014 winlin
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef SRS_CORE_HPP
#define SRS_CORE_HPP
/*
#include <srs_core.hpp>
*/
// current release version
#define VERSION_MAJOR "0"
#define VERSION_MINOR "9"
#define VERSION_REVISION "146"
#define RTMP_SIG_SRS_VERSION VERSION_MAJOR"."VERSION_MINOR"."VERSION_REVISION
// server info.
#define RTMP_SIG_SRS_KEY "SRS"
#define RTMP_SIG_SRS_ROLE "origin/edge server"
#define RTMP_SIG_SRS_NAME RTMP_SIG_SRS_KEY"(Simple RTMP Server)"
#define RTMP_SIG_SRS_URL_SHORT "github.com/winlinvip/simple-rtmp-server"
#define RTMP_SIG_SRS_URL "https://"RTMP_SIG_SRS_URL_SHORT
#define RTMP_SIG_SRS_WEB "http://blog.csdn.net/win_lin"
#define RTMP_SIG_SRS_EMAIL "winlin@vip.126.com"
#define RTMP_SIG_SRS_LICENSE "The MIT License (MIT)"
#define RTMP_SIG_SRS_COPYRIGHT "Copyright (c) 2013-2014 winlin"
#define RTMP_SIG_SRS_PRIMARY_AUTHROS "winlin,wenjie.zhao"
#define RTMP_SIG_SRS_CONTRIBUTORS_URL RTMP_SIG_SRS_URL"/blob/master/AUTHORS.txt"
/**
* the core provides the common defined macros, utilities,
* user must include the srs_core.hpp before any header, or maybe
* build failed.
*/
// for 32bit os, 2G big file limit for unistd io,
// ie. read/write/lseek to use 64bits size for huge file.
#ifndef _FILE_OFFSET_BITS
#define _FILE_OFFSET_BITS 64
#endif
// for int64_t print using PRId64 format.
#ifndef __STDC_FORMAT_MACROS
#define __STDC_FORMAT_MACROS
#endif
#include <inttypes.h>
#include <assert.h>
#define srs_assert(expression) assert(expression)
#include <stddef.h>
#include <sys/types.h>
// generated by configure.
#include <srs_auto_headers.hpp>
// free the p and set to NULL.
// p must be a T*.
#define srs_freep(p) \
if (p) { \
delete p; \
p = NULL; \
} \
(void)0
// sometimes, the freepa is useless,
// it's recomments to free each elem explicit.
// so we remove the srs_freepa utility.
/**
* disable copy constructor of class
*/
#define disable_default_copy(className)\
private:\
/** \
* disable the copy constructor and operator=, donot allow directly copy. \
*/ \
className(const className&); \
className& operator= (const className&)
#endif
/*
The MIT License (MIT)
Copyright (c) 2013-2014 winlin
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef SRS_CORE_HPP
#define SRS_CORE_HPP
/*
#include <srs_core.hpp>
*/
// current release version
#define VERSION_MAJOR "0"
#define VERSION_MINOR "9"
#define VERSION_REVISION "147"
#define RTMP_SIG_SRS_VERSION VERSION_MAJOR"."VERSION_MINOR"."VERSION_REVISION
// server info.
#define RTMP_SIG_SRS_KEY "SRS"
#define RTMP_SIG_SRS_ROLE "origin/edge server"
#define RTMP_SIG_SRS_NAME RTMP_SIG_SRS_KEY"(Simple RTMP Server)"
#define RTMP_SIG_SRS_URL_SHORT "github.com/winlinvip/simple-rtmp-server"
#define RTMP_SIG_SRS_URL "https://"RTMP_SIG_SRS_URL_SHORT
#define RTMP_SIG_SRS_WEB "http://blog.csdn.net/win_lin"
#define RTMP_SIG_SRS_EMAIL "winlin@vip.126.com"
#define RTMP_SIG_SRS_LICENSE "The MIT License (MIT)"
#define RTMP_SIG_SRS_COPYRIGHT "Copyright (c) 2013-2014 winlin"
#define RTMP_SIG_SRS_PRIMARY_AUTHROS "winlin,wenjie.zhao"
#define RTMP_SIG_SRS_CONTRIBUTORS_URL RTMP_SIG_SRS_URL"/blob/master/AUTHORS.txt"
/**
* the core provides the common defined macros, utilities,
* user must include the srs_core.hpp before any header, or maybe
* build failed.
*/
// for 32bit os, 2G big file limit for unistd io,
// ie. read/write/lseek to use 64bits size for huge file.
#ifndef _FILE_OFFSET_BITS
#define _FILE_OFFSET_BITS 64
#endif
// for int64_t print using PRId64 format.
#ifndef __STDC_FORMAT_MACROS
#define __STDC_FORMAT_MACROS
#endif
#include <inttypes.h>
#include <assert.h>
#define srs_assert(expression) assert(expression)
#include <stddef.h>
#include <sys/types.h>
// generated by configure.
#include <srs_auto_headers.hpp>
// free the p and set to NULL.
// p must be a T*.
#define srs_freep(p) \
if (p) { \
delete p; \
p = NULL; \
} \
(void)0
// sometimes, the freepa is useless,
// it's recomments to free each elem explicit.
// so we remove the srs_freepa utility.
/**
* disable copy constructor of class
*/
#define disable_default_copy(className)\
private:\
/** \
* disable the copy constructor and operator=, donot allow directly copy. \
*/ \
className(const className&); \
className& operator= (const className&)
#endif
... ...
... ... @@ -119,8 +119,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#define ERROR_SYSTEM_FILE_RENAME 429
#define ERROR_SYSTEM_CREATE_PIPE 430
#define ERROR_SYSTEM_FILE_SEEK 431
#define ERROR_SYSTEM_FLV_HEADER 432
#define ERROR_SYSTEM_IO_INVALID 433
#define ERROR_SYSTEM_IO_INVALID 432
// see librtmp.
// failed when open ssl create the dh
... ... @@ -189,12 +188,15 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#define ERROR_HTTP_FLV_SEQUENCE_HEADER 806
#define ERROR_HTTP_FLV_OFFSET_OVERFLOW 807
#define ERROR_KERNEL_FLV_HEADER 900
#define ERROR_KERNEL_FLV_STREAM_CLOSED 901
// system control message,
// not an error, but special control logic.
// sys ctl: rtmp close stream, support replay.
#define ERROR_CONTROL_RTMP_CLOSE 900
#define ERROR_CONTROL_RTMP_CLOSE 2000
// FMLE stop publish and republish.
#define ERROR_CONTROL_REPUBLISH 901
#define ERROR_CONTROL_REPUBLISH 2001
/**
* whether the error code is an system control error.
... ...
... ... @@ -53,6 +53,12 @@ int SrsFlvEncoder::initialize(SrsFileWriter* fs)
{
int ret = ERROR_SUCCESS;
if (!fs->is_open()) {
ret = ERROR_KERNEL_FLV_STREAM_CLOSED;
srs_warn("stream is not open for decoder. ret=%d", ret);
return ret;
}
_fs = fs;
return ret;
... ... @@ -92,7 +98,7 @@ int SrsFlvEncoder::write_header(char flv_header[9])
return ret;
}
char pts[] = { 0x00, 0x00, 0x00, 0x00 };
char pts[] = { (char)0x00, (char)0x00, (char)0x00, (char)0x00 };
if ((ret = _fs->write(pts, 4, NULL)) != ERROR_SUCCESS) {
return ret;
}
... ... @@ -104,6 +110,7 @@ int SrsFlvEncoder::write_metadata(char* data, int size)
{
int ret = ERROR_SUCCESS;
// 11 bytes tag header
static char tag_header[] = {
(char)18, // TagType UB [5], 18 = script data
(char)0x00, (char)0x00, (char)0x00, // DataSize UI24 Length of the message.
... ... @@ -240,6 +247,12 @@ int SrsFlvDecoder::initialize(SrsFileReader* fs)
{
int ret = ERROR_SUCCESS;
if (!fs->is_open()) {
ret = ERROR_KERNEL_FLV_STREAM_CLOSED;
srs_warn("stream is not open for decoder. ret=%d", ret);
return ret;
}
_fs = fs;
return ret;
... ... @@ -255,7 +268,7 @@ int SrsFlvDecoder::read_header(char header[9])
char* h = header;
if (h[0] != 'F' || h[1] != 'L' || h[2] != 'V') {
ret = ERROR_SYSTEM_FLV_HEADER;
ret = ERROR_KERNEL_FLV_HEADER;
srs_warn("flv header must start with FLV. ret=%d", ret);
return ret;
}
... ... @@ -345,35 +358,37 @@ int SrsFlvVodStreamDecoder::initialize(SrsFileReader* fs)
{
int ret = ERROR_SUCCESS;
if (!fs->is_open()) {
ret = ERROR_KERNEL_FLV_STREAM_CLOSED;
srs_warn("stream is not open for decoder. ret=%d", ret);
return ret;
}
_fs = fs;
return ret;
}
int SrsFlvVodStreamDecoder::read_header(char** pdata, int* psize)
int SrsFlvVodStreamDecoder::read_header_ext(char header[13])
{
*pdata = NULL;
*psize = 0;
int ret = ERROR_SUCCESS;
srs_assert(_fs);
// @remark, always false, for sizeof(char[13]) equals to sizeof(char*)
//srs_assert(13 == sizeof(header));
// 9bytes header and 4bytes first previous-tag-size
int size = 13;
char* buf = new char[size];
if ((ret = _fs->read(buf, size, NULL)) != ERROR_SUCCESS) {
if ((ret = _fs->read(header, size, NULL)) != ERROR_SUCCESS) {
return ret;
}
*pdata = buf;
*psize = size;
return ret;
}
int SrsFlvVodStreamDecoder::read_sequence_header(int64_t* pstart, int* psize)
int SrsFlvVodStreamDecoder::read_sequence_header_summary(int64_t* pstart, int* psize)
{
*pstart = 0;
*psize = 0;
... ...
... ... @@ -66,7 +66,7 @@ public:
virtual int write_header(char flv_header[9]);
/**
* write flv metadata.
* serialize from:
* @param data, the amf0 metadata which serialize from:
* AMF0 string: onMetaData,
* AMF0 object: the metadata object.
*/
... ... @@ -76,6 +76,7 @@ public:
*/
virtual int write_audio(int64_t timestamp, char* data, int size);
virtual int write_video(int64_t timestamp, char* data, int size);
public:
/**
* get the tag size,
* including the tag header, body, and 4bytes previous tag size.
... ... @@ -134,13 +135,17 @@ public:
virtual int initialize(SrsFileReader* fs);
public:
/**
* read the flv header and size.
* read the flv header and its size.
* @param header, fill it 13bytes(9bytes header, 4bytes previous tag size).
*/
virtual int read_header(char** pdata, int* psize);
virtual int read_header_ext(char header[13]);
/**
* read the sequence header and size.
* read the sequence header tags offset and its size.
* @param pstart, the start offset of sequence header.
* @param psize, output the size, (tag header)+(tag body)+(4bytes previous tag size).
* @remark we think the first audio/video is sequence header.
*/
virtual int read_sequence_header(int64_t* pstart, int* psize);
virtual int read_sequence_header_summary(int64_t* pstart, int* psize);
public:
/**
* for start offset, seed to this position and response flv stream.
... ...
... ... @@ -557,31 +557,6 @@ namespace srs
return bytes;
}
/**
* compare the memory in bytes.
*/
bool srs_bytes_equals(void* pa, void* pb, int size)
{
u_int8_t* a = (u_int8_t*)pa;
u_int8_t* b = (u_int8_t*)pb;
if (!a && !b) {
return true;
}
if (!a || !b) {
return false;
}
for(int i = 0; i < size; i++){
if(a[i] != b[i]){
return false;
}
}
return true;
}
c2s2::c2s2()
{
srs_random_generate(random, 1504);
... ...
... ... @@ -168,11 +168,6 @@ namespace srs
char* srs_bytes_join_schema1(int32_t time, int32_t version, digest_block* digest, key_block* key);
/**
* compare the memory in bytes.
*/
bool srs_bytes_equals(void* pa, void* pb, int size);
/**
* c1s1 schema0
* time: 4bytes
* version: 4bytes
... ...
... ... @@ -126,3 +126,28 @@ string srs_generate_tc_url(string ip, string vhost, string app, string port)
return tcUrl;
}
/**
* compare the memory in bytes.
*/
bool srs_bytes_equals(void* pa, void* pb, int size)
{
u_int8_t* a = (u_int8_t*)pa;
u_int8_t* b = (u_int8_t*)pb;
if (!a && !b) {
return true;
}
if (!a || !b) {
return false;
}
for(int i = 0; i < size; i++){
if(a[i] != b[i]){
return false;
}
}
return true;
}
... ...
... ... @@ -58,4 +58,9 @@ extern void srs_random_generate(char* bytes, int size);
// generate the tcUrl.
extern std::string srs_generate_tc_url(std::string ip, std::string vhost, std::string app, std::string port);
/**
* compare the memory in bytes.
*/
extern bool srs_bytes_equals(void* pa, void* pb, int size);
#endif
... ...
... ... @@ -27,93 +27,155 @@ using namespace std;
#include <srs_kernel_error.hpp>
#include <srs_kernel_codec.hpp>
#include <srs_kernel_flv.hpp>
#include <srs_kernel_utility.hpp>
#include <srs_protocol_utility.hpp>
#define MAX_MOCK_DATA_SIZE 1024 * 1024
MockSrsFileWriter::MockSrsFileWriter()
{
data = new char[MAX_MOCK_DATA_SIZE];
offset = -1;
}
MockSrsFileWriter::~MockSrsFileWriter()
{
srs_freep(data);
}
int MockSrsFileWriter::open(string file)
int MockSrsFileWriter::open(string /*file*/)
{
int ret = ERROR_SUCCESS;
offset = 0;
return ret;
}
void MockSrsFileWriter::close()
{
int ret = ERROR_SUCCESS;
return;
offset = 0;
}
bool MockSrsFileWriter::is_open()
{
return true;
return offset >= 0;
}
int64_t MockSrsFileWriter::tellg()
{
return 0;
return offset;
}
int MockSrsFileWriter::write(void* buf, size_t count, ssize_t* pnwrite)
{
int ret = ERROR_SUCCESS;
int size = srs_min(MAX_MOCK_DATA_SIZE - offset, count);
memcpy(data + offset, buf, size);
if (pnwrite) {
*pnwrite = size;
}
offset += size;
return ret;
}
void MockSrsFileWriter::mock_reset_offset()
{
offset = 0;
}
MockSrsFileReader::MockSrsFileReader()
{
data = new char[MAX_MOCK_DATA_SIZE];
size = 0;
offset = -1;
}
MockSrsFileReader::~MockSrsFileReader()
{
srs_freep(data);
}
int MockSrsFileReader::open(string file)
int MockSrsFileReader::open(string /*file*/)
{
int ret = ERROR_SUCCESS;
offset = 0;
return ret;
}
void MockSrsFileReader::close()
{
int ret = ERROR_SUCCESS;
return;
offset = 0;
}
bool MockSrsFileReader::is_open()
{
return true;
return offset >= 0;
}
int64_t MockSrsFileReader::tellg()
{
return 0;
return offset;
}
void MockSrsFileReader::skip(int64_t size)
void MockSrsFileReader::skip(int64_t _size)
{
offset += _size;
}
int64_t MockSrsFileReader::lseek(int64_t offset)
int64_t MockSrsFileReader::lseek(int64_t _offset)
{
offset = (int)_offset;
return offset;
}
int64_t MockSrsFileReader::filesize()
{
return 0;
return size;
}
int MockSrsFileReader::read(void* buf, size_t count, ssize_t* pnread)
{
int ret = ERROR_SUCCESS;
int s = srs_min(size - offset, (int)count);
if (s <= 0) {
return ret;
}
memcpy(buf, data + offset, s);
if (pnread) {
*pnread = s;
}
offset += s;
return ret;
}
void MockSrsFileReader::mock_append_data(const char* _data, int _size)
{
int s = srs_min(MAX_MOCK_DATA_SIZE - offset, _size);
memcpy(data + offset, _data, s);
offset += s;
size += s;
}
void MockSrsFileReader::mock_reset_offset()
{
offset = 0;
}
VOID TEST(KernelCodecTest, IsKeyFrame)
{
int8_t data;
... ... @@ -196,9 +258,431 @@ VOID TEST(KernelCodecTest, IsAudioSequenceHeader)
EXPECT_FALSE(SrsFlvCodec::video_is_sequence_header((int8_t*)pp, 2));
}
VOID TEST(KernelFlvTest, IsAudioSequenceHeader)
VOID TEST(KernelFlvTest, FlvEncoderStreamClosed)
{
MockSrsFileWriter fs;
SrsFlvEncoder enc;
ASSERT_TRUE(ERROR_SUCCESS != enc.initialize(&fs));
}
VOID TEST(KernelFlvTest, FlvEncoderWriteHeader)
{
MockSrsFileWriter fs;
SrsFlvEncoder enc;
ASSERT_TRUE(ERROR_SUCCESS == fs.open(""));
ASSERT_TRUE(ERROR_SUCCESS == enc.initialize(&fs));
// write header, 9bytes
char flv_header[] = {
'F', 'L', 'V', // Signatures "FLV"
(char)0x01, // File version (for example, 0x01 for FLV version 1)
(char)0x00, // 4, audio; 1, video; 5 audio+video.
(char)0x00, (char)0x00, (char)0x00, (char)0x09 // DataOffset UI32 The length of this header in bytes
};
char pts[] = { (char)0x00, (char)0x00, (char)0x00, (char)0x00 };
EXPECT_TRUE(ERROR_SUCCESS == enc.write_header());
ASSERT_TRUE(9 + 4 == fs.offset);
EXPECT_TRUE(srs_bytes_equals(flv_header, fs.data, 9));
EXPECT_TRUE(srs_bytes_equals(pts, fs.data + 9, 4));
// customer header
flv_header[3] = 0xF0;
flv_header[4] = 0xF1;
flv_header[5] = 0x01;
fs.mock_reset_offset();
EXPECT_TRUE(ERROR_SUCCESS == enc.write_header(flv_header));
ASSERT_TRUE(9 + 4 == fs.offset);
EXPECT_TRUE(srs_bytes_equals(flv_header, fs.data, 9));
EXPECT_TRUE(srs_bytes_equals(pts, fs.data + 9, 4));
}
VOID TEST(KernelFlvTest, FlvEncoderWriteMetadata)
{
MockSrsFileWriter fs;
EXPECT_TRUE(ERROR_SUCCESS == fs.open(""));
SrsFlvEncoder enc;
ASSERT_TRUE(ERROR_SUCCESS == enc.initialize(&fs));
// 11 bytes tag header
char tag_header[] = {
(char)18, // TagType UB [5], 18 = script data
(char)0x00, (char)0x00, (char)0x08, // DataSize UI24 Length of the message.
(char)0x00, (char)0x00, (char)0x00, // Timestamp UI24 Time in milliseconds at which the data in this tag applies.
(char)0x00, // TimestampExtended UI8
(char)0x00, (char)0x00, (char)0x00, // StreamID UI24 Always 0.
};
char md[] = {
(char)0x01, (char)0x02, (char)0x03, (char)0x04,
(char)0x04, (char)0x03, (char)0x02, (char)0x01
};
char pts[] = { (char)0x00, (char)0x00, (char)0x00, (char)19 };
ASSERT_TRUE(ERROR_SUCCESS == enc.write_metadata(md, 8));
ASSERT_TRUE(11 + 8 + 4 == fs.offset);
EXPECT_TRUE(srs_bytes_equals(tag_header, fs.data, 11));
EXPECT_TRUE(srs_bytes_equals(md, fs.data + 11, 8));
EXPECT_TRUE(true); // donot know why, if not add it, the print is disabled.
EXPECT_TRUE(srs_bytes_equals(pts, fs.data + 19, 4));
}
VOID TEST(KernelFlvTest, FlvEncoderWriteAudio)
{
MockSrsFileWriter fs;
SrsFlvEncoder enc;
ASSERT_TRUE(ERROR_SUCCESS == fs.open(""));
ASSERT_TRUE(ERROR_SUCCESS == enc.initialize(&fs));
// 11bytes tag header
char tag_header[] = {
(char)8, // TagType UB [5], 8 = audio
(char)0x00, (char)0x00, (char)0x08, // DataSize UI24 Length of the message.
(char)0x00, (char)0x00, (char)0x30, // Timestamp UI24 Time in milliseconds at which the data in this tag applies.
(char)0x00, // TimestampExtended UI8
(char)0x00, (char)0x00, (char)0x00, // StreamID UI24 Always 0.
};
char audio[] = {
(char)0x01, (char)0x02, (char)0x03, (char)0x04,
(char)0x04, (char)0x03, (char)0x02, (char)0x01
};
char pts[] = { (char)0x00, (char)0x00, (char)0x00, (char)19 };
ASSERT_TRUE(ERROR_SUCCESS == enc.write_audio(0x30, audio, 8));
ASSERT_TRUE(11 + 8 + 4 == fs.offset);
EXPECT_TRUE(srs_bytes_equals(tag_header, fs.data, 11));
EXPECT_TRUE(srs_bytes_equals(audio, fs.data + 11, 8));
EXPECT_TRUE(true); // donot know why, if not add it, the print is disabled.
EXPECT_TRUE(srs_bytes_equals(pts, fs.data + 11 + 8, 4));
}
VOID TEST(KernelFlvTest, FlvEncoderWriteVideo)
{
MockSrsFileWriter fs;
SrsFlvEncoder enc;
ASSERT_TRUE(ERROR_SUCCESS == fs.open(""));
ASSERT_TRUE(ERROR_SUCCESS == enc.initialize(&fs));
// 11bytes tag header
char tag_header[] = {
(char)9, // TagType UB [5], 9 = video
(char)0x00, (char)0x00, (char)0x08, // DataSize UI24 Length of the message.
(char)0x00, (char)0x00, (char)0x30, // Timestamp UI24 Time in milliseconds at which the data in this tag applies.
(char)0x00, // TimestampExtended UI8
(char)0x00, (char)0x00, (char)0x00, // StreamID UI24 Always 0.
};
char video[] = {
(char)0x01, (char)0x02, (char)0x03, (char)0x04,
(char)0x04, (char)0x03, (char)0x02, (char)0x01
};
char pts[] = { (char)0x00, (char)0x00, (char)0x00, (char)19 };
ASSERT_TRUE(ERROR_SUCCESS == enc.write_video(0x30, video, 8));
ASSERT_TRUE(11 + 8 + 4 == fs.offset);
EXPECT_TRUE(srs_bytes_equals(tag_header, fs.data, 11));
EXPECT_TRUE(srs_bytes_equals(video, fs.data + 11, 8));
EXPECT_TRUE(true); // donot know why, if not add it, the print is disabled.
EXPECT_TRUE(srs_bytes_equals(pts, fs.data + 11 + 8, 4));
}
VOID TEST(KernelFlvTest, FlvEncoderSizeTag)
{
EXPECT_EQ(11+4+10, SrsFlvEncoder::size_tag(10));
EXPECT_EQ(11+4+0, SrsFlvEncoder::size_tag(0));
}
VOID TEST(KernelFlvTest, FlvDecoderStreamClosed)
{
MockSrsFileReader fs;
SrsFlvDecoder dec;
ASSERT_TRUE(ERROR_SUCCESS != dec.initialize(&fs));
}
VOID TEST(KernelFlvTest, FlvDecoderHeader)
{
MockSrsFileReader fs;
SrsFlvDecoder dec;
ASSERT_TRUE(ERROR_SUCCESS == fs.open(""));
ASSERT_TRUE(ERROR_SUCCESS == dec.initialize(&fs));
// 9bytes
char flv_header[] = {
'F', 'L', 'V', // Signatures "FLV"
(char)0x01, // File version (for example, 0x01 for FLV version 1)
(char)0x00, // 4, audio; 1, video; 5 audio+video.
(char)0x00, (char)0x00, (char)0x00, (char)0x09 // DataOffset UI32 The length of this header in bytes
};
char pts[] = { (char)0x00, (char)0x00, (char)0x00, (char)0x00 };
fs.mock_append_data(flv_header, 9);
fs.mock_append_data(pts, 4);
char data[1024];
fs.mock_reset_offset();
EXPECT_TRUE(ERROR_SUCCESS == dec.read_header(data));
EXPECT_TRUE(srs_bytes_equals(flv_header, data, 9));
EXPECT_TRUE(ERROR_SUCCESS == dec.read_previous_tag_size(data));
EXPECT_TRUE(srs_bytes_equals(pts, data, 4));
}
VOID TEST(KernelFlvTest, FlvDecoderMetadata)
{
MockSrsFileReader fs;
SrsFlvDecoder dec;
ASSERT_TRUE(ERROR_SUCCESS == fs.open(""));
ASSERT_TRUE(ERROR_SUCCESS == dec.initialize(&fs));
// 11 bytes tag header
char tag_header[] = {
(char)18, // TagType UB [5], 18 = script data
(char)0x00, (char)0x00, (char)0x08, // DataSize UI24 Length of the message.
(char)0x00, (char)0x00, (char)0x00, // Timestamp UI24 Time in milliseconds at which the data in this tag applies.
(char)0x00, // TimestampExtended UI8
(char)0x00, (char)0x00, (char)0x00, // StreamID UI24 Always 0.
};
char md[] = {
(char)0x01, (char)0x02, (char)0x03, (char)0x04,
(char)0x04, (char)0x03, (char)0x02, (char)0x01
};
char pts[] = { (char)0x00, (char)0x00, (char)0x00, (char)19 };
fs.mock_append_data(tag_header, 11);
fs.mock_append_data(md, 8);
fs.mock_append_data(pts, 4);
char type = 0;
int32_t size = 0;
u_int32_t time = 0;
char data[1024];
fs.mock_reset_offset();
EXPECT_TRUE(ERROR_SUCCESS == dec.read_tag_header(&type, &size, &time));
EXPECT_TRUE(18 == type);
EXPECT_TRUE(8 == size);
EXPECT_TRUE(0 == time);
EXPECT_TRUE(ERROR_SUCCESS == dec.read_tag_data(data, size));
EXPECT_TRUE(srs_bytes_equals(md, data, 8));
EXPECT_TRUE(ERROR_SUCCESS == dec.read_previous_tag_size(data));
EXPECT_TRUE(srs_bytes_equals(pts, data, 4));
}
VOID TEST(KernelFlvTest, FlvDecoderAudio)
{
MockSrsFileReader fs;
SrsFlvDecoder dec;
ASSERT_TRUE(ERROR_SUCCESS == fs.open(""));
ASSERT_TRUE(ERROR_SUCCESS == dec.initialize(&fs));
// 11bytes tag header
char tag_header[] = {
(char)8, // TagType UB [5], 8 = audio
(char)0x00, (char)0x00, (char)0x08, // DataSize UI24 Length of the message.
(char)0x00, (char)0x00, (char)0x30, // Timestamp UI24 Time in milliseconds at which the data in this tag applies.
(char)0x00, // TimestampExtended UI8
(char)0x00, (char)0x00, (char)0x00, // StreamID UI24 Always 0.
};
char audio[] = {
(char)0x01, (char)0x02, (char)0x03, (char)0x04,
(char)0x04, (char)0x03, (char)0x02, (char)0x01
};
char pts[] = { (char)0x00, (char)0x00, (char)0x00, (char)19 };
fs.mock_append_data(tag_header, 11);
fs.mock_append_data(audio, 8);
fs.mock_append_data(pts, 4);
char type = 0;
int32_t size = 0;
u_int32_t time = 0;
char data[1024];
fs.mock_reset_offset();
EXPECT_TRUE(ERROR_SUCCESS == dec.read_tag_header(&type, &size, &time));
EXPECT_TRUE(8 == type);
EXPECT_TRUE(8 == size);
EXPECT_TRUE(0x30 == time);
EXPECT_TRUE(ERROR_SUCCESS == dec.read_tag_data(data, size));
EXPECT_TRUE(srs_bytes_equals(audio, data, 8));
EXPECT_TRUE(ERROR_SUCCESS == dec.read_previous_tag_size(data));
EXPECT_TRUE(srs_bytes_equals(pts, data, 4));
}
VOID TEST(KernelFlvTest, FlvDecoderVideo)
{
MockSrsFileReader fs;
SrsFlvDecoder dec;
ASSERT_TRUE(ERROR_SUCCESS == fs.open(""));
ASSERT_TRUE(ERROR_SUCCESS == dec.initialize(&fs));
// 11bytes tag header
char tag_header[] = {
(char)9, // TagType UB [5], 9 = video
(char)0x00, (char)0x00, (char)0x08, // DataSize UI24 Length of the message.
(char)0x00, (char)0x00, (char)0x30, // Timestamp UI24 Time in milliseconds at which the data in this tag applies.
(char)0x00, // TimestampExtended UI8
(char)0x00, (char)0x00, (char)0x00, // StreamID UI24 Always 0.
};
char video[] = {
(char)0x01, (char)0x02, (char)0x03, (char)0x04,
(char)0x04, (char)0x03, (char)0x02, (char)0x01
};
char pts[] = { (char)0x00, (char)0x00, (char)0x00, (char)19 };
fs.mock_append_data(tag_header, 11);
fs.mock_append_data(video, 8);
fs.mock_append_data(pts, 4);
char type = 0;
int32_t size = 0;
u_int32_t time = 0;
char data[1024];
fs.mock_reset_offset();
EXPECT_TRUE(ERROR_SUCCESS == dec.read_tag_header(&type, &size, &time));
EXPECT_TRUE(9 == type);
EXPECT_TRUE(8 == size);
EXPECT_TRUE(0x30 == time);
EXPECT_TRUE(ERROR_SUCCESS == dec.read_tag_data(data, size));
EXPECT_TRUE(srs_bytes_equals(video, data, 8));
EXPECT_TRUE(ERROR_SUCCESS == dec.read_previous_tag_size(data));
EXPECT_TRUE(srs_bytes_equals(pts, data, 4));
}
VOID TEST(KernelFlvTest, FlvVSDecoderStreamClosed)
{
MockSrsFileReader fs;
SrsFlvVodStreamDecoder dec;
ASSERT_TRUE(ERROR_SUCCESS != dec.initialize(&fs));
}
VOID TEST(KernelFlvTest, FlvVSDecoderHeader)
{
MockSrsFileReader fs;
SrsFlvVodStreamDecoder dec;
ASSERT_TRUE(ERROR_SUCCESS == fs.open(""));
ASSERT_TRUE(ERROR_SUCCESS == dec.initialize(&fs));
// 9bytes
char flv_header[] = {
'F', 'L', 'V', // Signatures "FLV"
(char)0x01, // File version (for example, 0x01 for FLV version 1)
(char)0x00, // 4, audio; 1, video; 5 audio+video.
(char)0x00, (char)0x00, (char)0x00, (char)0x09 // DataOffset UI32 The length of this header in bytes
};
char pts[] = { (char)0x00, (char)0x00, (char)0x00, (char)0x00 };
fs.mock_append_data(flv_header, 9);
fs.mock_append_data(pts, 4);
char data[1024];
fs.mock_reset_offset();
EXPECT_TRUE(ERROR_SUCCESS == dec.read_header_ext(data));
EXPECT_TRUE(srs_bytes_equals(flv_header, data, 9));
}
VOID TEST(KernelFlvTest, FlvVSDecoderSequenceHeader)
{
MockSrsFileReader fs;
SrsFlvVodStreamDecoder dec;
ASSERT_TRUE(ERROR_SUCCESS == fs.open(""));
ASSERT_TRUE(ERROR_SUCCESS == dec.initialize(&fs));
if (true) {
// 11 bytes tag header
char tag_header[] = {
(char)18, // TagType UB [5], 18 = script data
(char)0x00, (char)0x00, (char)0x08, // DataSize UI24 Length of the message.
(char)0x00, (char)0x00, (char)0x00, // Timestamp UI24 Time in milliseconds at which the data in this tag applies.
(char)0x00, // TimestampExtended UI8
(char)0x00, (char)0x00, (char)0x00, // StreamID UI24 Always 0.
};
char md[] = {
(char)0x01, (char)0x02, (char)0x03, (char)0x04,
(char)0x04, (char)0x03, (char)0x02, (char)0x01
};
char pts[] = { (char)0x00, (char)0x00, (char)0x00, (char)19 };
fs.mock_append_data(tag_header, 11);
fs.mock_append_data(md, 8);
fs.mock_append_data(pts, 4);
}
if (true) {
// 11bytes tag header
char tag_header[] = {
(char)8, // TagType UB [5], 8 = audio
(char)0x00, (char)0x00, (char)0x08, // DataSize UI24 Length of the message.
(char)0x00, (char)0x00, (char)0x30, // Timestamp UI24 Time in milliseconds at which the data in this tag applies.
(char)0x00, // TimestampExtended UI8
(char)0x00, (char)0x00, (char)0x00, // StreamID UI24 Always 0.
};
char audio[] = {
(char)0x01, (char)0x02, (char)0x03, (char)0x04,
(char)0x04, (char)0x03, (char)0x02, (char)0x01
};
char pts[] = { (char)0x00, (char)0x00, (char)0x00, (char)19 };
fs.mock_append_data(tag_header, 11);
fs.mock_append_data(audio, 8);
fs.mock_append_data(pts, 4);
}
if (true) {
// 11bytes tag header
char tag_header[] = {
(char)9, // TagType UB [5], 9 = video
(char)0x00, (char)0x00, (char)0x08, // DataSize UI24 Length of the message.
(char)0x00, (char)0x00, (char)0x30, // Timestamp UI24 Time in milliseconds at which the data in this tag applies.
(char)0x00, // TimestampExtended UI8
(char)0x00, (char)0x00, (char)0x00, // StreamID UI24 Always 0.
};
char video[] = {
(char)0x01, (char)0x02, (char)0x03, (char)0x04,
(char)0x04, (char)0x03, (char)0x02, (char)0x01
};
char pts[] = { (char)0x00, (char)0x00, (char)0x00, (char)19 };
fs.mock_append_data(tag_header, 11);
fs.mock_append_data(video, 8);
fs.mock_append_data(pts, 4);
}
fs.mock_reset_offset();
int64_t start = 0;
int size = 0;
EXPECT_TRUE(ERROR_SUCCESS == dec.read_sequence_header_summary(&start, &size));
EXPECT_TRUE(23 == start);
EXPECT_TRUE(46 == size);
}
VOID TEST(KernelFlvTest, FlvVSDecoderSeek)
{
MockSrsFileReader fs;
SrsFlvVodStreamDecoder dec;
ASSERT_TRUE(ERROR_SUCCESS == fs.open(""));
ASSERT_TRUE(ERROR_SUCCESS == dec.initialize(&fs));
// 11bytes tag header
char tag_header[] = {
(char)8, // TagType UB [5], 8 = audio
(char)0x00, (char)0x00, (char)0x08, // DataSize UI24 Length of the message.
(char)0x00, (char)0x00, (char)0x30, // Timestamp UI24 Time in milliseconds at which the data in this tag applies.
(char)0x00, // TimestampExtended UI8
(char)0x00, (char)0x00, (char)0x00, // StreamID UI24 Always 0.
};
fs.mock_append_data(tag_header, 11);
EXPECT_TRUE(11 == fs.offset);
EXPECT_TRUE(ERROR_SUCCESS == dec.lseek(0));
EXPECT_TRUE(0 == fs.offset);
EXPECT_TRUE(ERROR_SUCCESS == dec.lseek(5));
EXPECT_TRUE(5 == fs.offset);
}
... ...
... ... @@ -35,6 +35,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
class MockSrsFileWriter : public SrsFileWriter
{
public:
char* data;
int offset;
public:
MockSrsFileWriter();
virtual ~MockSrsFileWriter();
public:
... ... @@ -45,11 +48,18 @@ public:
virtual int64_t tellg();
public:
virtual int write(void* buf, size_t count, ssize_t* pnwrite);
// for mock
public:
void mock_reset_offset();
};
class MockSrsFileReader : public SrsFileReader
{
public:
char* data;
int size;
int offset;
public:
MockSrsFileReader();
virtual ~MockSrsFileReader();
public:
... ... @@ -63,6 +73,11 @@ public:
virtual int64_t filesize();
public:
virtual int read(void* buf, size_t count, ssize_t* pnread);
// for mock
public:
// append data to current offset, modify the offset and size.
void mock_append_data(const char* _data, int _size);
void mock_reset_offset();
};
#endif
... ...