正在显示
11 个修改的文件
包含
690 行增加
和
171 行删除
| @@ -312,14 +312,12 @@ int SrsHttpVhost::response_flv_file2(SrsSocket* skt, SrsHttpMessage* req, string | @@ -312,14 +312,12 @@ int SrsHttpVhost::response_flv_file2(SrsSocket* skt, SrsHttpMessage* req, string | ||
| 312 | } | 312 | } |
| 313 | 313 | ||
| 314 | // save header, send later. | 314 | // save header, send later. |
| 315 | - char* flv_header = NULL; | ||
| 316 | - int flv_size = 0; | 315 | + char flv_header[13]; |
| 317 | 316 | ||
| 318 | // send flv header | 317 | // send flv header |
| 319 | - if ((ret = ffd.read_header(&flv_header, &flv_size)) != ERROR_SUCCESS) { | 318 | + if ((ret = ffd.read_header_ext(flv_header)) != ERROR_SUCCESS) { |
| 320 | return ret; | 319 | return ret; |
| 321 | } | 320 | } |
| 322 | - SrsAutoFree(char, flv_header); | ||
| 323 | 321 | ||
| 324 | // save sequence header, send later | 322 | // save sequence header, send later |
| 325 | char* sh_data = NULL; | 323 | char* sh_data = NULL; |
| @@ -328,7 +326,7 @@ int SrsHttpVhost::response_flv_file2(SrsSocket* skt, SrsHttpMessage* req, string | @@ -328,7 +326,7 @@ int SrsHttpVhost::response_flv_file2(SrsSocket* skt, SrsHttpMessage* req, string | ||
| 328 | if (true) { | 326 | if (true) { |
| 329 | // send sequence header | 327 | // send sequence header |
| 330 | int64_t start = 0; | 328 | int64_t start = 0; |
| 331 | - if ((ret = ffd.read_sequence_header(&start, &sh_size)) != ERROR_SUCCESS) { | 329 | + if ((ret = ffd.read_sequence_header_summary(&start, &sh_size)) != ERROR_SUCCESS) { |
| 332 | return ret; | 330 | return ret; |
| 333 | } | 331 | } |
| 334 | if (sh_size <= 0) { | 332 | if (sh_size <= 0) { |
| @@ -350,7 +348,7 @@ int SrsHttpVhost::response_flv_file2(SrsSocket* skt, SrsHttpMessage* req, string | @@ -350,7 +348,7 @@ int SrsHttpVhost::response_flv_file2(SrsSocket* skt, SrsHttpMessage* req, string | ||
| 350 | std::stringstream ss; | 348 | std::stringstream ss; |
| 351 | 349 | ||
| 352 | res_status_line(ss)->res_content_type_flv(ss) | 350 | res_status_line(ss)->res_content_type_flv(ss) |
| 353 | - ->res_content_length(ss, (int)(flv_size + sh_size + left)); | 351 | + ->res_content_length(ss, (int)(sizeof(flv_header) + sh_size + left)); |
| 354 | 352 | ||
| 355 | if (req->requires_crossdomain()) { | 353 | if (req->requires_crossdomain()) { |
| 356 | res_enable_crossdomain(ss); | 354 | res_enable_crossdomain(ss); |
| @@ -363,7 +361,7 @@ int SrsHttpVhost::response_flv_file2(SrsSocket* skt, SrsHttpMessage* req, string | @@ -363,7 +361,7 @@ int SrsHttpVhost::response_flv_file2(SrsSocket* skt, SrsHttpMessage* req, string | ||
| 363 | return ret; | 361 | return ret; |
| 364 | } | 362 | } |
| 365 | 363 | ||
| 366 | - if (flv_size > 0 && (ret = skt->write(flv_header, flv_size, NULL)) != ERROR_SUCCESS) { | 364 | + if ((ret = skt->write(flv_header, sizeof(flv_header), NULL)) != ERROR_SUCCESS) { |
| 367 | return ret; | 365 | return ret; |
| 368 | } | 366 | } |
| 369 | if (sh_size > 0 && (ret = skt->write(sh_data, sh_size, NULL)) != ERROR_SUCCESS) { | 367 | if (sh_size > 0 && (ret = skt->write(sh_data, sh_size, NULL)) != ERROR_SUCCESS) { |
trunk/src/core/srs_core.hpp
100755 → 100644
| 1 | -/* | ||
| 2 | -The MIT License (MIT) | ||
| 3 | - | ||
| 4 | -Copyright (c) 2013-2014 winlin | ||
| 5 | - | ||
| 6 | -Permission is hereby granted, free of charge, to any person obtaining a copy of | ||
| 7 | -this software and associated documentation files (the "Software"), to deal in | ||
| 8 | -the Software without restriction, including without limitation the rights to | ||
| 9 | -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of | ||
| 10 | -the Software, and to permit persons to whom the Software is furnished to do so, | ||
| 11 | -subject to the following conditions: | ||
| 12 | - | ||
| 13 | -The above copyright notice and this permission notice shall be included in all | ||
| 14 | -copies or substantial portions of the Software. | ||
| 15 | - | ||
| 16 | -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 17 | -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS | ||
| 18 | -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR | ||
| 19 | -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER | ||
| 20 | -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
| 21 | -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 22 | -*/ | ||
| 23 | - | ||
| 24 | -#ifndef SRS_CORE_HPP | ||
| 25 | -#define SRS_CORE_HPP | ||
| 26 | - | ||
| 27 | -/* | ||
| 28 | -#include <srs_core.hpp> | ||
| 29 | -*/ | ||
| 30 | - | ||
| 31 | -// current release version | ||
| 32 | -#define VERSION_MAJOR "0" | ||
| 33 | -#define VERSION_MINOR "9" | ||
| 34 | -#define VERSION_REVISION "146" | ||
| 35 | -#define RTMP_SIG_SRS_VERSION VERSION_MAJOR"."VERSION_MINOR"."VERSION_REVISION | ||
| 36 | -// server info. | ||
| 37 | -#define RTMP_SIG_SRS_KEY "SRS" | ||
| 38 | -#define RTMP_SIG_SRS_ROLE "origin/edge server" | ||
| 39 | -#define RTMP_SIG_SRS_NAME RTMP_SIG_SRS_KEY"(Simple RTMP Server)" | ||
| 40 | -#define RTMP_SIG_SRS_URL_SHORT "github.com/winlinvip/simple-rtmp-server" | ||
| 41 | -#define RTMP_SIG_SRS_URL "https://"RTMP_SIG_SRS_URL_SHORT | ||
| 42 | -#define RTMP_SIG_SRS_WEB "http://blog.csdn.net/win_lin" | ||
| 43 | -#define RTMP_SIG_SRS_EMAIL "winlin@vip.126.com" | ||
| 44 | -#define RTMP_SIG_SRS_LICENSE "The MIT License (MIT)" | ||
| 45 | -#define RTMP_SIG_SRS_COPYRIGHT "Copyright (c) 2013-2014 winlin" | ||
| 46 | -#define RTMP_SIG_SRS_PRIMARY_AUTHROS "winlin,wenjie.zhao" | ||
| 47 | -#define RTMP_SIG_SRS_CONTRIBUTORS_URL RTMP_SIG_SRS_URL"/blob/master/AUTHORS.txt" | ||
| 48 | - | ||
| 49 | -/** | ||
| 50 | -* the core provides the common defined macros, utilities, | ||
| 51 | -* user must include the srs_core.hpp before any header, or maybe | ||
| 52 | -* build failed. | ||
| 53 | -*/ | ||
| 54 | - | ||
| 55 | -// for 32bit os, 2G big file limit for unistd io, | ||
| 56 | -// ie. read/write/lseek to use 64bits size for huge file. | ||
| 57 | -#ifndef _FILE_OFFSET_BITS | ||
| 58 | - #define _FILE_OFFSET_BITS 64 | ||
| 59 | -#endif | ||
| 60 | - | ||
| 61 | -// for int64_t print using PRId64 format. | ||
| 62 | -#ifndef __STDC_FORMAT_MACROS | ||
| 63 | - #define __STDC_FORMAT_MACROS | ||
| 64 | -#endif | ||
| 65 | -#include <inttypes.h> | ||
| 66 | - | ||
| 67 | -#include <assert.h> | ||
| 68 | -#define srs_assert(expression) assert(expression) | ||
| 69 | - | ||
| 70 | -#include <stddef.h> | ||
| 71 | -#include <sys/types.h> | ||
| 72 | - | ||
| 73 | -// generated by configure. | ||
| 74 | -#include <srs_auto_headers.hpp> | ||
| 75 | - | ||
| 76 | -// free the p and set to NULL. | ||
| 77 | -// p must be a T*. | ||
| 78 | -#define srs_freep(p) \ | ||
| 79 | - if (p) { \ | ||
| 80 | - delete p; \ | ||
| 81 | - p = NULL; \ | ||
| 82 | - } \ | ||
| 83 | - (void)0 | ||
| 84 | -// sometimes, the freepa is useless, | ||
| 85 | -// it's recomments to free each elem explicit. | ||
| 86 | -// so we remove the srs_freepa utility. | ||
| 87 | - | ||
| 88 | -/** | ||
| 89 | -* disable copy constructor of class | ||
| 90 | -*/ | ||
| 91 | -#define disable_default_copy(className)\ | ||
| 92 | - private:\ | ||
| 93 | - /** \ | ||
| 94 | - * disable the copy constructor and operator=, donot allow directly copy. \ | ||
| 95 | - */ \ | ||
| 96 | - className(const className&); \ | ||
| 97 | - className& operator= (const className&) | ||
| 98 | - | ||
| 99 | -#endif | 1 | +/* |
| 2 | +The MIT License (MIT) | ||
| 3 | + | ||
| 4 | +Copyright (c) 2013-2014 winlin | ||
| 5 | + | ||
| 6 | +Permission is hereby granted, free of charge, to any person obtaining a copy of | ||
| 7 | +this software and associated documentation files (the "Software"), to deal in | ||
| 8 | +the Software without restriction, including without limitation the rights to | ||
| 9 | +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of | ||
| 10 | +the Software, and to permit persons to whom the Software is furnished to do so, | ||
| 11 | +subject to the following conditions: | ||
| 12 | + | ||
| 13 | +The above copyright notice and this permission notice shall be included in all | ||
| 14 | +copies or substantial portions of the Software. | ||
| 15 | + | ||
| 16 | +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 17 | +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS | ||
| 18 | +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR | ||
| 19 | +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER | ||
| 20 | +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
| 21 | +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 22 | +*/ | ||
| 23 | + | ||
| 24 | +#ifndef SRS_CORE_HPP | ||
| 25 | +#define SRS_CORE_HPP | ||
| 26 | + | ||
| 27 | +/* | ||
| 28 | +#include <srs_core.hpp> | ||
| 29 | +*/ | ||
| 30 | + | ||
| 31 | +// current release version | ||
| 32 | +#define VERSION_MAJOR "0" | ||
| 33 | +#define VERSION_MINOR "9" | ||
| 34 | +#define VERSION_REVISION "147" | ||
| 35 | +#define RTMP_SIG_SRS_VERSION VERSION_MAJOR"."VERSION_MINOR"."VERSION_REVISION | ||
| 36 | +// server info. | ||
| 37 | +#define RTMP_SIG_SRS_KEY "SRS" | ||
| 38 | +#define RTMP_SIG_SRS_ROLE "origin/edge server" | ||
| 39 | +#define RTMP_SIG_SRS_NAME RTMP_SIG_SRS_KEY"(Simple RTMP Server)" | ||
| 40 | +#define RTMP_SIG_SRS_URL_SHORT "github.com/winlinvip/simple-rtmp-server" | ||
| 41 | +#define RTMP_SIG_SRS_URL "https://"RTMP_SIG_SRS_URL_SHORT | ||
| 42 | +#define RTMP_SIG_SRS_WEB "http://blog.csdn.net/win_lin" | ||
| 43 | +#define RTMP_SIG_SRS_EMAIL "winlin@vip.126.com" | ||
| 44 | +#define RTMP_SIG_SRS_LICENSE "The MIT License (MIT)" | ||
| 45 | +#define RTMP_SIG_SRS_COPYRIGHT "Copyright (c) 2013-2014 winlin" | ||
| 46 | +#define RTMP_SIG_SRS_PRIMARY_AUTHROS "winlin,wenjie.zhao" | ||
| 47 | +#define RTMP_SIG_SRS_CONTRIBUTORS_URL RTMP_SIG_SRS_URL"/blob/master/AUTHORS.txt" | ||
| 48 | + | ||
| 49 | +/** | ||
| 50 | +* the core provides the common defined macros, utilities, | ||
| 51 | +* user must include the srs_core.hpp before any header, or maybe | ||
| 52 | +* build failed. | ||
| 53 | +*/ | ||
| 54 | + | ||
| 55 | +// for 32bit os, 2G big file limit for unistd io, | ||
| 56 | +// ie. read/write/lseek to use 64bits size for huge file. | ||
| 57 | +#ifndef _FILE_OFFSET_BITS | ||
| 58 | + #define _FILE_OFFSET_BITS 64 | ||
| 59 | +#endif | ||
| 60 | + | ||
| 61 | +// for int64_t print using PRId64 format. | ||
| 62 | +#ifndef __STDC_FORMAT_MACROS | ||
| 63 | + #define __STDC_FORMAT_MACROS | ||
| 64 | +#endif | ||
| 65 | +#include <inttypes.h> | ||
| 66 | + | ||
| 67 | +#include <assert.h> | ||
| 68 | +#define srs_assert(expression) assert(expression) | ||
| 69 | + | ||
| 70 | +#include <stddef.h> | ||
| 71 | +#include <sys/types.h> | ||
| 72 | + | ||
| 73 | +// generated by configure. | ||
| 74 | +#include <srs_auto_headers.hpp> | ||
| 75 | + | ||
| 76 | +// free the p and set to NULL. | ||
| 77 | +// p must be a T*. | ||
| 78 | +#define srs_freep(p) \ | ||
| 79 | + if (p) { \ | ||
| 80 | + delete p; \ | ||
| 81 | + p = NULL; \ | ||
| 82 | + } \ | ||
| 83 | + (void)0 | ||
| 84 | +// sometimes, the freepa is useless, | ||
| 85 | +// it's recomments to free each elem explicit. | ||
| 86 | +// so we remove the srs_freepa utility. | ||
| 87 | + | ||
| 88 | +/** | ||
| 89 | +* disable copy constructor of class | ||
| 90 | +*/ | ||
| 91 | +#define disable_default_copy(className)\ | ||
| 92 | + private:\ | ||
| 93 | + /** \ | ||
| 94 | + * disable the copy constructor and operator=, donot allow directly copy. \ | ||
| 95 | + */ \ | ||
| 96 | + className(const className&); \ | ||
| 97 | + className& operator= (const className&) | ||
| 98 | + | ||
| 99 | +#endif |
| @@ -119,8 +119,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -119,8 +119,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 119 | #define ERROR_SYSTEM_FILE_RENAME 429 | 119 | #define ERROR_SYSTEM_FILE_RENAME 429 |
| 120 | #define ERROR_SYSTEM_CREATE_PIPE 430 | 120 | #define ERROR_SYSTEM_CREATE_PIPE 430 |
| 121 | #define ERROR_SYSTEM_FILE_SEEK 431 | 121 | #define ERROR_SYSTEM_FILE_SEEK 431 |
| 122 | -#define ERROR_SYSTEM_FLV_HEADER 432 | ||
| 123 | -#define ERROR_SYSTEM_IO_INVALID 433 | 122 | +#define ERROR_SYSTEM_IO_INVALID 432 |
| 124 | 123 | ||
| 125 | // see librtmp. | 124 | // see librtmp. |
| 126 | // failed when open ssl create the dh | 125 | // failed when open ssl create the dh |
| @@ -189,12 +188,15 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -189,12 +188,15 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 189 | #define ERROR_HTTP_FLV_SEQUENCE_HEADER 806 | 188 | #define ERROR_HTTP_FLV_SEQUENCE_HEADER 806 |
| 190 | #define ERROR_HTTP_FLV_OFFSET_OVERFLOW 807 | 189 | #define ERROR_HTTP_FLV_OFFSET_OVERFLOW 807 |
| 191 | 190 | ||
| 191 | +#define ERROR_KERNEL_FLV_HEADER 900 | ||
| 192 | +#define ERROR_KERNEL_FLV_STREAM_CLOSED 901 | ||
| 193 | + | ||
| 192 | // system control message, | 194 | // system control message, |
| 193 | // not an error, but special control logic. | 195 | // not an error, but special control logic. |
| 194 | // sys ctl: rtmp close stream, support replay. | 196 | // sys ctl: rtmp close stream, support replay. |
| 195 | -#define ERROR_CONTROL_RTMP_CLOSE 900 | 197 | +#define ERROR_CONTROL_RTMP_CLOSE 2000 |
| 196 | // FMLE stop publish and republish. | 198 | // FMLE stop publish and republish. |
| 197 | -#define ERROR_CONTROL_REPUBLISH 901 | 199 | +#define ERROR_CONTROL_REPUBLISH 2001 |
| 198 | 200 | ||
| 199 | /** | 201 | /** |
| 200 | * whether the error code is an system control error. | 202 | * whether the error code is an system control error. |
| @@ -53,6 +53,12 @@ int SrsFlvEncoder::initialize(SrsFileWriter* fs) | @@ -53,6 +53,12 @@ int SrsFlvEncoder::initialize(SrsFileWriter* fs) | ||
| 53 | { | 53 | { |
| 54 | int ret = ERROR_SUCCESS; | 54 | int ret = ERROR_SUCCESS; |
| 55 | 55 | ||
| 56 | + if (!fs->is_open()) { | ||
| 57 | + ret = ERROR_KERNEL_FLV_STREAM_CLOSED; | ||
| 58 | + srs_warn("stream is not open for decoder. ret=%d", ret); | ||
| 59 | + return ret; | ||
| 60 | + } | ||
| 61 | + | ||
| 56 | _fs = fs; | 62 | _fs = fs; |
| 57 | 63 | ||
| 58 | return ret; | 64 | return ret; |
| @@ -92,7 +98,7 @@ int SrsFlvEncoder::write_header(char flv_header[9]) | @@ -92,7 +98,7 @@ int SrsFlvEncoder::write_header(char flv_header[9]) | ||
| 92 | return ret; | 98 | return ret; |
| 93 | } | 99 | } |
| 94 | 100 | ||
| 95 | - char pts[] = { 0x00, 0x00, 0x00, 0x00 }; | 101 | + char pts[] = { (char)0x00, (char)0x00, (char)0x00, (char)0x00 }; |
| 96 | if ((ret = _fs->write(pts, 4, NULL)) != ERROR_SUCCESS) { | 102 | if ((ret = _fs->write(pts, 4, NULL)) != ERROR_SUCCESS) { |
| 97 | return ret; | 103 | return ret; |
| 98 | } | 104 | } |
| @@ -104,6 +110,7 @@ int SrsFlvEncoder::write_metadata(char* data, int size) | @@ -104,6 +110,7 @@ int SrsFlvEncoder::write_metadata(char* data, int size) | ||
| 104 | { | 110 | { |
| 105 | int ret = ERROR_SUCCESS; | 111 | int ret = ERROR_SUCCESS; |
| 106 | 112 | ||
| 113 | + // 11 bytes tag header | ||
| 107 | static char tag_header[] = { | 114 | static char tag_header[] = { |
| 108 | (char)18, // TagType UB [5], 18 = script data | 115 | (char)18, // TagType UB [5], 18 = script data |
| 109 | (char)0x00, (char)0x00, (char)0x00, // DataSize UI24 Length of the message. | 116 | (char)0x00, (char)0x00, (char)0x00, // DataSize UI24 Length of the message. |
| @@ -240,6 +247,12 @@ int SrsFlvDecoder::initialize(SrsFileReader* fs) | @@ -240,6 +247,12 @@ int SrsFlvDecoder::initialize(SrsFileReader* fs) | ||
| 240 | { | 247 | { |
| 241 | int ret = ERROR_SUCCESS; | 248 | int ret = ERROR_SUCCESS; |
| 242 | 249 | ||
| 250 | + if (!fs->is_open()) { | ||
| 251 | + ret = ERROR_KERNEL_FLV_STREAM_CLOSED; | ||
| 252 | + srs_warn("stream is not open for decoder. ret=%d", ret); | ||
| 253 | + return ret; | ||
| 254 | + } | ||
| 255 | + | ||
| 243 | _fs = fs; | 256 | _fs = fs; |
| 244 | 257 | ||
| 245 | return ret; | 258 | return ret; |
| @@ -255,7 +268,7 @@ int SrsFlvDecoder::read_header(char header[9]) | @@ -255,7 +268,7 @@ int SrsFlvDecoder::read_header(char header[9]) | ||
| 255 | 268 | ||
| 256 | char* h = header; | 269 | char* h = header; |
| 257 | if (h[0] != 'F' || h[1] != 'L' || h[2] != 'V') { | 270 | if (h[0] != 'F' || h[1] != 'L' || h[2] != 'V') { |
| 258 | - ret = ERROR_SYSTEM_FLV_HEADER; | 271 | + ret = ERROR_KERNEL_FLV_HEADER; |
| 259 | srs_warn("flv header must start with FLV. ret=%d", ret); | 272 | srs_warn("flv header must start with FLV. ret=%d", ret); |
| 260 | return ret; | 273 | return ret; |
| 261 | } | 274 | } |
| @@ -345,35 +358,37 @@ int SrsFlvVodStreamDecoder::initialize(SrsFileReader* fs) | @@ -345,35 +358,37 @@ int SrsFlvVodStreamDecoder::initialize(SrsFileReader* fs) | ||
| 345 | { | 358 | { |
| 346 | int ret = ERROR_SUCCESS; | 359 | int ret = ERROR_SUCCESS; |
| 347 | 360 | ||
| 361 | + if (!fs->is_open()) { | ||
| 362 | + ret = ERROR_KERNEL_FLV_STREAM_CLOSED; | ||
| 363 | + srs_warn("stream is not open for decoder. ret=%d", ret); | ||
| 364 | + return ret; | ||
| 365 | + } | ||
| 366 | + | ||
| 348 | _fs = fs; | 367 | _fs = fs; |
| 349 | 368 | ||
| 350 | return ret; | 369 | return ret; |
| 351 | } | 370 | } |
| 352 | 371 | ||
| 353 | -int SrsFlvVodStreamDecoder::read_header(char** pdata, int* psize) | 372 | +int SrsFlvVodStreamDecoder::read_header_ext(char header[13]) |
| 354 | { | 373 | { |
| 355 | - *pdata = NULL; | ||
| 356 | - *psize = 0; | ||
| 357 | - | ||
| 358 | int ret = ERROR_SUCCESS; | 374 | int ret = ERROR_SUCCESS; |
| 359 | 375 | ||
| 360 | srs_assert(_fs); | 376 | srs_assert(_fs); |
| 361 | 377 | ||
| 378 | + // @remark, always false, for sizeof(char[13]) equals to sizeof(char*) | ||
| 379 | + //srs_assert(13 == sizeof(header)); | ||
| 380 | + | ||
| 362 | // 9bytes header and 4bytes first previous-tag-size | 381 | // 9bytes header and 4bytes first previous-tag-size |
| 363 | int size = 13; | 382 | int size = 13; |
| 364 | - char* buf = new char[size]; | ||
| 365 | 383 | ||
| 366 | - if ((ret = _fs->read(buf, size, NULL)) != ERROR_SUCCESS) { | 384 | + if ((ret = _fs->read(header, size, NULL)) != ERROR_SUCCESS) { |
| 367 | return ret; | 385 | return ret; |
| 368 | } | 386 | } |
| 369 | 387 | ||
| 370 | - *pdata = buf; | ||
| 371 | - *psize = size; | ||
| 372 | - | ||
| 373 | return ret; | 388 | return ret; |
| 374 | } | 389 | } |
| 375 | 390 | ||
| 376 | -int SrsFlvVodStreamDecoder::read_sequence_header(int64_t* pstart, int* psize) | 391 | +int SrsFlvVodStreamDecoder::read_sequence_header_summary(int64_t* pstart, int* psize) |
| 377 | { | 392 | { |
| 378 | *pstart = 0; | 393 | *pstart = 0; |
| 379 | *psize = 0; | 394 | *psize = 0; |
| @@ -66,7 +66,7 @@ public: | @@ -66,7 +66,7 @@ public: | ||
| 66 | virtual int write_header(char flv_header[9]); | 66 | virtual int write_header(char flv_header[9]); |
| 67 | /** | 67 | /** |
| 68 | * write flv metadata. | 68 | * write flv metadata. |
| 69 | - * serialize from: | 69 | + * @param data, the amf0 metadata which serialize from: |
| 70 | * AMF0 string: onMetaData, | 70 | * AMF0 string: onMetaData, |
| 71 | * AMF0 object: the metadata object. | 71 | * AMF0 object: the metadata object. |
| 72 | */ | 72 | */ |
| @@ -76,6 +76,7 @@ public: | @@ -76,6 +76,7 @@ public: | ||
| 76 | */ | 76 | */ |
| 77 | virtual int write_audio(int64_t timestamp, char* data, int size); | 77 | virtual int write_audio(int64_t timestamp, char* data, int size); |
| 78 | virtual int write_video(int64_t timestamp, char* data, int size); | 78 | virtual int write_video(int64_t timestamp, char* data, int size); |
| 79 | +public: | ||
| 79 | /** | 80 | /** |
| 80 | * get the tag size, | 81 | * get the tag size, |
| 81 | * including the tag header, body, and 4bytes previous tag size. | 82 | * including the tag header, body, and 4bytes previous tag size. |
| @@ -134,13 +135,17 @@ public: | @@ -134,13 +135,17 @@ public: | ||
| 134 | virtual int initialize(SrsFileReader* fs); | 135 | virtual int initialize(SrsFileReader* fs); |
| 135 | public: | 136 | public: |
| 136 | /** | 137 | /** |
| 137 | - * read the flv header and size. | 138 | + * read the flv header and its size. |
| 139 | + * @param header, fill it 13bytes(9bytes header, 4bytes previous tag size). | ||
| 138 | */ | 140 | */ |
| 139 | - virtual int read_header(char** pdata, int* psize); | 141 | + virtual int read_header_ext(char header[13]); |
| 140 | /** | 142 | /** |
| 141 | - * read the sequence header and size. | 143 | + * read the sequence header tags offset and its size. |
| 144 | + * @param pstart, the start offset of sequence header. | ||
| 145 | + * @param psize, output the size, (tag header)+(tag body)+(4bytes previous tag size). | ||
| 146 | + * @remark we think the first audio/video is sequence header. | ||
| 142 | */ | 147 | */ |
| 143 | - virtual int read_sequence_header(int64_t* pstart, int* psize); | 148 | + virtual int read_sequence_header_summary(int64_t* pstart, int* psize); |
| 144 | public: | 149 | public: |
| 145 | /** | 150 | /** |
| 146 | * for start offset, seed to this position and response flv stream. | 151 | * for start offset, seed to this position and response flv stream. |
| @@ -557,31 +557,6 @@ namespace srs | @@ -557,31 +557,6 @@ namespace srs | ||
| 557 | return bytes; | 557 | return bytes; |
| 558 | } | 558 | } |
| 559 | 559 | ||
| 560 | - /** | ||
| 561 | - * compare the memory in bytes. | ||
| 562 | - */ | ||
| 563 | - bool srs_bytes_equals(void* pa, void* pb, int size) | ||
| 564 | - { | ||
| 565 | - u_int8_t* a = (u_int8_t*)pa; | ||
| 566 | - u_int8_t* b = (u_int8_t*)pb; | ||
| 567 | - | ||
| 568 | - if (!a && !b) { | ||
| 569 | - return true; | ||
| 570 | - } | ||
| 571 | - | ||
| 572 | - if (!a || !b) { | ||
| 573 | - return false; | ||
| 574 | - } | ||
| 575 | - | ||
| 576 | - for(int i = 0; i < size; i++){ | ||
| 577 | - if(a[i] != b[i]){ | ||
| 578 | - return false; | ||
| 579 | - } | ||
| 580 | - } | ||
| 581 | - | ||
| 582 | - return true; | ||
| 583 | - } | ||
| 584 | - | ||
| 585 | c2s2::c2s2() | 560 | c2s2::c2s2() |
| 586 | { | 561 | { |
| 587 | srs_random_generate(random, 1504); | 562 | srs_random_generate(random, 1504); |
| @@ -168,11 +168,6 @@ namespace srs | @@ -168,11 +168,6 @@ namespace srs | ||
| 168 | char* srs_bytes_join_schema1(int32_t time, int32_t version, digest_block* digest, key_block* key); | 168 | char* srs_bytes_join_schema1(int32_t time, int32_t version, digest_block* digest, key_block* key); |
| 169 | 169 | ||
| 170 | /** | 170 | /** |
| 171 | - * compare the memory in bytes. | ||
| 172 | - */ | ||
| 173 | - bool srs_bytes_equals(void* pa, void* pb, int size); | ||
| 174 | - | ||
| 175 | - /** | ||
| 176 | * c1s1 schema0 | 171 | * c1s1 schema0 |
| 177 | * time: 4bytes | 172 | * time: 4bytes |
| 178 | * version: 4bytes | 173 | * version: 4bytes |
| @@ -126,3 +126,28 @@ string srs_generate_tc_url(string ip, string vhost, string app, string port) | @@ -126,3 +126,28 @@ string srs_generate_tc_url(string ip, string vhost, string app, string port) | ||
| 126 | 126 | ||
| 127 | return tcUrl; | 127 | return tcUrl; |
| 128 | } | 128 | } |
| 129 | + | ||
| 130 | +/** | ||
| 131 | +* compare the memory in bytes. | ||
| 132 | +*/ | ||
| 133 | +bool srs_bytes_equals(void* pa, void* pb, int size) | ||
| 134 | +{ | ||
| 135 | + u_int8_t* a = (u_int8_t*)pa; | ||
| 136 | + u_int8_t* b = (u_int8_t*)pb; | ||
| 137 | + | ||
| 138 | + if (!a && !b) { | ||
| 139 | + return true; | ||
| 140 | + } | ||
| 141 | + | ||
| 142 | + if (!a || !b) { | ||
| 143 | + return false; | ||
| 144 | + } | ||
| 145 | + | ||
| 146 | + for(int i = 0; i < size; i++){ | ||
| 147 | + if(a[i] != b[i]){ | ||
| 148 | + return false; | ||
| 149 | + } | ||
| 150 | + } | ||
| 151 | + | ||
| 152 | + return true; | ||
| 153 | +} |
| @@ -58,4 +58,9 @@ extern void srs_random_generate(char* bytes, int size); | @@ -58,4 +58,9 @@ extern void srs_random_generate(char* bytes, int size); | ||
| 58 | // generate the tcUrl. | 58 | // generate the tcUrl. |
| 59 | extern std::string srs_generate_tc_url(std::string ip, std::string vhost, std::string app, std::string port); | 59 | extern std::string srs_generate_tc_url(std::string ip, std::string vhost, std::string app, std::string port); |
| 60 | 60 | ||
| 61 | +/** | ||
| 62 | +* compare the memory in bytes. | ||
| 63 | +*/ | ||
| 64 | +extern bool srs_bytes_equals(void* pa, void* pb, int size); | ||
| 65 | + | ||
| 61 | #endif | 66 | #endif |
| @@ -27,93 +27,155 @@ using namespace std; | @@ -27,93 +27,155 @@ using namespace std; | ||
| 27 | #include <srs_kernel_error.hpp> | 27 | #include <srs_kernel_error.hpp> |
| 28 | #include <srs_kernel_codec.hpp> | 28 | #include <srs_kernel_codec.hpp> |
| 29 | #include <srs_kernel_flv.hpp> | 29 | #include <srs_kernel_flv.hpp> |
| 30 | +#include <srs_kernel_utility.hpp> | ||
| 31 | +#include <srs_protocol_utility.hpp> | ||
| 32 | + | ||
| 33 | +#define MAX_MOCK_DATA_SIZE 1024 * 1024 | ||
| 30 | 34 | ||
| 31 | MockSrsFileWriter::MockSrsFileWriter() | 35 | MockSrsFileWriter::MockSrsFileWriter() |
| 32 | { | 36 | { |
| 37 | + data = new char[MAX_MOCK_DATA_SIZE]; | ||
| 38 | + offset = -1; | ||
| 33 | } | 39 | } |
| 34 | 40 | ||
| 35 | MockSrsFileWriter::~MockSrsFileWriter() | 41 | MockSrsFileWriter::~MockSrsFileWriter() |
| 36 | { | 42 | { |
| 43 | + srs_freep(data); | ||
| 37 | } | 44 | } |
| 38 | 45 | ||
| 39 | -int MockSrsFileWriter::open(string file) | 46 | +int MockSrsFileWriter::open(string /*file*/) |
| 40 | { | 47 | { |
| 41 | int ret = ERROR_SUCCESS; | 48 | int ret = ERROR_SUCCESS; |
| 49 | + | ||
| 50 | + offset = 0; | ||
| 51 | + | ||
| 42 | return ret; | 52 | return ret; |
| 43 | } | 53 | } |
| 44 | 54 | ||
| 45 | void MockSrsFileWriter::close() | 55 | void MockSrsFileWriter::close() |
| 46 | { | 56 | { |
| 47 | - int ret = ERROR_SUCCESS; | ||
| 48 | - return; | 57 | + offset = 0; |
| 49 | } | 58 | } |
| 50 | 59 | ||
| 51 | bool MockSrsFileWriter::is_open() | 60 | bool MockSrsFileWriter::is_open() |
| 52 | { | 61 | { |
| 53 | - return true; | 62 | + return offset >= 0; |
| 54 | } | 63 | } |
| 55 | 64 | ||
| 56 | int64_t MockSrsFileWriter::tellg() | 65 | int64_t MockSrsFileWriter::tellg() |
| 57 | { | 66 | { |
| 58 | - return 0; | 67 | + return offset; |
| 59 | } | 68 | } |
| 60 | 69 | ||
| 61 | int MockSrsFileWriter::write(void* buf, size_t count, ssize_t* pnwrite) | 70 | int MockSrsFileWriter::write(void* buf, size_t count, ssize_t* pnwrite) |
| 62 | { | 71 | { |
| 63 | int ret = ERROR_SUCCESS; | 72 | int ret = ERROR_SUCCESS; |
| 73 | + | ||
| 74 | + int size = srs_min(MAX_MOCK_DATA_SIZE - offset, count); | ||
| 75 | + | ||
| 76 | + memcpy(data + offset, buf, size); | ||
| 77 | + | ||
| 78 | + if (pnwrite) { | ||
| 79 | + *pnwrite = size; | ||
| 80 | + } | ||
| 81 | + | ||
| 82 | + offset += size; | ||
| 83 | + | ||
| 64 | return ret; | 84 | return ret; |
| 65 | } | 85 | } |
| 66 | 86 | ||
| 87 | +void MockSrsFileWriter::mock_reset_offset() | ||
| 88 | +{ | ||
| 89 | + offset = 0; | ||
| 90 | +} | ||
| 91 | + | ||
| 67 | MockSrsFileReader::MockSrsFileReader() | 92 | MockSrsFileReader::MockSrsFileReader() |
| 68 | { | 93 | { |
| 94 | + data = new char[MAX_MOCK_DATA_SIZE]; | ||
| 95 | + size = 0; | ||
| 96 | + offset = -1; | ||
| 69 | } | 97 | } |
| 70 | 98 | ||
| 71 | MockSrsFileReader::~MockSrsFileReader() | 99 | MockSrsFileReader::~MockSrsFileReader() |
| 72 | { | 100 | { |
| 101 | + srs_freep(data); | ||
| 73 | } | 102 | } |
| 74 | 103 | ||
| 75 | -int MockSrsFileReader::open(string file) | 104 | +int MockSrsFileReader::open(string /*file*/) |
| 76 | { | 105 | { |
| 77 | int ret = ERROR_SUCCESS; | 106 | int ret = ERROR_SUCCESS; |
| 107 | + | ||
| 108 | + offset = 0; | ||
| 109 | + | ||
| 78 | return ret; | 110 | return ret; |
| 79 | } | 111 | } |
| 80 | 112 | ||
| 81 | void MockSrsFileReader::close() | 113 | void MockSrsFileReader::close() |
| 82 | { | 114 | { |
| 83 | - int ret = ERROR_SUCCESS; | ||
| 84 | - return; | 115 | + offset = 0; |
| 85 | } | 116 | } |
| 86 | 117 | ||
| 87 | bool MockSrsFileReader::is_open() | 118 | bool MockSrsFileReader::is_open() |
| 88 | { | 119 | { |
| 89 | - return true; | 120 | + return offset >= 0; |
| 90 | } | 121 | } |
| 91 | 122 | ||
| 92 | int64_t MockSrsFileReader::tellg() | 123 | int64_t MockSrsFileReader::tellg() |
| 93 | { | 124 | { |
| 94 | - return 0; | 125 | + return offset; |
| 95 | } | 126 | } |
| 96 | 127 | ||
| 97 | -void MockSrsFileReader::skip(int64_t size) | 128 | +void MockSrsFileReader::skip(int64_t _size) |
| 98 | { | 129 | { |
| 130 | + offset += _size; | ||
| 99 | } | 131 | } |
| 100 | 132 | ||
| 101 | -int64_t MockSrsFileReader::lseek(int64_t offset) | 133 | +int64_t MockSrsFileReader::lseek(int64_t _offset) |
| 102 | { | 134 | { |
| 135 | + offset = (int)_offset; | ||
| 103 | return offset; | 136 | return offset; |
| 104 | } | 137 | } |
| 105 | 138 | ||
| 106 | int64_t MockSrsFileReader::filesize() | 139 | int64_t MockSrsFileReader::filesize() |
| 107 | { | 140 | { |
| 108 | - return 0; | 141 | + return size; |
| 109 | } | 142 | } |
| 110 | 143 | ||
| 111 | int MockSrsFileReader::read(void* buf, size_t count, ssize_t* pnread) | 144 | int MockSrsFileReader::read(void* buf, size_t count, ssize_t* pnread) |
| 112 | { | 145 | { |
| 113 | int ret = ERROR_SUCCESS; | 146 | int ret = ERROR_SUCCESS; |
| 147 | + | ||
| 148 | + int s = srs_min(size - offset, (int)count); | ||
| 149 | + | ||
| 150 | + if (s <= 0) { | ||
| 151 | + return ret; | ||
| 152 | + } | ||
| 153 | + | ||
| 154 | + memcpy(buf, data + offset, s); | ||
| 155 | + | ||
| 156 | + if (pnread) { | ||
| 157 | + *pnread = s; | ||
| 158 | + } | ||
| 159 | + | ||
| 160 | + offset += s; | ||
| 161 | + | ||
| 114 | return ret; | 162 | return ret; |
| 115 | } | 163 | } |
| 116 | 164 | ||
| 165 | +void MockSrsFileReader::mock_append_data(const char* _data, int _size) | ||
| 166 | +{ | ||
| 167 | + int s = srs_min(MAX_MOCK_DATA_SIZE - offset, _size); | ||
| 168 | + memcpy(data + offset, _data, s); | ||
| 169 | + | ||
| 170 | + offset += s; | ||
| 171 | + size += s; | ||
| 172 | +} | ||
| 173 | + | ||
| 174 | +void MockSrsFileReader::mock_reset_offset() | ||
| 175 | +{ | ||
| 176 | + offset = 0; | ||
| 177 | +} | ||
| 178 | + | ||
| 117 | VOID TEST(KernelCodecTest, IsKeyFrame) | 179 | VOID TEST(KernelCodecTest, IsKeyFrame) |
| 118 | { | 180 | { |
| 119 | int8_t data; | 181 | int8_t data; |
| @@ -196,9 +258,431 @@ VOID TEST(KernelCodecTest, IsAudioSequenceHeader) | @@ -196,9 +258,431 @@ VOID TEST(KernelCodecTest, IsAudioSequenceHeader) | ||
| 196 | EXPECT_FALSE(SrsFlvCodec::video_is_sequence_header((int8_t*)pp, 2)); | 258 | EXPECT_FALSE(SrsFlvCodec::video_is_sequence_header((int8_t*)pp, 2)); |
| 197 | } | 259 | } |
| 198 | 260 | ||
| 199 | -VOID TEST(KernelFlvTest, IsAudioSequenceHeader) | 261 | +VOID TEST(KernelFlvTest, FlvEncoderStreamClosed) |
| 262 | +{ | ||
| 263 | + MockSrsFileWriter fs; | ||
| 264 | + SrsFlvEncoder enc; | ||
| 265 | + ASSERT_TRUE(ERROR_SUCCESS != enc.initialize(&fs)); | ||
| 266 | +} | ||
| 267 | + | ||
| 268 | +VOID TEST(KernelFlvTest, FlvEncoderWriteHeader) | ||
| 269 | +{ | ||
| 270 | + MockSrsFileWriter fs; | ||
| 271 | + SrsFlvEncoder enc; | ||
| 272 | + ASSERT_TRUE(ERROR_SUCCESS == fs.open("")); | ||
| 273 | + ASSERT_TRUE(ERROR_SUCCESS == enc.initialize(&fs)); | ||
| 274 | + | ||
| 275 | + // write header, 9bytes | ||
| 276 | + char flv_header[] = { | ||
| 277 | + 'F', 'L', 'V', // Signatures "FLV" | ||
| 278 | + (char)0x01, // File version (for example, 0x01 for FLV version 1) | ||
| 279 | + (char)0x00, // 4, audio; 1, video; 5 audio+video. | ||
| 280 | + (char)0x00, (char)0x00, (char)0x00, (char)0x09 // DataOffset UI32 The length of this header in bytes | ||
| 281 | + }; | ||
| 282 | + char pts[] = { (char)0x00, (char)0x00, (char)0x00, (char)0x00 }; | ||
| 283 | + | ||
| 284 | + EXPECT_TRUE(ERROR_SUCCESS == enc.write_header()); | ||
| 285 | + ASSERT_TRUE(9 + 4 == fs.offset); | ||
| 286 | + | ||
| 287 | + EXPECT_TRUE(srs_bytes_equals(flv_header, fs.data, 9)); | ||
| 288 | + EXPECT_TRUE(srs_bytes_equals(pts, fs.data + 9, 4)); | ||
| 289 | + | ||
| 290 | + // customer header | ||
| 291 | + flv_header[3] = 0xF0; | ||
| 292 | + flv_header[4] = 0xF1; | ||
| 293 | + flv_header[5] = 0x01; | ||
| 294 | + | ||
| 295 | + fs.mock_reset_offset(); | ||
| 296 | + | ||
| 297 | + EXPECT_TRUE(ERROR_SUCCESS == enc.write_header(flv_header)); | ||
| 298 | + ASSERT_TRUE(9 + 4 == fs.offset); | ||
| 299 | + | ||
| 300 | + EXPECT_TRUE(srs_bytes_equals(flv_header, fs.data, 9)); | ||
| 301 | + EXPECT_TRUE(srs_bytes_equals(pts, fs.data + 9, 4)); | ||
| 302 | +} | ||
| 303 | + | ||
| 304 | +VOID TEST(KernelFlvTest, FlvEncoderWriteMetadata) | ||
| 305 | +{ | ||
| 306 | + MockSrsFileWriter fs; | ||
| 307 | + EXPECT_TRUE(ERROR_SUCCESS == fs.open("")); | ||
| 308 | + SrsFlvEncoder enc; | ||
| 309 | + ASSERT_TRUE(ERROR_SUCCESS == enc.initialize(&fs)); | ||
| 310 | + | ||
| 311 | + // 11 bytes tag header | ||
| 312 | + char tag_header[] = { | ||
| 313 | + (char)18, // TagType UB [5], 18 = script data | ||
| 314 | + (char)0x00, (char)0x00, (char)0x08, // DataSize UI24 Length of the message. | ||
| 315 | + (char)0x00, (char)0x00, (char)0x00, // Timestamp UI24 Time in milliseconds at which the data in this tag applies. | ||
| 316 | + (char)0x00, // TimestampExtended UI8 | ||
| 317 | + (char)0x00, (char)0x00, (char)0x00, // StreamID UI24 Always 0. | ||
| 318 | + }; | ||
| 319 | + char md[] = { | ||
| 320 | + (char)0x01, (char)0x02, (char)0x03, (char)0x04, | ||
| 321 | + (char)0x04, (char)0x03, (char)0x02, (char)0x01 | ||
| 322 | + }; | ||
| 323 | + char pts[] = { (char)0x00, (char)0x00, (char)0x00, (char)19 }; | ||
| 324 | + | ||
| 325 | + ASSERT_TRUE(ERROR_SUCCESS == enc.write_metadata(md, 8)); | ||
| 326 | + ASSERT_TRUE(11 + 8 + 4 == fs.offset); | ||
| 327 | + | ||
| 328 | + EXPECT_TRUE(srs_bytes_equals(tag_header, fs.data, 11)); | ||
| 329 | + EXPECT_TRUE(srs_bytes_equals(md, fs.data + 11, 8)); | ||
| 330 | + EXPECT_TRUE(true); // donot know why, if not add it, the print is disabled. | ||
| 331 | + EXPECT_TRUE(srs_bytes_equals(pts, fs.data + 19, 4)); | ||
| 332 | +} | ||
| 333 | + | ||
| 334 | +VOID TEST(KernelFlvTest, FlvEncoderWriteAudio) | ||
| 335 | +{ | ||
| 336 | + MockSrsFileWriter fs; | ||
| 337 | + SrsFlvEncoder enc; | ||
| 338 | + ASSERT_TRUE(ERROR_SUCCESS == fs.open("")); | ||
| 339 | + ASSERT_TRUE(ERROR_SUCCESS == enc.initialize(&fs)); | ||
| 340 | + | ||
| 341 | + // 11bytes tag header | ||
| 342 | + char tag_header[] = { | ||
| 343 | + (char)8, // TagType UB [5], 8 = audio | ||
| 344 | + (char)0x00, (char)0x00, (char)0x08, // DataSize UI24 Length of the message. | ||
| 345 | + (char)0x00, (char)0x00, (char)0x30, // Timestamp UI24 Time in milliseconds at which the data in this tag applies. | ||
| 346 | + (char)0x00, // TimestampExtended UI8 | ||
| 347 | + (char)0x00, (char)0x00, (char)0x00, // StreamID UI24 Always 0. | ||
| 348 | + }; | ||
| 349 | + char audio[] = { | ||
| 350 | + (char)0x01, (char)0x02, (char)0x03, (char)0x04, | ||
| 351 | + (char)0x04, (char)0x03, (char)0x02, (char)0x01 | ||
| 352 | + }; | ||
| 353 | + char pts[] = { (char)0x00, (char)0x00, (char)0x00, (char)19 }; | ||
| 354 | + | ||
| 355 | + ASSERT_TRUE(ERROR_SUCCESS == enc.write_audio(0x30, audio, 8)); | ||
| 356 | + ASSERT_TRUE(11 + 8 + 4 == fs.offset); | ||
| 357 | + | ||
| 358 | + EXPECT_TRUE(srs_bytes_equals(tag_header, fs.data, 11)); | ||
| 359 | + EXPECT_TRUE(srs_bytes_equals(audio, fs.data + 11, 8)); | ||
| 360 | + EXPECT_TRUE(true); // donot know why, if not add it, the print is disabled. | ||
| 361 | + EXPECT_TRUE(srs_bytes_equals(pts, fs.data + 11 + 8, 4)); | ||
| 362 | +} | ||
| 363 | + | ||
| 364 | +VOID TEST(KernelFlvTest, FlvEncoderWriteVideo) | ||
| 200 | { | 365 | { |
| 201 | MockSrsFileWriter fs; | 366 | MockSrsFileWriter fs; |
| 202 | SrsFlvEncoder enc; | 367 | SrsFlvEncoder enc; |
| 368 | + ASSERT_TRUE(ERROR_SUCCESS == fs.open("")); | ||
| 203 | ASSERT_TRUE(ERROR_SUCCESS == enc.initialize(&fs)); | 369 | ASSERT_TRUE(ERROR_SUCCESS == enc.initialize(&fs)); |
| 370 | + | ||
| 371 | + // 11bytes tag header | ||
| 372 | + char tag_header[] = { | ||
| 373 | + (char)9, // TagType UB [5], 9 = video | ||
| 374 | + (char)0x00, (char)0x00, (char)0x08, // DataSize UI24 Length of the message. | ||
| 375 | + (char)0x00, (char)0x00, (char)0x30, // Timestamp UI24 Time in milliseconds at which the data in this tag applies. | ||
| 376 | + (char)0x00, // TimestampExtended UI8 | ||
| 377 | + (char)0x00, (char)0x00, (char)0x00, // StreamID UI24 Always 0. | ||
| 378 | + }; | ||
| 379 | + char video[] = { | ||
| 380 | + (char)0x01, (char)0x02, (char)0x03, (char)0x04, | ||
| 381 | + (char)0x04, (char)0x03, (char)0x02, (char)0x01 | ||
| 382 | + }; | ||
| 383 | + char pts[] = { (char)0x00, (char)0x00, (char)0x00, (char)19 }; | ||
| 384 | + | ||
| 385 | + ASSERT_TRUE(ERROR_SUCCESS == enc.write_video(0x30, video, 8)); | ||
| 386 | + ASSERT_TRUE(11 + 8 + 4 == fs.offset); | ||
| 387 | + | ||
| 388 | + EXPECT_TRUE(srs_bytes_equals(tag_header, fs.data, 11)); | ||
| 389 | + EXPECT_TRUE(srs_bytes_equals(video, fs.data + 11, 8)); | ||
| 390 | + EXPECT_TRUE(true); // donot know why, if not add it, the print is disabled. | ||
| 391 | + EXPECT_TRUE(srs_bytes_equals(pts, fs.data + 11 + 8, 4)); | ||
| 392 | +} | ||
| 393 | + | ||
| 394 | +VOID TEST(KernelFlvTest, FlvEncoderSizeTag) | ||
| 395 | +{ | ||
| 396 | + EXPECT_EQ(11+4+10, SrsFlvEncoder::size_tag(10)); | ||
| 397 | + EXPECT_EQ(11+4+0, SrsFlvEncoder::size_tag(0)); | ||
| 398 | +} | ||
| 399 | + | ||
| 400 | +VOID TEST(KernelFlvTest, FlvDecoderStreamClosed) | ||
| 401 | +{ | ||
| 402 | + MockSrsFileReader fs; | ||
| 403 | + SrsFlvDecoder dec; | ||
| 404 | + ASSERT_TRUE(ERROR_SUCCESS != dec.initialize(&fs)); | ||
| 405 | +} | ||
| 406 | + | ||
| 407 | +VOID TEST(KernelFlvTest, FlvDecoderHeader) | ||
| 408 | +{ | ||
| 409 | + MockSrsFileReader fs; | ||
| 410 | + SrsFlvDecoder dec; | ||
| 411 | + ASSERT_TRUE(ERROR_SUCCESS == fs.open("")); | ||
| 412 | + ASSERT_TRUE(ERROR_SUCCESS == dec.initialize(&fs)); | ||
| 413 | + | ||
| 414 | + // 9bytes | ||
| 415 | + char flv_header[] = { | ||
| 416 | + 'F', 'L', 'V', // Signatures "FLV" | ||
| 417 | + (char)0x01, // File version (for example, 0x01 for FLV version 1) | ||
| 418 | + (char)0x00, // 4, audio; 1, video; 5 audio+video. | ||
| 419 | + (char)0x00, (char)0x00, (char)0x00, (char)0x09 // DataOffset UI32 The length of this header in bytes | ||
| 420 | + }; | ||
| 421 | + char pts[] = { (char)0x00, (char)0x00, (char)0x00, (char)0x00 }; | ||
| 422 | + fs.mock_append_data(flv_header, 9); | ||
| 423 | + fs.mock_append_data(pts, 4); | ||
| 424 | + | ||
| 425 | + char data[1024]; | ||
| 426 | + fs.mock_reset_offset(); | ||
| 427 | + | ||
| 428 | + EXPECT_TRUE(ERROR_SUCCESS == dec.read_header(data)); | ||
| 429 | + EXPECT_TRUE(srs_bytes_equals(flv_header, data, 9)); | ||
| 430 | + | ||
| 431 | + EXPECT_TRUE(ERROR_SUCCESS == dec.read_previous_tag_size(data)); | ||
| 432 | + EXPECT_TRUE(srs_bytes_equals(pts, data, 4)); | ||
| 433 | +} | ||
| 434 | + | ||
| 435 | +VOID TEST(KernelFlvTest, FlvDecoderMetadata) | ||
| 436 | +{ | ||
| 437 | + MockSrsFileReader fs; | ||
| 438 | + SrsFlvDecoder dec; | ||
| 439 | + ASSERT_TRUE(ERROR_SUCCESS == fs.open("")); | ||
| 440 | + ASSERT_TRUE(ERROR_SUCCESS == dec.initialize(&fs)); | ||
| 441 | + | ||
| 442 | + // 11 bytes tag header | ||
| 443 | + char tag_header[] = { | ||
| 444 | + (char)18, // TagType UB [5], 18 = script data | ||
| 445 | + (char)0x00, (char)0x00, (char)0x08, // DataSize UI24 Length of the message. | ||
| 446 | + (char)0x00, (char)0x00, (char)0x00, // Timestamp UI24 Time in milliseconds at which the data in this tag applies. | ||
| 447 | + (char)0x00, // TimestampExtended UI8 | ||
| 448 | + (char)0x00, (char)0x00, (char)0x00, // StreamID UI24 Always 0. | ||
| 449 | + }; | ||
| 450 | + char md[] = { | ||
| 451 | + (char)0x01, (char)0x02, (char)0x03, (char)0x04, | ||
| 452 | + (char)0x04, (char)0x03, (char)0x02, (char)0x01 | ||
| 453 | + }; | ||
| 454 | + char pts[] = { (char)0x00, (char)0x00, (char)0x00, (char)19 }; | ||
| 455 | + fs.mock_append_data(tag_header, 11); | ||
| 456 | + fs.mock_append_data(md, 8); | ||
| 457 | + fs.mock_append_data(pts, 4); | ||
| 458 | + | ||
| 459 | + char type = 0; | ||
| 460 | + int32_t size = 0; | ||
| 461 | + u_int32_t time = 0; | ||
| 462 | + char data[1024]; | ||
| 463 | + fs.mock_reset_offset(); | ||
| 464 | + | ||
| 465 | + EXPECT_TRUE(ERROR_SUCCESS == dec.read_tag_header(&type, &size, &time)); | ||
| 466 | + EXPECT_TRUE(18 == type); | ||
| 467 | + EXPECT_TRUE(8 == size); | ||
| 468 | + EXPECT_TRUE(0 == time); | ||
| 469 | + | ||
| 470 | + EXPECT_TRUE(ERROR_SUCCESS == dec.read_tag_data(data, size)); | ||
| 471 | + EXPECT_TRUE(srs_bytes_equals(md, data, 8)); | ||
| 472 | + | ||
| 473 | + EXPECT_TRUE(ERROR_SUCCESS == dec.read_previous_tag_size(data)); | ||
| 474 | + EXPECT_TRUE(srs_bytes_equals(pts, data, 4)); | ||
| 475 | +} | ||
| 476 | + | ||
| 477 | +VOID TEST(KernelFlvTest, FlvDecoderAudio) | ||
| 478 | +{ | ||
| 479 | + MockSrsFileReader fs; | ||
| 480 | + SrsFlvDecoder dec; | ||
| 481 | + ASSERT_TRUE(ERROR_SUCCESS == fs.open("")); | ||
| 482 | + ASSERT_TRUE(ERROR_SUCCESS == dec.initialize(&fs)); | ||
| 483 | + | ||
| 484 | + // 11bytes tag header | ||
| 485 | + char tag_header[] = { | ||
| 486 | + (char)8, // TagType UB [5], 8 = audio | ||
| 487 | + (char)0x00, (char)0x00, (char)0x08, // DataSize UI24 Length of the message. | ||
| 488 | + (char)0x00, (char)0x00, (char)0x30, // Timestamp UI24 Time in milliseconds at which the data in this tag applies. | ||
| 489 | + (char)0x00, // TimestampExtended UI8 | ||
| 490 | + (char)0x00, (char)0x00, (char)0x00, // StreamID UI24 Always 0. | ||
| 491 | + }; | ||
| 492 | + char audio[] = { | ||
| 493 | + (char)0x01, (char)0x02, (char)0x03, (char)0x04, | ||
| 494 | + (char)0x04, (char)0x03, (char)0x02, (char)0x01 | ||
| 495 | + }; | ||
| 496 | + char pts[] = { (char)0x00, (char)0x00, (char)0x00, (char)19 }; | ||
| 497 | + fs.mock_append_data(tag_header, 11); | ||
| 498 | + fs.mock_append_data(audio, 8); | ||
| 499 | + fs.mock_append_data(pts, 4); | ||
| 500 | + | ||
| 501 | + char type = 0; | ||
| 502 | + int32_t size = 0; | ||
| 503 | + u_int32_t time = 0; | ||
| 504 | + char data[1024]; | ||
| 505 | + fs.mock_reset_offset(); | ||
| 506 | + | ||
| 507 | + EXPECT_TRUE(ERROR_SUCCESS == dec.read_tag_header(&type, &size, &time)); | ||
| 508 | + EXPECT_TRUE(8 == type); | ||
| 509 | + EXPECT_TRUE(8 == size); | ||
| 510 | + EXPECT_TRUE(0x30 == time); | ||
| 511 | + | ||
| 512 | + EXPECT_TRUE(ERROR_SUCCESS == dec.read_tag_data(data, size)); | ||
| 513 | + EXPECT_TRUE(srs_bytes_equals(audio, data, 8)); | ||
| 514 | + | ||
| 515 | + EXPECT_TRUE(ERROR_SUCCESS == dec.read_previous_tag_size(data)); | ||
| 516 | + EXPECT_TRUE(srs_bytes_equals(pts, data, 4)); | ||
| 517 | +} | ||
| 518 | + | ||
| 519 | +VOID TEST(KernelFlvTest, FlvDecoderVideo) | ||
| 520 | +{ | ||
| 521 | + MockSrsFileReader fs; | ||
| 522 | + SrsFlvDecoder dec; | ||
| 523 | + ASSERT_TRUE(ERROR_SUCCESS == fs.open("")); | ||
| 524 | + ASSERT_TRUE(ERROR_SUCCESS == dec.initialize(&fs)); | ||
| 525 | + | ||
| 526 | + // 11bytes tag header | ||
| 527 | + char tag_header[] = { | ||
| 528 | + (char)9, // TagType UB [5], 9 = video | ||
| 529 | + (char)0x00, (char)0x00, (char)0x08, // DataSize UI24 Length of the message. | ||
| 530 | + (char)0x00, (char)0x00, (char)0x30, // Timestamp UI24 Time in milliseconds at which the data in this tag applies. | ||
| 531 | + (char)0x00, // TimestampExtended UI8 | ||
| 532 | + (char)0x00, (char)0x00, (char)0x00, // StreamID UI24 Always 0. | ||
| 533 | + }; | ||
| 534 | + char video[] = { | ||
| 535 | + (char)0x01, (char)0x02, (char)0x03, (char)0x04, | ||
| 536 | + (char)0x04, (char)0x03, (char)0x02, (char)0x01 | ||
| 537 | + }; | ||
| 538 | + char pts[] = { (char)0x00, (char)0x00, (char)0x00, (char)19 }; | ||
| 539 | + fs.mock_append_data(tag_header, 11); | ||
| 540 | + fs.mock_append_data(video, 8); | ||
| 541 | + fs.mock_append_data(pts, 4); | ||
| 542 | + | ||
| 543 | + char type = 0; | ||
| 544 | + int32_t size = 0; | ||
| 545 | + u_int32_t time = 0; | ||
| 546 | + char data[1024]; | ||
| 547 | + fs.mock_reset_offset(); | ||
| 548 | + | ||
| 549 | + EXPECT_TRUE(ERROR_SUCCESS == dec.read_tag_header(&type, &size, &time)); | ||
| 550 | + EXPECT_TRUE(9 == type); | ||
| 551 | + EXPECT_TRUE(8 == size); | ||
| 552 | + EXPECT_TRUE(0x30 == time); | ||
| 553 | + | ||
| 554 | + EXPECT_TRUE(ERROR_SUCCESS == dec.read_tag_data(data, size)); | ||
| 555 | + EXPECT_TRUE(srs_bytes_equals(video, data, 8)); | ||
| 556 | + | ||
| 557 | + EXPECT_TRUE(ERROR_SUCCESS == dec.read_previous_tag_size(data)); | ||
| 558 | + EXPECT_TRUE(srs_bytes_equals(pts, data, 4)); | ||
| 559 | +} | ||
| 560 | + | ||
| 561 | +VOID TEST(KernelFlvTest, FlvVSDecoderStreamClosed) | ||
| 562 | +{ | ||
| 563 | + MockSrsFileReader fs; | ||
| 564 | + SrsFlvVodStreamDecoder dec; | ||
| 565 | + ASSERT_TRUE(ERROR_SUCCESS != dec.initialize(&fs)); | ||
| 566 | +} | ||
| 567 | + | ||
| 568 | +VOID TEST(KernelFlvTest, FlvVSDecoderHeader) | ||
| 569 | +{ | ||
| 570 | + MockSrsFileReader fs; | ||
| 571 | + SrsFlvVodStreamDecoder dec; | ||
| 572 | + | ||
| 573 | + ASSERT_TRUE(ERROR_SUCCESS == fs.open("")); | ||
| 574 | + ASSERT_TRUE(ERROR_SUCCESS == dec.initialize(&fs)); | ||
| 575 | + | ||
| 576 | + // 9bytes | ||
| 577 | + char flv_header[] = { | ||
| 578 | + 'F', 'L', 'V', // Signatures "FLV" | ||
| 579 | + (char)0x01, // File version (for example, 0x01 for FLV version 1) | ||
| 580 | + (char)0x00, // 4, audio; 1, video; 5 audio+video. | ||
| 581 | + (char)0x00, (char)0x00, (char)0x00, (char)0x09 // DataOffset UI32 The length of this header in bytes | ||
| 582 | + }; | ||
| 583 | + char pts[] = { (char)0x00, (char)0x00, (char)0x00, (char)0x00 }; | ||
| 584 | + fs.mock_append_data(flv_header, 9); | ||
| 585 | + fs.mock_append_data(pts, 4); | ||
| 586 | + | ||
| 587 | + char data[1024]; | ||
| 588 | + fs.mock_reset_offset(); | ||
| 589 | + | ||
| 590 | + EXPECT_TRUE(ERROR_SUCCESS == dec.read_header_ext(data)); | ||
| 591 | + EXPECT_TRUE(srs_bytes_equals(flv_header, data, 9)); | ||
| 592 | +} | ||
| 593 | + | ||
| 594 | +VOID TEST(KernelFlvTest, FlvVSDecoderSequenceHeader) | ||
| 595 | +{ | ||
| 596 | + MockSrsFileReader fs; | ||
| 597 | + SrsFlvVodStreamDecoder dec; | ||
| 598 | + ASSERT_TRUE(ERROR_SUCCESS == fs.open("")); | ||
| 599 | + ASSERT_TRUE(ERROR_SUCCESS == dec.initialize(&fs)); | ||
| 600 | + | ||
| 601 | + if (true) { | ||
| 602 | + // 11 bytes tag header | ||
| 603 | + char tag_header[] = { | ||
| 604 | + (char)18, // TagType UB [5], 18 = script data | ||
| 605 | + (char)0x00, (char)0x00, (char)0x08, // DataSize UI24 Length of the message. | ||
| 606 | + (char)0x00, (char)0x00, (char)0x00, // Timestamp UI24 Time in milliseconds at which the data in this tag applies. | ||
| 607 | + (char)0x00, // TimestampExtended UI8 | ||
| 608 | + (char)0x00, (char)0x00, (char)0x00, // StreamID UI24 Always 0. | ||
| 609 | + }; | ||
| 610 | + char md[] = { | ||
| 611 | + (char)0x01, (char)0x02, (char)0x03, (char)0x04, | ||
| 612 | + (char)0x04, (char)0x03, (char)0x02, (char)0x01 | ||
| 613 | + }; | ||
| 614 | + char pts[] = { (char)0x00, (char)0x00, (char)0x00, (char)19 }; | ||
| 615 | + fs.mock_append_data(tag_header, 11); | ||
| 616 | + fs.mock_append_data(md, 8); | ||
| 617 | + fs.mock_append_data(pts, 4); | ||
| 618 | + } | ||
| 619 | + if (true) { | ||
| 620 | + // 11bytes tag header | ||
| 621 | + char tag_header[] = { | ||
| 622 | + (char)8, // TagType UB [5], 8 = audio | ||
| 623 | + (char)0x00, (char)0x00, (char)0x08, // DataSize UI24 Length of the message. | ||
| 624 | + (char)0x00, (char)0x00, (char)0x30, // Timestamp UI24 Time in milliseconds at which the data in this tag applies. | ||
| 625 | + (char)0x00, // TimestampExtended UI8 | ||
| 626 | + (char)0x00, (char)0x00, (char)0x00, // StreamID UI24 Always 0. | ||
| 627 | + }; | ||
| 628 | + char audio[] = { | ||
| 629 | + (char)0x01, (char)0x02, (char)0x03, (char)0x04, | ||
| 630 | + (char)0x04, (char)0x03, (char)0x02, (char)0x01 | ||
| 631 | + }; | ||
| 632 | + char pts[] = { (char)0x00, (char)0x00, (char)0x00, (char)19 }; | ||
| 633 | + fs.mock_append_data(tag_header, 11); | ||
| 634 | + fs.mock_append_data(audio, 8); | ||
| 635 | + fs.mock_append_data(pts, 4); | ||
| 636 | + } | ||
| 637 | + if (true) { | ||
| 638 | + // 11bytes tag header | ||
| 639 | + char tag_header[] = { | ||
| 640 | + (char)9, // TagType UB [5], 9 = video | ||
| 641 | + (char)0x00, (char)0x00, (char)0x08, // DataSize UI24 Length of the message. | ||
| 642 | + (char)0x00, (char)0x00, (char)0x30, // Timestamp UI24 Time in milliseconds at which the data in this tag applies. | ||
| 643 | + (char)0x00, // TimestampExtended UI8 | ||
| 644 | + (char)0x00, (char)0x00, (char)0x00, // StreamID UI24 Always 0. | ||
| 645 | + }; | ||
| 646 | + char video[] = { | ||
| 647 | + (char)0x01, (char)0x02, (char)0x03, (char)0x04, | ||
| 648 | + (char)0x04, (char)0x03, (char)0x02, (char)0x01 | ||
| 649 | + }; | ||
| 650 | + char pts[] = { (char)0x00, (char)0x00, (char)0x00, (char)19 }; | ||
| 651 | + fs.mock_append_data(tag_header, 11); | ||
| 652 | + fs.mock_append_data(video, 8); | ||
| 653 | + fs.mock_append_data(pts, 4); | ||
| 654 | + } | ||
| 655 | + | ||
| 656 | + fs.mock_reset_offset(); | ||
| 657 | + | ||
| 658 | + int64_t start = 0; | ||
| 659 | + int size = 0; | ||
| 660 | + EXPECT_TRUE(ERROR_SUCCESS == dec.read_sequence_header_summary(&start, &size)); | ||
| 661 | + EXPECT_TRUE(23 == start); | ||
| 662 | + EXPECT_TRUE(46 == size); | ||
| 663 | +} | ||
| 664 | + | ||
| 665 | +VOID TEST(KernelFlvTest, FlvVSDecoderSeek) | ||
| 666 | +{ | ||
| 667 | + MockSrsFileReader fs; | ||
| 668 | + SrsFlvVodStreamDecoder dec; | ||
| 669 | + ASSERT_TRUE(ERROR_SUCCESS == fs.open("")); | ||
| 670 | + ASSERT_TRUE(ERROR_SUCCESS == dec.initialize(&fs)); | ||
| 671 | + | ||
| 672 | + // 11bytes tag header | ||
| 673 | + char tag_header[] = { | ||
| 674 | + (char)8, // TagType UB [5], 8 = audio | ||
| 675 | + (char)0x00, (char)0x00, (char)0x08, // DataSize UI24 Length of the message. | ||
| 676 | + (char)0x00, (char)0x00, (char)0x30, // Timestamp UI24 Time in milliseconds at which the data in this tag applies. | ||
| 677 | + (char)0x00, // TimestampExtended UI8 | ||
| 678 | + (char)0x00, (char)0x00, (char)0x00, // StreamID UI24 Always 0. | ||
| 679 | + }; | ||
| 680 | + fs.mock_append_data(tag_header, 11); | ||
| 681 | + EXPECT_TRUE(11 == fs.offset); | ||
| 682 | + | ||
| 683 | + EXPECT_TRUE(ERROR_SUCCESS == dec.lseek(0)); | ||
| 684 | + EXPECT_TRUE(0 == fs.offset); | ||
| 685 | + | ||
| 686 | + EXPECT_TRUE(ERROR_SUCCESS == dec.lseek(5)); | ||
| 687 | + EXPECT_TRUE(5 == fs.offset); | ||
| 204 | } | 688 | } |
| @@ -35,6 +35,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -35,6 +35,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 35 | class MockSrsFileWriter : public SrsFileWriter | 35 | class MockSrsFileWriter : public SrsFileWriter |
| 36 | { | 36 | { |
| 37 | public: | 37 | public: |
| 38 | + char* data; | ||
| 39 | + int offset; | ||
| 40 | +public: | ||
| 38 | MockSrsFileWriter(); | 41 | MockSrsFileWriter(); |
| 39 | virtual ~MockSrsFileWriter(); | 42 | virtual ~MockSrsFileWriter(); |
| 40 | public: | 43 | public: |
| @@ -45,11 +48,18 @@ public: | @@ -45,11 +48,18 @@ public: | ||
| 45 | virtual int64_t tellg(); | 48 | virtual int64_t tellg(); |
| 46 | public: | 49 | public: |
| 47 | virtual int write(void* buf, size_t count, ssize_t* pnwrite); | 50 | virtual int write(void* buf, size_t count, ssize_t* pnwrite); |
| 51 | +// for mock | ||
| 52 | +public: | ||
| 53 | + void mock_reset_offset(); | ||
| 48 | }; | 54 | }; |
| 49 | 55 | ||
| 50 | class MockSrsFileReader : public SrsFileReader | 56 | class MockSrsFileReader : public SrsFileReader |
| 51 | { | 57 | { |
| 52 | public: | 58 | public: |
| 59 | + char* data; | ||
| 60 | + int size; | ||
| 61 | + int offset; | ||
| 62 | +public: | ||
| 53 | MockSrsFileReader(); | 63 | MockSrsFileReader(); |
| 54 | virtual ~MockSrsFileReader(); | 64 | virtual ~MockSrsFileReader(); |
| 55 | public: | 65 | public: |
| @@ -63,6 +73,11 @@ public: | @@ -63,6 +73,11 @@ public: | ||
| 63 | virtual int64_t filesize(); | 73 | virtual int64_t filesize(); |
| 64 | public: | 74 | public: |
| 65 | virtual int read(void* buf, size_t count, ssize_t* pnread); | 75 | virtual int read(void* buf, size_t count, ssize_t* pnread); |
| 76 | +// for mock | ||
| 77 | +public: | ||
| 78 | + // append data to current offset, modify the offset and size. | ||
| 79 | + void mock_append_data(const char* _data, int _size); | ||
| 80 | + void mock_reset_offset(); | ||
| 66 | }; | 81 | }; |
| 67 | 82 | ||
| 68 | #endif | 83 | #endif |
-
请 注册 或 登录 后发表评论