winlin

add flv injecter, add flv codec to librtmp.

@@ -446,7 +446,8 @@ CORE_OBJS="${MODULE_OBJS[@]}" @@ -446,7 +446,8 @@ CORE_OBJS="${MODULE_OBJS[@]}"
446 MODULE_ID="KERNEL" 446 MODULE_ID="KERNEL"
447 MODULE_DEPENDS=("CORE") 447 MODULE_DEPENDS=("CORE")
448 ModuleLibIncs=(${SRS_OBJS}) 448 ModuleLibIncs=(${SRS_OBJS})
449 -MODULE_FILES=("srs_kernel_error" "srs_kernel_log" "srs_kernel_stream" "srs_kernel_buffer" "srs_kernel_utility") 449 +MODULE_FILES=("srs_kernel_error" "srs_kernel_log" "srs_kernel_stream" "srs_kernel_buffer"
  450 + "srs_kernel_utility" "srs_kernel_flv")
450 KERNEL_INCS="src/kernel"; MODULE_DIR=${KERNEL_INCS} . auto/modules.sh 451 KERNEL_INCS="src/kernel"; MODULE_DIR=${KERNEL_INCS} . auto/modules.sh
451 KERNEL_OBJS="${MODULE_OBJS[@]}" 452 KERNEL_OBJS="${MODULE_OBJS[@]}"
452 # 453 #
@@ -468,8 +469,7 @@ MODULE_FILES=("srs_app_server" "srs_app_conn" "srs_app_rtmp_conn" "srs_app_socke @@ -468,8 +469,7 @@ MODULE_FILES=("srs_app_server" "srs_app_conn" "srs_app_rtmp_conn" "srs_app_socke
468 "srs_app_thread" "srs_app_bandwidth" "srs_app_st" "srs_app_log" "srs_app_config" 469 "srs_app_thread" "srs_app_bandwidth" "srs_app_st" "srs_app_log" "srs_app_config"
469 "srs_app_pithy_print" "srs_app_reload" "srs_app_http_api" "srs_app_http_conn" "srs_app_http_hooks" 470 "srs_app_pithy_print" "srs_app_reload" "srs_app_http_api" "srs_app_http_conn" "srs_app_http_hooks"
470 "srs_app_json" "srs_app_ingest" "srs_app_ffmpeg" "srs_app_utility" "srs_app_dvr" "srs_app_edge" 471 "srs_app_json" "srs_app_ingest" "srs_app_ffmpeg" "srs_app_utility" "srs_app_dvr" "srs_app_edge"
471 - "srs_app_kbps" "srs_app_heartbeat" "srs_app_empty" "srs_app_http_client"  
472 - "srs_app_flv") 472 + "srs_app_kbps" "srs_app_heartbeat" "srs_app_empty" "srs_app_http_client")
473 APP_INCS="src/app"; MODULE_DIR=${APP_INCS} . auto/modules.sh 473 APP_INCS="src/app"; MODULE_DIR=${APP_INCS} . auto/modules.sh
474 APP_OBJS="${MODULE_OBJS[@]}" 474 APP_OBJS="${MODULE_OBJS[@]}"
475 # 475 #
@@ -3,7 +3,7 @@ GCC = gcc @@ -3,7 +3,7 @@ GCC = gcc
3 ifeq ($(HANDSHAKE),) 3 ifeq ($(HANDSHAKE),)
4 ST_ALL = help 4 ST_ALL = help
5 else 5 else
6 - ST_ALL = srs_flv_parser srs_publish srs_play srs_ingest_flv srs_ingest_rtmp 6 + ST_ALL = srs_flv_parser srs_flv_injecter srs_publish srs_play srs_ingest_flv srs_ingest_rtmp
7 endif 7 endif
8 8
9 .PHONY: default clean help ssl nossl 9 .PHONY: default clean help ssl nossl
@@ -11,12 +11,13 @@ endif @@ -11,12 +11,13 @@ endif
11 default: $(ST_ALL) 11 default: $(ST_ALL)
12 12
13 help: 13 help:
14 - @echo "Usage: make <help>|<clean>|<srs_flv_parser>|<srs_publish>|<srs_play>|<srs_ingest_flv>|<srs_ingest_rtmp>" 14 + @echo "Usage: make <help>|<clean>|<srs_flv_parser>|<srs_flv_injecter>|<srs_publish>|<srs_play>|<srs_ingest_flv>|<srs_ingest_rtmp>"
15 @echo " help display this help" 15 @echo " help display this help"
16 @echo " clean cleanup build" 16 @echo " clean cleanup build"
17 @echo " ssl all tools link ssl" 17 @echo " ssl all tools link ssl"
18 @echo " nossl all tools never link ssl" 18 @echo " nossl all tools never link ssl"
19 @echo " srs_flv_parser parse flv file, print detail info." 19 @echo " srs_flv_parser parse flv file, print detail info."
  20 + @echo " srs_flv_injecter inject keyframes information to metadata."
20 @echo " srs_publish publish program using srs-librtmp" 21 @echo " srs_publish publish program using srs-librtmp"
21 @echo " srs_play play program using srs-librtmp" 22 @echo " srs_play play program using srs-librtmp"
22 @echo " srs_ingest_flv ingest flv file and publish to RTMP server." 23 @echo " srs_ingest_flv ingest flv file and publish to RTMP server."
@@ -29,7 +30,7 @@ help: @@ -29,7 +30,7 @@ help:
29 @echo "Remark: before make this sample, user must make the srs, with/without ssl" 30 @echo "Remark: before make this sample, user must make the srs, with/without ssl"
30 31
31 clean: 32 clean:
32 - @rm -f srs_flv_parser srs_publish srs_play srs_ingest_flv srs_ingest_rtmp 33 + @rm -f srs_flv_parser srs_flv_injecter srs_publish srs_play srs_ingest_flv srs_ingest_rtmp
33 34
34 # srs library root 35 # srs library root
35 SRS_OBJS = ../../objs 36 SRS_OBJS = ../../objs
@@ -66,6 +67,9 @@ nossl: @@ -66,6 +67,9 @@ nossl:
66 srs_flv_parser: srs_flv_parser.c $(SRS_RESEARCH_DEPS) $(SRS_LIBRTMP_I) $(SRS_LIBRTMP_L) 67 srs_flv_parser: srs_flv_parser.c $(SRS_RESEARCH_DEPS) $(SRS_LIBRTMP_I) $(SRS_LIBRTMP_L)
67 $(GCC) srs_flv_parser.c $(SRS_LIBRTMP_L) $(SRS_LIBSSL_L) $(EXTRA_CXX_FLAG) -o srs_flv_parser 68 $(GCC) srs_flv_parser.c $(SRS_LIBRTMP_L) $(SRS_LIBSSL_L) $(EXTRA_CXX_FLAG) -o srs_flv_parser
68 69
  70 +srs_flv_injecter: srs_flv_injecter.c $(SRS_RESEARCH_DEPS) $(SRS_LIBRTMP_I) $(SRS_LIBRTMP_L)
  71 + $(GCC) srs_flv_injecter.c $(SRS_LIBRTMP_L) $(SRS_LIBSSL_L) $(EXTRA_CXX_FLAG) -o srs_flv_injecter
  72 +
69 srs_publish: srs_publish.c $(SRS_RESEARCH_DEPS) $(SRS_LIBRTMP_I) $(SRS_LIBRTMP_L) $(SRS_LIBSSL_L) 73 srs_publish: srs_publish.c $(SRS_RESEARCH_DEPS) $(SRS_LIBRTMP_I) $(SRS_LIBRTMP_L) $(SRS_LIBSSL_L)
70 $(GCC) srs_publish.c $(SRS_LIBRTMP_L) $(SRS_LIBSSL_L) $(EXTRA_CXX_FLAG) -o srs_publish 74 $(GCC) srs_publish.c $(SRS_LIBRTMP_L) $(SRS_LIBSSL_L) $(EXTRA_CXX_FLAG) -o srs_publish
71 75
  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 +gcc srs_flv_injecter.c ../../objs/lib/srs_librtmp.a -g -O0 -lstdc++ -o srs_flv_injecter
  25 +*/
  26 +
  27 +#include <stdio.h>
  28 +#include <stdlib.h>
  29 +#include <unistd.h>
  30 +
  31 +#include <sys/types.h>
  32 +#include <sys/stat.h>
  33 +#include <fcntl.h>
  34 +
  35 +#include "../../objs/include/srs_librtmp.h"
  36 +#include "srs_research_public.h"
  37 +#include "srs_flv_codec.h"
  38 +
  39 +int process(const char* in_flv_file, const char* out_flv_file, srs_flv_t* pic, srs_flv_t* poc);
  40 +int inject_flv(srs_flv_t ic, srs_flv_t oc);
  41 +int main(int argc, char** argv)
  42 +{
  43 + int ret = 0;
  44 +
  45 + // user options.
  46 + char* in_flv_file;
  47 + char* out_flv_file;
  48 + // flv handler
  49 + srs_flv_t ic = NULL;
  50 + srs_flv_t oc = NULL;
  51 +
  52 + // temp variables.
  53 + char* tmp_file;
  54 +
  55 + if (argc <= 2) {
  56 + printf("inject flv file keyframes to metadata\n"
  57 + "Usage: %s in_flv_file out_flv_file\n"
  58 + " in_flv_file input flv file to inject.\n"
  59 + " out_flv_file the inject output file, can be in_flv_file.\n"
  60 + "For example:\n"
  61 + " %s ../../doc/source.200kbps.768x320.flv injected.flv\n",
  62 + argv[0]);
  63 + ret = 1;
  64 + exit(ret);
  65 + return ret;
  66 + }
  67 +
  68 + in_flv_file = argv[1];
  69 + out_flv_file = argv[2];
  70 +
  71 + tmp_file = (char*)malloc(strlen(out_flv_file) + strlen(".tmp") + 1);
  72 +
  73 + trace("inject flv file keyframes to metadata.");
  74 + trace("srs(simple-rtmp-server) client librtmp library.");
  75 + trace("version: %d.%d.%d", srs_version_major(), srs_version_minor(), srs_version_revision());
  76 + trace("input: %s", in_flv_file);
  77 + trace("output: %s", out_flv_file);
  78 +
  79 + if ((ret = process(in_flv_file, out_flv_file, &ic, &oc)) != 0) {
  80 + return ret;
  81 + }
  82 +
  83 + srs_flv_close(ic);
  84 + srs_flv_close(oc);
  85 + free(tmp_file);
  86 +
  87 + return ret;
  88 +}
  89 +
  90 +int process(const char* in_flv_file, const char* out_flv_file, srs_flv_t* pic, srs_flv_t* poc)
  91 +{
  92 + int ret = 0;
  93 +
  94 + if ((*pic = srs_flv_open_read(in_flv_file)) == NULL) {
  95 + ret = 2;
  96 + trace("open input flv file failed. ret=%d", ret);
  97 + return ret;
  98 + }
  99 +
  100 + if ((*poc = srs_flv_open_write(out_flv_file)) == NULL) {
  101 + ret = 2;
  102 + trace("open output flv file failed. ret=%d", ret);
  103 + return ret;
  104 + }
  105 +
  106 + if ((ret = inject_flv(*pic, *poc)) != 0) {
  107 + return ret;
  108 + }
  109 +
  110 + return ret;
  111 +}
  112 +
  113 +int inject_flv(srs_flv_t ic, srs_flv_t oc)
  114 +{
  115 + int ret = 0;
  116 +
  117 + return ret;
  118 +}
@@ -36,7 +36,7 @@ gcc srs_ingest_flv.c ../../objs/lib/srs_librtmp.a -g -O0 -lstdc++ -o srs_ingest_ @@ -36,7 +36,7 @@ gcc srs_ingest_flv.c ../../objs/lib/srs_librtmp.a -g -O0 -lstdc++ -o srs_ingest_
36 #include "srs_research_public.h" 36 #include "srs_research_public.h"
37 #include "srs_flv_codec.h" 37 #include "srs_flv_codec.h"
38 38
39 -int parse_flv(int flv_fd); 39 +int parse_flv(srs_flv_t flv);
40 int main(int argc, char** argv) 40 int main(int argc, char** argv)
41 { 41 {
42 int ret = 0; 42 int ret = 0;
@@ -44,7 +44,7 @@ int main(int argc, char** argv) @@ -44,7 +44,7 @@ int main(int argc, char** argv)
44 // user options. 44 // user options.
45 char* in_flv_file; 45 char* in_flv_file;
46 // flv handler 46 // flv handler
47 - int flv_fd; 47 + srs_flv_t flv;
48 48
49 if (argc <= 1) { 49 if (argc <= 1) {
50 printf("parse and show flv file detail\n" 50 printf("parse and show flv file detail\n"
@@ -65,15 +65,14 @@ int main(int argc, char** argv) @@ -65,15 +65,14 @@ int main(int argc, char** argv)
65 trace("version: %d.%d.%d", srs_version_major(), srs_version_minor(), srs_version_revision()); 65 trace("version: %d.%d.%d", srs_version_major(), srs_version_minor(), srs_version_revision());
66 trace("input: %s", in_flv_file); 66 trace("input: %s", in_flv_file);
67 67
68 - flv_fd = open_flv_file(in_flv_file);  
69 - if (flv_fd <= 0) { 68 + if ((flv = srs_flv_open_read(in_flv_file)) == NULL) {
70 ret = 2; 69 ret = 2;
71 trace("open flv file failed. ret=%d", ret); 70 trace("open flv file failed. ret=%d", ret);
72 return ret; 71 return ret;
73 } 72 }
74 73
75 - ret = parse_flv(flv_fd);  
76 - close_flv_file(flv_fd); 74 + ret = parse_flv(flv);
  75 + srs_flv_close(flv);
77 76
78 return ret; 77 return ret;
79 } 78 }
@@ -207,26 +206,30 @@ int parse_video_data(u_int32_t timestamp, char* data, int size, int64_t offset) @@ -207,26 +206,30 @@ int parse_video_data(u_int32_t timestamp, char* data, int size, int64_t offset)
207 return ret; 206 return ret;
208 } 207 }
209 208
210 -int parse_flv(int flv_fd) 209 +int parse_flv(srs_flv_t flv)
211 { 210 {
212 int ret = 0; 211 int ret = 0;
213 212
214 - if ((ret = flv_open_ic(flv_fd)) != 0) {  
215 - return ret;  
216 - }  
217 - 213 + // flv header
  214 + char header[13];
218 // packet data 215 // packet data
219 - int type, size; 216 + char type;
220 u_int32_t timestamp = 0; 217 u_int32_t timestamp = 0;
221 char* data = NULL; 218 char* data = NULL;
  219 + int32_t size;
222 int64_t offset = 0; 220 int64_t offset = 0;
223 221
  222 + if ((ret = srs_flv_read_header(flv, header)) != 0) {
  223 + return ret;
  224 + }
  225 +
224 trace("start parse flv"); 226 trace("start parse flv");
225 for (;;) { 227 for (;;) {
226 - offset = lseek(flv_fd, 0, SEEK_CUR); 228 + offset = srs_flv_tellg(flv);
227 229
228 - if ((ret = flv_read_packet(flv_fd, &type, &timestamp, &data, &size)) != 0) {  
229 - if (ret == ERROR_FLV_CODEC_EOF) { 230 + // tag header
  231 + if ((ret = srs_flv_read_tag_header(flv, &type, &size, &timestamp)) != 0) {
  232 + if (srs_flv_is_eof(ret)) {
230 trace("parse completed."); 233 trace("parse completed.");
231 return 0; 234 return 0;
232 } 235 }
@@ -234,6 +237,16 @@ int parse_flv(int flv_fd) @@ -234,6 +237,16 @@ int parse_flv(int flv_fd)
234 return ret; 237 return ret;
235 } 238 }
236 239
  240 + if (size <= 0) {
  241 + trace("invalid size=%d", size);
  242 + break;
  243 + }
  244 +
  245 + data = (char*)malloc(size);
  246 + if ((ret = srs_flv_read_tag_data(flv, data, size)) != 0) {
  247 + return ret;
  248 + }
  249 +
237 // data tag 250 // data tag
238 if (type == SRS_RTMP_TYPE_AUDIO) { 251 if (type == SRS_RTMP_TYPE_AUDIO) {
239 if ((ret = parse_audio_data(timestamp, data, size, offset)) != 0) { 252 if ((ret = parse_audio_data(timestamp, data, size, offset)) != 0) {
@@ -39,7 +39,7 @@ using namespace std; @@ -39,7 +39,7 @@ using namespace std;
39 #include <srs_kernel_utility.hpp> 39 #include <srs_kernel_utility.hpp>
40 #include <srs_app_http_hooks.hpp> 40 #include <srs_app_http_hooks.hpp>
41 #include <srs_app_codec.hpp> 41 #include <srs_app_codec.hpp>
42 -#include <srs_app_flv.hpp> 42 +#include <srs_kernel_flv.hpp>
43 43
44 SrsFlvSegment::SrsFlvSegment() 44 SrsFlvSegment::SrsFlvSegment()
45 { 45 {
@@ -40,7 +40,7 @@ using namespace std; @@ -40,7 +40,7 @@ using namespace std;
40 #include <srs_core_autofree.hpp> 40 #include <srs_core_autofree.hpp>
41 #include <srs_app_json.hpp> 41 #include <srs_app_json.hpp>
42 #include <srs_app_config.hpp> 42 #include <srs_app_config.hpp>
43 -#include <srs_app_flv.hpp> 43 +#include <srs_kernel_flv.hpp>
44 44
45 #define SRS_HTTP_DEFAULT_PAGE "index.html" 45 #define SRS_HTTP_DEFAULT_PAGE "index.html"
46 46
@@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 // current release version 31 // current release version
32 #define VERSION_MAJOR "0" 32 #define VERSION_MAJOR "0"
33 #define VERSION_MINOR "9" 33 #define VERSION_MINOR "9"
34 -#define VERSION_REVISION "120" 34 +#define VERSION_REVISION "121"
35 #define RTMP_SIG_SRS_VERSION VERSION_MAJOR"."VERSION_MINOR"."VERSION_REVISION 35 #define RTMP_SIG_SRS_VERSION VERSION_MAJOR"."VERSION_MINOR"."VERSION_REVISION
36 // server info. 36 // server info.
37 #define RTMP_SIG_SRS_KEY "SRS" 37 #define RTMP_SIG_SRS_KEY "SRS"
@@ -118,6 +118,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -118,6 +118,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
118 #define ERROR_SYSTEM_FILE_RENAME 429 118 #define ERROR_SYSTEM_FILE_RENAME 429
119 #define ERROR_SYSTEM_CREATE_PIPE 430 119 #define ERROR_SYSTEM_CREATE_PIPE 430
120 #define ERROR_SYSTEM_FILE_SEEK 431 120 #define ERROR_SYSTEM_FILE_SEEK 431
  121 +#define ERROR_SYSTEM_FLV_HEADER 432
121 122
122 // see librtmp. 123 // see librtmp.
123 // failed when open ssl create the dh 124 // failed when open ssl create the dh
@@ -21,22 +21,17 @@ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN @@ -21,22 +21,17 @@ 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. 21 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */ 22 */
23 23
24 -#include <srs_app_flv.hpp> 24 +#include <srs_kernel_flv.hpp>
25 25
26 #include <fcntl.h> 26 #include <fcntl.h>
27 #include <sstream> 27 #include <sstream>
28 using namespace std; 28 using namespace std;
29 29
30 -#include <srs_app_config.hpp> 30 +#include <srs_kernel_log.hpp>
31 #include <srs_kernel_error.hpp> 31 #include <srs_kernel_error.hpp>
32 -#include <srs_protocol_rtmp.hpp>  
33 -#include <srs_protocol_rtmp_stack.hpp>  
34 -#include <srs_app_source.hpp>  
35 #include <srs_core_autofree.hpp> 32 #include <srs_core_autofree.hpp>
36 #include <srs_kernel_stream.hpp> 33 #include <srs_kernel_stream.hpp>
37 #include <srs_kernel_utility.hpp> 34 #include <srs_kernel_utility.hpp>
38 -#include <srs_app_http_hooks.hpp>  
39 -#include <srs_app_codec.hpp>  
40 35
41 #define SRS_FLV_TAG_HEADER_SIZE 11 36 #define SRS_FLV_TAG_HEADER_SIZE 11
42 #define SRS_FLV_PREVIOUS_TAG_SIZE 4 37 #define SRS_FLV_PREVIOUS_TAG_SIZE 4
@@ -509,3 +504,109 @@ int SrsFlvFastDecoder::lseek(int64_t offset) @@ -509,3 +504,109 @@ int SrsFlvFastDecoder::lseek(int64_t offset)
509 504
510 return ret; 505 return ret;
511 } 506 }
  507 +
  508 +SrsFlvDecoder::SrsFlvDecoder()
  509 +{
  510 + _fs = NULL;
  511 + tag_stream = new SrsStream();
  512 +}
  513 +
  514 +SrsFlvDecoder::~SrsFlvDecoder()
  515 +{
  516 + srs_freep(tag_stream);
  517 +}
  518 +
  519 +int SrsFlvDecoder::initialize(SrsFileStream* fs)
  520 +{
  521 + int ret = ERROR_SUCCESS;
  522 +
  523 + _fs = fs;
  524 +
  525 + return ret;
  526 +}
  527 +
  528 +int SrsFlvDecoder::read_header(char header[9])
  529 +{
  530 + int ret = ERROR_SUCCESS;
  531 +
  532 + if ((ret = _fs->read(header, 9, NULL)) != ERROR_SUCCESS) {
  533 + return ret;
  534 + }
  535 +
  536 + char* h = header;
  537 + if (h[0] != 'F' || h[1] != 'L' || h[2] != 'V') {
  538 + ret = ERROR_SYSTEM_FLV_HEADER;
  539 + srs_warn("flv header must start with FLV. ret=%d", ret);
  540 + return ret;
  541 + }
  542 +
  543 + return ret;
  544 +}
  545 +
  546 +int SrsFlvDecoder::read_tag_header(char* ptype, int32_t* pdata_size, u_int32_t* ptime)
  547 +{
  548 + int ret = ERROR_SUCCESS;
  549 +
  550 + char th[11]; // tag header
  551 +
  552 + // read tag header
  553 + if ((ret = _fs->read(th, 11, NULL)) != ERROR_SUCCESS) {
  554 + if (ret != ERROR_SYSTEM_FILE_EOF) {
  555 + srs_error("read flv tag header failed. ret=%d", ret);
  556 + }
  557 + return ret;
  558 + }
  559 +
  560 + // Reserved UB [2]
  561 + // Filter UB [1]
  562 + // TagType UB [5]
  563 + *ptype = (int)(th[0] & 0x1F);
  564 +
  565 + // DataSize UI24
  566 + char* pp = (char*)pdata_size;
  567 + pp[2] = th[1];
  568 + pp[1] = th[2];
  569 + pp[0] = th[3];
  570 +
  571 + // Timestamp UI24
  572 + pp = (char*)ptime;
  573 + pp[2] = th[4];
  574 + pp[1] = th[5];
  575 + pp[0] = th[6];
  576 +
  577 + // TimestampExtended UI8
  578 + pp[3] = th[7];
  579 +
  580 + return ret;
  581 +}
  582 +
  583 +int SrsFlvDecoder::read_tag_data(char* data, int32_t size)
  584 +{
  585 + int ret = ERROR_SUCCESS;
  586 +
  587 + if ((ret = _fs->read(data, size, NULL)) != ERROR_SUCCESS) {
  588 + if (ret != ERROR_SYSTEM_FILE_EOF) {
  589 + srs_error("read flv tag header failed. ret=%d", ret);
  590 + }
  591 + return ret;
  592 + }
  593 +
  594 + return ret;
  595 +
  596 +}
  597 +
  598 +int SrsFlvDecoder::read_previous_tag_size(char ts[4])
  599 +{
  600 + int ret = ERROR_SUCCESS;
  601 +
  602 + // ignore 4bytes tag size.
  603 + if ((ret = _fs->read(ts, 4, NULL)) != ERROR_SUCCESS) {
  604 + if (ret != ERROR_SYSTEM_FILE_EOF) {
  605 + srs_error("read flv previous tag size failed. ret=%d", ret);
  606 + }
  607 + return ret;
  608 + }
  609 +
  610 + return ret;
  611 +}
  612 +
@@ -25,7 +25,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -25,7 +25,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 #define SRS_APP_FLV_HPP 25 #define SRS_APP_FLV_HPP
26 26
27 /* 27 /*
28 -#include <srs_app_flv.hpp> 28 +#include <srs_kernel_flv.hpp>
29 */ 29 */
30 #include <srs_core.hpp> 30 #include <srs_core.hpp>
31 31
@@ -142,4 +142,29 @@ public: @@ -142,4 +142,29 @@ public:
142 virtual int lseek(int64_t offset); 142 virtual int lseek(int64_t offset);
143 }; 143 };
144 144
  145 +/**
  146 +* decode flv file.
  147 +*/
  148 +class SrsFlvDecoder
  149 +{
  150 +private:
  151 + SrsFileStream* _fs;
  152 +private:
  153 + SrsStream* tag_stream;
  154 +public:
  155 + SrsFlvDecoder();
  156 + virtual ~SrsFlvDecoder();
  157 +public:
  158 + /**
  159 + * initialize the underlayer file stream,
  160 + * user can initialize multiple times to decode multiple flv files.
  161 + */
  162 + virtual int initialize(SrsFileStream* fs);
  163 +public:
  164 + virtual int read_header(char header[9]);
  165 + virtual int read_tag_header(char* ptype, int32_t* pdata_size, u_int32_t* ptime);
  166 + virtual int read_tag_data(char* data, int32_t size);
  167 + virtual int read_previous_tag_size(char ts[4]);
  168 +};
  169 +
145 #endif 170 #endif
@@ -39,6 +39,7 @@ using namespace std; @@ -39,6 +39,7 @@ using namespace std;
39 #include <srs_kernel_utility.hpp> 39 #include <srs_kernel_utility.hpp>
40 #include <srs_kernel_stream.hpp> 40 #include <srs_kernel_stream.hpp>
41 #include <srs_protocol_amf0.hpp> 41 #include <srs_protocol_amf0.hpp>
  42 +#include <srs_kernel_flv.hpp>
42 43
43 // if user want to define log, define the folowing macro. 44 // if user want to define log, define the folowing macro.
44 #ifndef SRS_RTMP_USER_DEFINED_LOG 45 #ifndef SRS_RTMP_USER_DEFINED_LOG
@@ -382,6 +383,124 @@ int64_t srs_get_time_ms() @@ -382,6 +383,124 @@ int64_t srs_get_time_ms()
382 return srs_get_system_time_ms(); 383 return srs_get_system_time_ms();
383 } 384 }
384 385
  386 +struct FlvContext
  387 +{
  388 + SrsFileStream fs;
  389 + SrsFlvEncoder enc;
  390 + SrsFlvDecoder dec;
  391 +};
  392 +
  393 +srs_flv_t srs_flv_open_read(const char* file)
  394 +{
  395 + int ret = ERROR_SUCCESS;
  396 +
  397 + FlvContext* flv = new FlvContext();
  398 +
  399 + if ((ret = flv->fs.open_read(file)) != ERROR_SUCCESS) {
  400 + srs_freep(flv);
  401 + return NULL;
  402 + }
  403 +
  404 + if ((ret = flv->enc.initialize(&flv->fs)) != ERROR_SUCCESS) {
  405 + srs_freep(flv);
  406 + return NULL;
  407 + }
  408 +
  409 + if ((ret = flv->dec.initialize(&flv->fs)) != ERROR_SUCCESS) {
  410 + srs_freep(flv);
  411 + return NULL;
  412 + }
  413 +
  414 + return flv;
  415 +}
  416 +
  417 +srs_flv_t srs_flv_open_write(const char* file)
  418 +{
  419 + int ret = ERROR_SUCCESS;
  420 +
  421 + FlvContext* flv = new FlvContext();
  422 +
  423 + if ((ret = flv->fs.open_write(file)) != ERROR_SUCCESS) {
  424 + srs_freep(flv);
  425 + return NULL;
  426 + }
  427 +
  428 + if ((ret = flv->enc.initialize(&flv->fs)) != ERROR_SUCCESS) {
  429 + srs_freep(flv);
  430 + return NULL;
  431 + }
  432 +
  433 + if ((ret = flv->dec.initialize(&flv->fs)) != ERROR_SUCCESS) {
  434 + srs_freep(flv);
  435 + return NULL;
  436 + }
  437 +
  438 + return flv;
  439 +}
  440 +
  441 +void srs_flv_close(srs_flv_t flv)
  442 +{
  443 + FlvContext* context = (FlvContext*)flv;
  444 + srs_freep(context);
  445 +}
  446 +
  447 +int srs_flv_read_header(srs_flv_t flv, char header[9])
  448 +{
  449 + int ret = ERROR_SUCCESS;
  450 +
  451 + FlvContext* context = (FlvContext*)flv;
  452 + if ((ret = context->dec.read_header(header)) != ERROR_SUCCESS) {
  453 + return ret;
  454 + }
  455 +
  456 + char ts[4]; // tag size
  457 + if ((ret = context->dec.read_previous_tag_size(ts)) != ERROR_SUCCESS) {
  458 + return ret;
  459 + }
  460 +
  461 + return ret;
  462 +}
  463 +
  464 +int srs_flv_read_tag_header(srs_flv_t flv, char* ptype, int32_t* pdata_size, u_int32_t* ptime)
  465 +{
  466 + int ret = ERROR_SUCCESS;
  467 +
  468 + FlvContext* context = (FlvContext*)flv;
  469 + if ((ret = context->dec.read_tag_header(ptype, pdata_size, ptime)) != ERROR_SUCCESS) {
  470 + return ret;
  471 + }
  472 +
  473 + return ret;
  474 +}
  475 +
  476 +int srs_flv_read_tag_data(srs_flv_t flv, char* data, int32_t size)
  477 +{
  478 + int ret = ERROR_SUCCESS;
  479 +
  480 + FlvContext* context = (FlvContext*)flv;
  481 + if ((ret = context->dec.read_tag_data(data, size)) != ERROR_SUCCESS) {
  482 + return ret;
  483 + }
  484 +
  485 + char ts[4]; // tag size
  486 + if ((ret = context->dec.read_previous_tag_size(ts)) != ERROR_SUCCESS) {
  487 + return ret;
  488 + }
  489 +
  490 + return ret;
  491 +}
  492 +
  493 +int64_t srs_flv_tellg(srs_flv_t flv)
  494 +{
  495 + FlvContext* context = (FlvContext*)flv;
  496 + return context->fs.tellg();
  497 +}
  498 +
  499 +flv_bool srs_flv_is_eof(int error_code)
  500 +{
  501 + return error_code == ERROR_SYSTEM_FILE_EOF;
  502 +}
  503 +
385 srs_amf0_t srs_amf0_parse(char* data, int size, int* nparsed) 504 srs_amf0_t srs_amf0_parse(char* data, int size, int* nparsed)
386 { 505 {
387 int ret = ERROR_SUCCESS; 506 int ret = ERROR_SUCCESS;
@@ -152,6 +152,25 @@ int srs_version_revision(); @@ -152,6 +152,25 @@ int srs_version_revision();
152 int64_t srs_get_time_ms(); 152 int64_t srs_get_time_ms();
153 153
154 /** 154 /**
  155 +* flv codec
  156 +*/
  157 +typedef void* srs_flv_t;
  158 +typedef int flv_bool;
  159 +srs_flv_t srs_flv_open_read(const char* file);
  160 +srs_flv_t srs_flv_open_write(const char* file);
  161 +void srs_flv_close(srs_flv_t flv);
  162 +/* read the flv header. 9bytes header. drop the 4bytes zero previous tag size */
  163 +int srs_flv_read_header(srs_flv_t flv, char header[9]);
  164 +/* read the flv tag header, 1bytes tag, 3bytes data_size, 4bytes time, 3bytes stream id. */
  165 +int srs_flv_read_tag_header(srs_flv_t flv, char* ptype, int32_t* pdata_size, u_int32_t* ptime);
  166 +/* read the tag data. drop the 4bytes previous tag size */
  167 +int srs_flv_read_tag_data(srs_flv_t flv, char* data, int32_t size);
  168 +/* file stream tellg to get offset */
  169 +int64_t srs_flv_tellg(srs_flv_t flv);
  170 +/* whether the error code indicates EOF */
  171 +flv_bool srs_flv_is_eof(int error_code);
  172 +
  173 +/**
155 * amf0 codec 174 * amf0 codec
156 */ 175 */
157 /* the output handler. */ 176 /* the output handler. */
@@ -184,7 +203,12 @@ srs_amf0_t srs_amf0_ecma_array_property_value_at(srs_amf0_t amf0, int index); @@ -184,7 +203,12 @@ srs_amf0_t srs_amf0_ecma_array_property_value_at(srs_amf0_t amf0, int index);
184 /* strict array value converter */ 203 /* strict array value converter */
185 int srs_amf0_strict_array_property_count(srs_amf0_t amf0); 204 int srs_amf0_strict_array_property_count(srs_amf0_t amf0);
186 srs_amf0_t srs_amf0_strict_array_property_at(srs_amf0_t amf0, int index); 205 srs_amf0_t srs_amf0_strict_array_property_at(srs_amf0_t amf0, int index);
187 -/* human readable print */ 206 +/**
  207 +* human readable print
  208 +* @param pdata, output the heap data,
  209 +* user must use srs_amf0_free_bytes to free it.
  210 +* @return return the *pdata for print.
  211 +*/
188 char* srs_amf0_human_print(srs_amf0_t amf0, char** pdata, int* psize); 212 char* srs_amf0_human_print(srs_amf0_t amf0, char** pdata, int* psize);
189 213
190 #ifdef __cplusplus 214 #ifdef __cplusplus
@@ -19,6 +19,8 @@ file @@ -19,6 +19,8 @@ file
19 ..\kernel\srs_kernel_buffer.cpp, 19 ..\kernel\srs_kernel_buffer.cpp,
20 ..\kernel\srs_kernel_error.hpp, 20 ..\kernel\srs_kernel_error.hpp,
21 ..\kernel\srs_kernel_error.cpp, 21 ..\kernel\srs_kernel_error.cpp,
  22 + ..\kernel\srs_kernel_flv.hpp,
  23 + ..\kernel\srs_kernel_flv.cpp,
22 ..\kernel\srs_kernel_log.hpp, 24 ..\kernel\srs_kernel_log.hpp,
23 ..\kernel\srs_kernel_log.cpp, 25 ..\kernel\srs_kernel_log.cpp,
24 ..\kernel\srs_kernel_stream.hpp, 26 ..\kernel\srs_kernel_stream.hpp,
@@ -57,8 +59,6 @@ file @@ -57,8 +59,6 @@ file
57 ..\app\srs_app_encoder.cpp, 59 ..\app\srs_app_encoder.cpp,
58 ..\app\srs_app_ffmpeg.hpp, 60 ..\app\srs_app_ffmpeg.hpp,
59 ..\app\srs_app_ffmpeg.cpp, 61 ..\app\srs_app_ffmpeg.cpp,
60 - ..\app\srs_app_flv.hpp,  
61 - ..\app\srs_app_flv.cpp,  
62 ..\app\srs_app_forward.hpp, 62 ..\app\srs_app_forward.hpp,
63 ..\app\srs_app_forward.cpp, 63 ..\app\srs_app_forward.cpp,
64 ..\app\srs_app_heartbeat.hpp, 64 ..\app\srs_app_heartbeat.hpp,
@@ -112,6 +112,7 @@ file @@ -112,6 +112,7 @@ file
112 ..\utest\srs_utest_handshake.cpp, 112 ..\utest\srs_utest_handshake.cpp,
113 research readonly separator, 113 research readonly separator,
114 ..\..\research\librtmp\srs_flv_codec.h, 114 ..\..\research\librtmp\srs_flv_codec.h,
  115 + ..\..\research\librtmp\srs_flv_injecter.c,
115 ..\..\research\librtmp\srs_flv_parser.c, 116 ..\..\research\librtmp\srs_flv_parser.c,
116 ..\..\research\librtmp\srs_ingest_flv.c, 117 ..\..\research\librtmp\srs_ingest_flv.c,
117 ..\..\research\librtmp\srs_ingest_rtmp.c, 118 ..\..\research\librtmp\srs_ingest_rtmp.c,