mirror of
https://github.com/ossrs/srs.git
synced 2025-02-13 11:51:57 +00:00
complete the normal kernel flv utest. 0.9.147
This commit is contained in:
parent
010eb09a30
commit
d219a7b67e
11 changed files with 691 additions and 172 deletions
|
@ -312,14 +312,12 @@ int SrsHttpVhost::response_flv_file2(SrsSocket* skt, SrsHttpMessage* req, string
|
||||||
}
|
}
|
||||||
|
|
||||||
// save header, send later.
|
// save header, send later.
|
||||||
char* flv_header = NULL;
|
char flv_header[13];
|
||||||
int flv_size = 0;
|
|
||||||
|
|
||||||
// send flv header
|
// 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;
|
return ret;
|
||||||
}
|
}
|
||||||
SrsAutoFree(char, flv_header);
|
|
||||||
|
|
||||||
// save sequence header, send later
|
// save sequence header, send later
|
||||||
char* sh_data = NULL;
|
char* sh_data = NULL;
|
||||||
|
@ -328,7 +326,7 @@ int SrsHttpVhost::response_flv_file2(SrsSocket* skt, SrsHttpMessage* req, string
|
||||||
if (true) {
|
if (true) {
|
||||||
// send sequence header
|
// send sequence header
|
||||||
int64_t start = 0;
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
if (sh_size <= 0) {
|
if (sh_size <= 0) {
|
||||||
|
@ -350,7 +348,7 @@ int SrsHttpVhost::response_flv_file2(SrsSocket* skt, SrsHttpMessage* req, string
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
|
|
||||||
res_status_line(ss)->res_content_type_flv(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()) {
|
if (req->requires_crossdomain()) {
|
||||||
res_enable_crossdomain(ss);
|
res_enable_crossdomain(ss);
|
||||||
|
@ -363,7 +361,7 @@ int SrsHttpVhost::response_flv_file2(SrsSocket* skt, SrsHttpMessage* req, string
|
||||||
return ret;
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
if (sh_size > 0 && (ret = skt->write(sh_data, sh_size, NULL)) != ERROR_SUCCESS) {
|
if (sh_size > 0 && (ret = skt->write(sh_data, sh_size, NULL)) != ERROR_SUCCESS) {
|
||||||
|
|
198
trunk/src/core/srs_core.hpp
Executable file → Normal file
198
trunk/src/core/srs_core.hpp
Executable file → Normal file
|
@ -1,99 +1,99 @@
|
||||||
/*
|
/*
|
||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright (c) 2013-2014 winlin
|
Copyright (c) 2013-2014 winlin
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
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
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
the Software without restriction, including without limitation the rights to
|
the Software without restriction, including without limitation the rights to
|
||||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
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,
|
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
subject to the following conditions:
|
subject to the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
The above copyright notice and this permission notice shall be included in all
|
||||||
copies or substantial portions of the Software.
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
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
|
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
|
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.
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef SRS_CORE_HPP
|
#ifndef SRS_CORE_HPP
|
||||||
#define SRS_CORE_HPP
|
#define SRS_CORE_HPP
|
||||||
|
|
||||||
/*
|
/*
|
||||||
#include <srs_core.hpp>
|
#include <srs_core.hpp>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// current release version
|
// current release version
|
||||||
#define VERSION_MAJOR "0"
|
#define VERSION_MAJOR "0"
|
||||||
#define VERSION_MINOR "9"
|
#define VERSION_MINOR "9"
|
||||||
#define VERSION_REVISION "146"
|
#define VERSION_REVISION "147"
|
||||||
#define RTMP_SIG_SRS_VERSION VERSION_MAJOR"."VERSION_MINOR"."VERSION_REVISION
|
#define RTMP_SIG_SRS_VERSION VERSION_MAJOR"."VERSION_MINOR"."VERSION_REVISION
|
||||||
// server info.
|
// server info.
|
||||||
#define RTMP_SIG_SRS_KEY "SRS"
|
#define RTMP_SIG_SRS_KEY "SRS"
|
||||||
#define RTMP_SIG_SRS_ROLE "origin/edge server"
|
#define RTMP_SIG_SRS_ROLE "origin/edge server"
|
||||||
#define RTMP_SIG_SRS_NAME RTMP_SIG_SRS_KEY"(Simple RTMP 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_SHORT "github.com/winlinvip/simple-rtmp-server"
|
||||||
#define RTMP_SIG_SRS_URL "https://"RTMP_SIG_SRS_URL_SHORT
|
#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_WEB "http://blog.csdn.net/win_lin"
|
||||||
#define RTMP_SIG_SRS_EMAIL "winlin@vip.126.com"
|
#define RTMP_SIG_SRS_EMAIL "winlin@vip.126.com"
|
||||||
#define RTMP_SIG_SRS_LICENSE "The MIT License (MIT)"
|
#define RTMP_SIG_SRS_LICENSE "The MIT License (MIT)"
|
||||||
#define RTMP_SIG_SRS_COPYRIGHT "Copyright (c) 2013-2014 winlin"
|
#define RTMP_SIG_SRS_COPYRIGHT "Copyright (c) 2013-2014 winlin"
|
||||||
#define RTMP_SIG_SRS_PRIMARY_AUTHROS "winlin,wenjie.zhao"
|
#define RTMP_SIG_SRS_PRIMARY_AUTHROS "winlin,wenjie.zhao"
|
||||||
#define RTMP_SIG_SRS_CONTRIBUTORS_URL RTMP_SIG_SRS_URL"/blob/master/AUTHORS.txt"
|
#define RTMP_SIG_SRS_CONTRIBUTORS_URL RTMP_SIG_SRS_URL"/blob/master/AUTHORS.txt"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the core provides the common defined macros, utilities,
|
* the core provides the common defined macros, utilities,
|
||||||
* user must include the srs_core.hpp before any header, or maybe
|
* user must include the srs_core.hpp before any header, or maybe
|
||||||
* build failed.
|
* build failed.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// for 32bit os, 2G big file limit for unistd io,
|
// for 32bit os, 2G big file limit for unistd io,
|
||||||
// ie. read/write/lseek to use 64bits size for huge file.
|
// ie. read/write/lseek to use 64bits size for huge file.
|
||||||
#ifndef _FILE_OFFSET_BITS
|
#ifndef _FILE_OFFSET_BITS
|
||||||
#define _FILE_OFFSET_BITS 64
|
#define _FILE_OFFSET_BITS 64
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// for int64_t print using PRId64 format.
|
// for int64_t print using PRId64 format.
|
||||||
#ifndef __STDC_FORMAT_MACROS
|
#ifndef __STDC_FORMAT_MACROS
|
||||||
#define __STDC_FORMAT_MACROS
|
#define __STDC_FORMAT_MACROS
|
||||||
#endif
|
#endif
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#define srs_assert(expression) assert(expression)
|
#define srs_assert(expression) assert(expression)
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
// generated by configure.
|
// generated by configure.
|
||||||
#include <srs_auto_headers.hpp>
|
#include <srs_auto_headers.hpp>
|
||||||
|
|
||||||
// free the p and set to NULL.
|
// free the p and set to NULL.
|
||||||
// p must be a T*.
|
// p must be a T*.
|
||||||
#define srs_freep(p) \
|
#define srs_freep(p) \
|
||||||
if (p) { \
|
if (p) { \
|
||||||
delete p; \
|
delete p; \
|
||||||
p = NULL; \
|
p = NULL; \
|
||||||
} \
|
} \
|
||||||
(void)0
|
(void)0
|
||||||
// sometimes, the freepa is useless,
|
// sometimes, the freepa is useless,
|
||||||
// it's recomments to free each elem explicit.
|
// it's recomments to free each elem explicit.
|
||||||
// so we remove the srs_freepa utility.
|
// so we remove the srs_freepa utility.
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* disable copy constructor of class
|
* disable copy constructor of class
|
||||||
*/
|
*/
|
||||||
#define disable_default_copy(className)\
|
#define disable_default_copy(className)\
|
||||||
private:\
|
private:\
|
||||||
/** \
|
/** \
|
||||||
* disable the copy constructor and operator=, donot allow directly copy. \
|
* disable the copy constructor and operator=, donot allow directly copy. \
|
||||||
*/ \
|
*/ \
|
||||||
className(const className&); \
|
className(const className&); \
|
||||||
className& operator= (const className&)
|
className& operator= (const className&)
|
||||||
|
|
||||||
#endif
|
#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_FILE_RENAME 429
|
||||||
#define ERROR_SYSTEM_CREATE_PIPE 430
|
#define ERROR_SYSTEM_CREATE_PIPE 430
|
||||||
#define ERROR_SYSTEM_FILE_SEEK 431
|
#define ERROR_SYSTEM_FILE_SEEK 431
|
||||||
#define ERROR_SYSTEM_FLV_HEADER 432
|
#define ERROR_SYSTEM_IO_INVALID 432
|
||||||
#define ERROR_SYSTEM_IO_INVALID 433
|
|
||||||
|
|
||||||
// see librtmp.
|
// see librtmp.
|
||||||
// failed when open ssl create the dh
|
// 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_SEQUENCE_HEADER 806
|
||||||
#define ERROR_HTTP_FLV_OFFSET_OVERFLOW 807
|
#define ERROR_HTTP_FLV_OFFSET_OVERFLOW 807
|
||||||
|
|
||||||
|
#define ERROR_KERNEL_FLV_HEADER 900
|
||||||
|
#define ERROR_KERNEL_FLV_STREAM_CLOSED 901
|
||||||
|
|
||||||
// system control message,
|
// system control message,
|
||||||
// not an error, but special control logic.
|
// not an error, but special control logic.
|
||||||
// sys ctl: rtmp close stream, support replay.
|
// sys ctl: rtmp close stream, support replay.
|
||||||
#define ERROR_CONTROL_RTMP_CLOSE 900
|
#define ERROR_CONTROL_RTMP_CLOSE 2000
|
||||||
// FMLE stop publish and republish.
|
// FMLE stop publish and republish.
|
||||||
#define ERROR_CONTROL_REPUBLISH 901
|
#define ERROR_CONTROL_REPUBLISH 2001
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* whether the error code is an system control error.
|
* whether the error code is an system control error.
|
||||||
|
|
|
@ -53,6 +53,12 @@ int SrsFlvEncoder::initialize(SrsFileWriter* fs)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
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;
|
_fs = fs;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -92,7 +98,7 @@ int SrsFlvEncoder::write_header(char flv_header[9])
|
||||||
return ret;
|
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) {
|
if ((ret = _fs->write(pts, 4, NULL)) != ERROR_SUCCESS) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -104,6 +110,7 @@ int SrsFlvEncoder::write_metadata(char* data, int size)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
// 11 bytes tag header
|
||||||
static char tag_header[] = {
|
static char tag_header[] = {
|
||||||
(char)18, // TagType UB [5], 18 = script data
|
(char)18, // TagType UB [5], 18 = script data
|
||||||
(char)0x00, (char)0x00, (char)0x00, // DataSize UI24 Length of the message.
|
(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;
|
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;
|
_fs = fs;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -255,7 +268,7 @@ int SrsFlvDecoder::read_header(char header[9])
|
||||||
|
|
||||||
char* h = header;
|
char* h = header;
|
||||||
if (h[0] != 'F' || h[1] != 'L' || h[2] != 'V') {
|
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);
|
srs_warn("flv header must start with FLV. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -345,35 +358,37 @@ int SrsFlvVodStreamDecoder::initialize(SrsFileReader* fs)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
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;
|
_fs = fs;
|
||||||
|
|
||||||
return ret;
|
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;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
srs_assert(_fs);
|
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
|
// 9bytes header and 4bytes first previous-tag-size
|
||||||
int size = 13;
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
*pdata = buf;
|
|
||||||
*psize = size;
|
|
||||||
|
|
||||||
return ret;
|
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;
|
*pstart = 0;
|
||||||
*psize = 0;
|
*psize = 0;
|
||||||
|
|
|
@ -66,7 +66,7 @@ public:
|
||||||
virtual int write_header(char flv_header[9]);
|
virtual int write_header(char flv_header[9]);
|
||||||
/**
|
/**
|
||||||
* write flv metadata.
|
* write flv metadata.
|
||||||
* serialize from:
|
* @param data, the amf0 metadata which serialize from:
|
||||||
* AMF0 string: onMetaData,
|
* AMF0 string: onMetaData,
|
||||||
* AMF0 object: the metadata object.
|
* AMF0 object: the metadata object.
|
||||||
*/
|
*/
|
||||||
|
@ -76,6 +76,7 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual int write_audio(int64_t timestamp, char* data, int size);
|
virtual int write_audio(int64_t timestamp, char* data, int size);
|
||||||
virtual int write_video(int64_t timestamp, char* data, int size);
|
virtual int write_video(int64_t timestamp, char* data, int size);
|
||||||
|
public:
|
||||||
/**
|
/**
|
||||||
* get the tag size,
|
* get the tag size,
|
||||||
* including the tag header, body, and 4bytes previous tag size.
|
* including the tag header, body, and 4bytes previous tag size.
|
||||||
|
@ -134,13 +135,17 @@ public:
|
||||||
virtual int initialize(SrsFileReader* fs);
|
virtual int initialize(SrsFileReader* fs);
|
||||||
public:
|
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:
|
public:
|
||||||
/**
|
/**
|
||||||
* for start offset, seed to this position and response flv stream.
|
* for start offset, seed to this position and response flv stream.
|
||||||
|
|
|
@ -557,31 +557,6 @@ namespace srs
|
||||||
return bytes;
|
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()
|
c2s2::c2s2()
|
||||||
{
|
{
|
||||||
srs_random_generate(random, 1504);
|
srs_random_generate(random, 1504);
|
||||||
|
|
|
@ -167,11 +167,6 @@ namespace srs
|
||||||
*/
|
*/
|
||||||
char* srs_bytes_join_schema1(int32_t time, int32_t version, digest_block* digest, key_block* key);
|
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
|
* c1s1 schema0
|
||||||
* time: 4bytes
|
* time: 4bytes
|
||||||
|
|
|
@ -126,3 +126,28 @@ string srs_generate_tc_url(string ip, string vhost, string app, string port)
|
||||||
|
|
||||||
return tcUrl;
|
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.
|
// generate the tcUrl.
|
||||||
extern std::string srs_generate_tc_url(std::string ip, std::string vhost, std::string app, std::string port);
|
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
|
#endif
|
||||||
|
|
|
@ -27,93 +27,155 @@ using namespace std;
|
||||||
#include <srs_kernel_error.hpp>
|
#include <srs_kernel_error.hpp>
|
||||||
#include <srs_kernel_codec.hpp>
|
#include <srs_kernel_codec.hpp>
|
||||||
#include <srs_kernel_flv.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()
|
MockSrsFileWriter::MockSrsFileWriter()
|
||||||
{
|
{
|
||||||
|
data = new char[MAX_MOCK_DATA_SIZE];
|
||||||
|
offset = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
MockSrsFileWriter::~MockSrsFileWriter()
|
MockSrsFileWriter::~MockSrsFileWriter()
|
||||||
{
|
{
|
||||||
|
srs_freep(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
int MockSrsFileWriter::open(string file)
|
int MockSrsFileWriter::open(string /*file*/)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
offset = 0;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MockSrsFileWriter::close()
|
void MockSrsFileWriter::close()
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
offset = 0;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MockSrsFileWriter::is_open()
|
bool MockSrsFileWriter::is_open()
|
||||||
{
|
{
|
||||||
return true;
|
return offset >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t MockSrsFileWriter::tellg()
|
int64_t MockSrsFileWriter::tellg()
|
||||||
{
|
{
|
||||||
return 0;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
int MockSrsFileWriter::write(void* buf, size_t count, ssize_t* pnwrite)
|
int MockSrsFileWriter::write(void* buf, size_t count, ssize_t* pnwrite)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MockSrsFileWriter::mock_reset_offset()
|
||||||
|
{
|
||||||
|
offset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
MockSrsFileReader::MockSrsFileReader()
|
MockSrsFileReader::MockSrsFileReader()
|
||||||
{
|
{
|
||||||
|
data = new char[MAX_MOCK_DATA_SIZE];
|
||||||
|
size = 0;
|
||||||
|
offset = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
MockSrsFileReader::~MockSrsFileReader()
|
MockSrsFileReader::~MockSrsFileReader()
|
||||||
{
|
{
|
||||||
|
srs_freep(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
int MockSrsFileReader::open(string file)
|
int MockSrsFileReader::open(string /*file*/)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
offset = 0;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MockSrsFileReader::close()
|
void MockSrsFileReader::close()
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
offset = 0;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MockSrsFileReader::is_open()
|
bool MockSrsFileReader::is_open()
|
||||||
{
|
{
|
||||||
return true;
|
return offset >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t MockSrsFileReader::tellg()
|
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;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t MockSrsFileReader::filesize()
|
int64_t MockSrsFileReader::filesize()
|
||||||
{
|
{
|
||||||
return 0;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
int MockSrsFileReader::read(void* buf, size_t count, ssize_t* pnread)
|
int MockSrsFileReader::read(void* buf, size_t count, ssize_t* pnread)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
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;
|
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)
|
VOID TEST(KernelCodecTest, IsKeyFrame)
|
||||||
{
|
{
|
||||||
int8_t data;
|
int8_t data;
|
||||||
|
@ -196,9 +258,431 @@ VOID TEST(KernelCodecTest, IsAudioSequenceHeader)
|
||||||
EXPECT_FALSE(SrsFlvCodec::video_is_sequence_header((int8_t*)pp, 2));
|
EXPECT_FALSE(SrsFlvCodec::video_is_sequence_header((int8_t*)pp, 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID TEST(KernelFlvTest, IsAudioSequenceHeader)
|
VOID TEST(KernelFlvTest, FlvEncoderStreamClosed)
|
||||||
{
|
{
|
||||||
MockSrsFileWriter fs;
|
MockSrsFileWriter fs;
|
||||||
SrsFlvEncoder enc;
|
SrsFlvEncoder enc;
|
||||||
ASSERT_TRUE(ERROR_SUCCESS == enc.initialize(&fs));
|
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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
class MockSrsFileWriter : public SrsFileWriter
|
class MockSrsFileWriter : public SrsFileWriter
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
char* data;
|
||||||
|
int offset;
|
||||||
public:
|
public:
|
||||||
MockSrsFileWriter();
|
MockSrsFileWriter();
|
||||||
virtual ~MockSrsFileWriter();
|
virtual ~MockSrsFileWriter();
|
||||||
|
@ -45,10 +48,17 @@ public:
|
||||||
virtual int64_t tellg();
|
virtual int64_t tellg();
|
||||||
public:
|
public:
|
||||||
virtual int write(void* buf, size_t count, ssize_t* pnwrite);
|
virtual int write(void* buf, size_t count, ssize_t* pnwrite);
|
||||||
|
// for mock
|
||||||
|
public:
|
||||||
|
void mock_reset_offset();
|
||||||
};
|
};
|
||||||
|
|
||||||
class MockSrsFileReader : public SrsFileReader
|
class MockSrsFileReader : public SrsFileReader
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
char* data;
|
||||||
|
int size;
|
||||||
|
int offset;
|
||||||
public:
|
public:
|
||||||
MockSrsFileReader();
|
MockSrsFileReader();
|
||||||
virtual ~MockSrsFileReader();
|
virtual ~MockSrsFileReader();
|
||||||
|
@ -63,6 +73,11 @@ public:
|
||||||
virtual int64_t filesize();
|
virtual int64_t filesize();
|
||||||
public:
|
public:
|
||||||
virtual int read(void* buf, size_t count, ssize_t* pnread);
|
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
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue