mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
add flv injecter, add flv codec to librtmp.
This commit is contained in:
parent
99cfbaaad9
commit
608083d42f
13 changed files with 443 additions and 37 deletions
6
trunk/configure
vendored
6
trunk/configure
vendored
|
@ -446,7 +446,8 @@ CORE_OBJS="${MODULE_OBJS[@]}"
|
||||||
MODULE_ID="KERNEL"
|
MODULE_ID="KERNEL"
|
||||||
MODULE_DEPENDS=("CORE")
|
MODULE_DEPENDS=("CORE")
|
||||||
ModuleLibIncs=(${SRS_OBJS})
|
ModuleLibIncs=(${SRS_OBJS})
|
||||||
MODULE_FILES=("srs_kernel_error" "srs_kernel_log" "srs_kernel_stream" "srs_kernel_buffer" "srs_kernel_utility")
|
MODULE_FILES=("srs_kernel_error" "srs_kernel_log" "srs_kernel_stream" "srs_kernel_buffer"
|
||||||
|
"srs_kernel_utility" "srs_kernel_flv")
|
||||||
KERNEL_INCS="src/kernel"; MODULE_DIR=${KERNEL_INCS} . auto/modules.sh
|
KERNEL_INCS="src/kernel"; MODULE_DIR=${KERNEL_INCS} . auto/modules.sh
|
||||||
KERNEL_OBJS="${MODULE_OBJS[@]}"
|
KERNEL_OBJS="${MODULE_OBJS[@]}"
|
||||||
#
|
#
|
||||||
|
@ -468,8 +469,7 @@ MODULE_FILES=("srs_app_server" "srs_app_conn" "srs_app_rtmp_conn" "srs_app_socke
|
||||||
"srs_app_thread" "srs_app_bandwidth" "srs_app_st" "srs_app_log" "srs_app_config"
|
"srs_app_thread" "srs_app_bandwidth" "srs_app_st" "srs_app_log" "srs_app_config"
|
||||||
"srs_app_pithy_print" "srs_app_reload" "srs_app_http_api" "srs_app_http_conn" "srs_app_http_hooks"
|
"srs_app_pithy_print" "srs_app_reload" "srs_app_http_api" "srs_app_http_conn" "srs_app_http_hooks"
|
||||||
"srs_app_json" "srs_app_ingest" "srs_app_ffmpeg" "srs_app_utility" "srs_app_dvr" "srs_app_edge"
|
"srs_app_json" "srs_app_ingest" "srs_app_ffmpeg" "srs_app_utility" "srs_app_dvr" "srs_app_edge"
|
||||||
"srs_app_kbps" "srs_app_heartbeat" "srs_app_empty" "srs_app_http_client"
|
"srs_app_kbps" "srs_app_heartbeat" "srs_app_empty" "srs_app_http_client")
|
||||||
"srs_app_flv")
|
|
||||||
APP_INCS="src/app"; MODULE_DIR=${APP_INCS} . auto/modules.sh
|
APP_INCS="src/app"; MODULE_DIR=${APP_INCS} . auto/modules.sh
|
||||||
APP_OBJS="${MODULE_OBJS[@]}"
|
APP_OBJS="${MODULE_OBJS[@]}"
|
||||||
#
|
#
|
||||||
|
|
10
trunk/research/librtmp/Makefile
Normal file → Executable file
10
trunk/research/librtmp/Makefile
Normal file → Executable file
|
@ -3,7 +3,7 @@ GCC = gcc
|
||||||
ifeq ($(HANDSHAKE),)
|
ifeq ($(HANDSHAKE),)
|
||||||
ST_ALL = help
|
ST_ALL = help
|
||||||
else
|
else
|
||||||
ST_ALL = srs_flv_parser srs_publish srs_play srs_ingest_flv srs_ingest_rtmp
|
ST_ALL = srs_flv_parser srs_flv_injecter srs_publish srs_play srs_ingest_flv srs_ingest_rtmp
|
||||||
endif
|
endif
|
||||||
|
|
||||||
.PHONY: default clean help ssl nossl
|
.PHONY: default clean help ssl nossl
|
||||||
|
@ -11,12 +11,13 @@ endif
|
||||||
default: $(ST_ALL)
|
default: $(ST_ALL)
|
||||||
|
|
||||||
help:
|
help:
|
||||||
@echo "Usage: make <help>|<clean>|<srs_flv_parser>|<srs_publish>|<srs_play>|<srs_ingest_flv>|<srs_ingest_rtmp>"
|
@echo "Usage: make <help>|<clean>|<srs_flv_parser>|<srs_flv_injecter>|<srs_publish>|<srs_play>|<srs_ingest_flv>|<srs_ingest_rtmp>"
|
||||||
@echo " help display this help"
|
@echo " help display this help"
|
||||||
@echo " clean cleanup build"
|
@echo " clean cleanup build"
|
||||||
@echo " ssl all tools link ssl"
|
@echo " ssl all tools link ssl"
|
||||||
@echo " nossl all tools never link ssl"
|
@echo " nossl all tools never link ssl"
|
||||||
@echo " srs_flv_parser parse flv file, print detail info."
|
@echo " srs_flv_parser parse flv file, print detail info."
|
||||||
|
@echo " srs_flv_injecter inject keyframes information to metadata."
|
||||||
@echo " srs_publish publish program using srs-librtmp"
|
@echo " srs_publish publish program using srs-librtmp"
|
||||||
@echo " srs_play play program using srs-librtmp"
|
@echo " srs_play play program using srs-librtmp"
|
||||||
@echo " srs_ingest_flv ingest flv file and publish to RTMP server."
|
@echo " srs_ingest_flv ingest flv file and publish to RTMP server."
|
||||||
|
@ -29,7 +30,7 @@ help:
|
||||||
@echo "Remark: before make this sample, user must make the srs, with/without ssl"
|
@echo "Remark: before make this sample, user must make the srs, with/without ssl"
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@rm -f srs_flv_parser srs_publish srs_play srs_ingest_flv srs_ingest_rtmp
|
@rm -f srs_flv_parser srs_flv_injecter srs_publish srs_play srs_ingest_flv srs_ingest_rtmp
|
||||||
|
|
||||||
# srs library root
|
# srs library root
|
||||||
SRS_OBJS = ../../objs
|
SRS_OBJS = ../../objs
|
||||||
|
@ -66,6 +67,9 @@ nossl:
|
||||||
srs_flv_parser: srs_flv_parser.c $(SRS_RESEARCH_DEPS) $(SRS_LIBRTMP_I) $(SRS_LIBRTMP_L)
|
srs_flv_parser: srs_flv_parser.c $(SRS_RESEARCH_DEPS) $(SRS_LIBRTMP_I) $(SRS_LIBRTMP_L)
|
||||||
$(GCC) srs_flv_parser.c $(SRS_LIBRTMP_L) $(SRS_LIBSSL_L) $(EXTRA_CXX_FLAG) -o srs_flv_parser
|
$(GCC) srs_flv_parser.c $(SRS_LIBRTMP_L) $(SRS_LIBSSL_L) $(EXTRA_CXX_FLAG) -o srs_flv_parser
|
||||||
|
|
||||||
|
srs_flv_injecter: srs_flv_injecter.c $(SRS_RESEARCH_DEPS) $(SRS_LIBRTMP_I) $(SRS_LIBRTMP_L)
|
||||||
|
$(GCC) srs_flv_injecter.c $(SRS_LIBRTMP_L) $(SRS_LIBSSL_L) $(EXTRA_CXX_FLAG) -o srs_flv_injecter
|
||||||
|
|
||||||
srs_publish: srs_publish.c $(SRS_RESEARCH_DEPS) $(SRS_LIBRTMP_I) $(SRS_LIBRTMP_L) $(SRS_LIBSSL_L)
|
srs_publish: srs_publish.c $(SRS_RESEARCH_DEPS) $(SRS_LIBRTMP_I) $(SRS_LIBRTMP_L) $(SRS_LIBSSL_L)
|
||||||
$(GCC) srs_publish.c $(SRS_LIBRTMP_L) $(SRS_LIBSSL_L) $(EXTRA_CXX_FLAG) -o srs_publish
|
$(GCC) srs_publish.c $(SRS_LIBRTMP_L) $(SRS_LIBSSL_L) $(EXTRA_CXX_FLAG) -o srs_publish
|
||||||
|
|
||||||
|
|
118
trunk/research/librtmp/srs_flv_injecter.c
Normal file
118
trunk/research/librtmp/srs_flv_injecter.c
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
/*
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2013-2014 winlin
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
gcc srs_flv_injecter.c ../../objs/lib/srs_librtmp.a -g -O0 -lstdc++ -o srs_flv_injecter
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#include "../../objs/include/srs_librtmp.h"
|
||||||
|
#include "srs_research_public.h"
|
||||||
|
#include "srs_flv_codec.h"
|
||||||
|
|
||||||
|
int process(const char* in_flv_file, const char* out_flv_file, srs_flv_t* pic, srs_flv_t* poc);
|
||||||
|
int inject_flv(srs_flv_t ic, srs_flv_t oc);
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
// user options.
|
||||||
|
char* in_flv_file;
|
||||||
|
char* out_flv_file;
|
||||||
|
// flv handler
|
||||||
|
srs_flv_t ic = NULL;
|
||||||
|
srs_flv_t oc = NULL;
|
||||||
|
|
||||||
|
// temp variables.
|
||||||
|
char* tmp_file;
|
||||||
|
|
||||||
|
if (argc <= 2) {
|
||||||
|
printf("inject flv file keyframes to metadata\n"
|
||||||
|
"Usage: %s in_flv_file out_flv_file\n"
|
||||||
|
" in_flv_file input flv file to inject.\n"
|
||||||
|
" out_flv_file the inject output file, can be in_flv_file.\n"
|
||||||
|
"For example:\n"
|
||||||
|
" %s ../../doc/source.200kbps.768x320.flv injected.flv\n",
|
||||||
|
argv[0]);
|
||||||
|
ret = 1;
|
||||||
|
exit(ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
in_flv_file = argv[1];
|
||||||
|
out_flv_file = argv[2];
|
||||||
|
|
||||||
|
tmp_file = (char*)malloc(strlen(out_flv_file) + strlen(".tmp") + 1);
|
||||||
|
|
||||||
|
trace("inject flv file keyframes to metadata.");
|
||||||
|
trace("srs(simple-rtmp-server) client librtmp library.");
|
||||||
|
trace("version: %d.%d.%d", srs_version_major(), srs_version_minor(), srs_version_revision());
|
||||||
|
trace("input: %s", in_flv_file);
|
||||||
|
trace("output: %s", out_flv_file);
|
||||||
|
|
||||||
|
if ((ret = process(in_flv_file, out_flv_file, &ic, &oc)) != 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
srs_flv_close(ic);
|
||||||
|
srs_flv_close(oc);
|
||||||
|
free(tmp_file);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int process(const char* in_flv_file, const char* out_flv_file, srs_flv_t* pic, srs_flv_t* poc)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if ((*pic = srs_flv_open_read(in_flv_file)) == NULL) {
|
||||||
|
ret = 2;
|
||||||
|
trace("open input flv file failed. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((*poc = srs_flv_open_write(out_flv_file)) == NULL) {
|
||||||
|
ret = 2;
|
||||||
|
trace("open output flv file failed. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ret = inject_flv(*pic, *poc)) != 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int inject_flv(srs_flv_t ic, srs_flv_t oc)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
|
@ -36,7 +36,7 @@ gcc srs_ingest_flv.c ../../objs/lib/srs_librtmp.a -g -O0 -lstdc++ -o srs_ingest_
|
||||||
#include "srs_research_public.h"
|
#include "srs_research_public.h"
|
||||||
#include "srs_flv_codec.h"
|
#include "srs_flv_codec.h"
|
||||||
|
|
||||||
int parse_flv(int flv_fd);
|
int parse_flv(srs_flv_t flv);
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
@ -44,7 +44,7 @@ int main(int argc, char** argv)
|
||||||
// user options.
|
// user options.
|
||||||
char* in_flv_file;
|
char* in_flv_file;
|
||||||
// flv handler
|
// flv handler
|
||||||
int flv_fd;
|
srs_flv_t flv;
|
||||||
|
|
||||||
if (argc <= 1) {
|
if (argc <= 1) {
|
||||||
printf("parse and show flv file detail\n"
|
printf("parse and show flv file detail\n"
|
||||||
|
@ -65,15 +65,14 @@ int main(int argc, char** argv)
|
||||||
trace("version: %d.%d.%d", srs_version_major(), srs_version_minor(), srs_version_revision());
|
trace("version: %d.%d.%d", srs_version_major(), srs_version_minor(), srs_version_revision());
|
||||||
trace("input: %s", in_flv_file);
|
trace("input: %s", in_flv_file);
|
||||||
|
|
||||||
flv_fd = open_flv_file(in_flv_file);
|
if ((flv = srs_flv_open_read(in_flv_file)) == NULL) {
|
||||||
if (flv_fd <= 0) {
|
|
||||||
ret = 2;
|
ret = 2;
|
||||||
trace("open flv file failed. ret=%d", ret);
|
trace("open flv file failed. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = parse_flv(flv_fd);
|
ret = parse_flv(flv);
|
||||||
close_flv_file(flv_fd);
|
srs_flv_close(flv);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -207,26 +206,30 @@ int parse_video_data(u_int32_t timestamp, char* data, int size, int64_t offset)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int parse_flv(int flv_fd)
|
int parse_flv(srs_flv_t flv)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if ((ret = flv_open_ic(flv_fd)) != 0) {
|
// flv header
|
||||||
|
char header[13];
|
||||||
|
// packet data
|
||||||
|
char type;
|
||||||
|
u_int32_t timestamp = 0;
|
||||||
|
char* data = NULL;
|
||||||
|
int32_t size;
|
||||||
|
int64_t offset = 0;
|
||||||
|
|
||||||
|
if ((ret = srs_flv_read_header(flv, header)) != 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// packet data
|
|
||||||
int type, size;
|
|
||||||
u_int32_t timestamp = 0;
|
|
||||||
char* data = NULL;
|
|
||||||
int64_t offset = 0;
|
|
||||||
|
|
||||||
trace("start parse flv");
|
trace("start parse flv");
|
||||||
for (;;) {
|
for (;;) {
|
||||||
offset = lseek(flv_fd, 0, SEEK_CUR);
|
offset = srs_flv_tellg(flv);
|
||||||
|
|
||||||
if ((ret = flv_read_packet(flv_fd, &type, ×tamp, &data, &size)) != 0) {
|
// tag header
|
||||||
if (ret == ERROR_FLV_CODEC_EOF) {
|
if ((ret = srs_flv_read_tag_header(flv, &type, &size, ×tamp)) != 0) {
|
||||||
|
if (srs_flv_is_eof(ret)) {
|
||||||
trace("parse completed.");
|
trace("parse completed.");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -234,6 +237,16 @@ int parse_flv(int flv_fd)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (size <= 0) {
|
||||||
|
trace("invalid size=%d", size);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
data = (char*)malloc(size);
|
||||||
|
if ((ret = srs_flv_read_tag_data(flv, data, size)) != 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
// data tag
|
// data tag
|
||||||
if (type == SRS_RTMP_TYPE_AUDIO) {
|
if (type == SRS_RTMP_TYPE_AUDIO) {
|
||||||
if ((ret = parse_audio_data(timestamp, data, size, offset)) != 0) {
|
if ((ret = parse_audio_data(timestamp, data, size, offset)) != 0) {
|
||||||
|
|
|
@ -39,7 +39,7 @@ using namespace std;
|
||||||
#include <srs_kernel_utility.hpp>
|
#include <srs_kernel_utility.hpp>
|
||||||
#include <srs_app_http_hooks.hpp>
|
#include <srs_app_http_hooks.hpp>
|
||||||
#include <srs_app_codec.hpp>
|
#include <srs_app_codec.hpp>
|
||||||
#include <srs_app_flv.hpp>
|
#include <srs_kernel_flv.hpp>
|
||||||
|
|
||||||
SrsFlvSegment::SrsFlvSegment()
|
SrsFlvSegment::SrsFlvSegment()
|
||||||
{
|
{
|
||||||
|
|
|
@ -40,7 +40,7 @@ using namespace std;
|
||||||
#include <srs_core_autofree.hpp>
|
#include <srs_core_autofree.hpp>
|
||||||
#include <srs_app_json.hpp>
|
#include <srs_app_json.hpp>
|
||||||
#include <srs_app_config.hpp>
|
#include <srs_app_config.hpp>
|
||||||
#include <srs_app_flv.hpp>
|
#include <srs_kernel_flv.hpp>
|
||||||
|
|
||||||
#define SRS_HTTP_DEFAULT_PAGE "index.html"
|
#define SRS_HTTP_DEFAULT_PAGE "index.html"
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
// 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 "120"
|
#define VERSION_REVISION "121"
|
||||||
#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"
|
||||||
|
|
|
@ -118,6 +118,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
|
||||||
|
|
||||||
// see librtmp.
|
// see librtmp.
|
||||||
// failed when open ssl create the dh
|
// 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
|
||||||
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.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <srs_app_flv.hpp>
|
#include <srs_kernel_flv.hpp>
|
||||||
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
#include <srs_app_config.hpp>
|
#include <srs_kernel_log.hpp>
|
||||||
#include <srs_kernel_error.hpp>
|
#include <srs_kernel_error.hpp>
|
||||||
#include <srs_protocol_rtmp.hpp>
|
|
||||||
#include <srs_protocol_rtmp_stack.hpp>
|
|
||||||
#include <srs_app_source.hpp>
|
|
||||||
#include <srs_core_autofree.hpp>
|
#include <srs_core_autofree.hpp>
|
||||||
#include <srs_kernel_stream.hpp>
|
#include <srs_kernel_stream.hpp>
|
||||||
#include <srs_kernel_utility.hpp>
|
#include <srs_kernel_utility.hpp>
|
||||||
#include <srs_app_http_hooks.hpp>
|
|
||||||
#include <srs_app_codec.hpp>
|
|
||||||
|
|
||||||
#define SRS_FLV_TAG_HEADER_SIZE 11
|
#define SRS_FLV_TAG_HEADER_SIZE 11
|
||||||
#define SRS_FLV_PREVIOUS_TAG_SIZE 4
|
#define SRS_FLV_PREVIOUS_TAG_SIZE 4
|
||||||
|
@ -509,3 +504,109 @@ int SrsFlvFastDecoder::lseek(int64_t offset)
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SrsFlvDecoder::SrsFlvDecoder()
|
||||||
|
{
|
||||||
|
_fs = NULL;
|
||||||
|
tag_stream = new SrsStream();
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsFlvDecoder::~SrsFlvDecoder()
|
||||||
|
{
|
||||||
|
srs_freep(tag_stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
int SrsFlvDecoder::initialize(SrsFileStream* fs)
|
||||||
|
{
|
||||||
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
_fs = fs;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SrsFlvDecoder::read_header(char header[9])
|
||||||
|
{
|
||||||
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
if ((ret = _fs->read(header, 9, NULL)) != ERROR_SUCCESS) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* h = header;
|
||||||
|
if (h[0] != 'F' || h[1] != 'L' || h[2] != 'V') {
|
||||||
|
ret = ERROR_SYSTEM_FLV_HEADER;
|
||||||
|
srs_warn("flv header must start with FLV. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SrsFlvDecoder::read_tag_header(char* ptype, int32_t* pdata_size, u_int32_t* ptime)
|
||||||
|
{
|
||||||
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
char th[11]; // tag header
|
||||||
|
|
||||||
|
// read tag header
|
||||||
|
if ((ret = _fs->read(th, 11, NULL)) != ERROR_SUCCESS) {
|
||||||
|
if (ret != ERROR_SYSTEM_FILE_EOF) {
|
||||||
|
srs_error("read flv tag header failed. ret=%d", ret);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reserved UB [2]
|
||||||
|
// Filter UB [1]
|
||||||
|
// TagType UB [5]
|
||||||
|
*ptype = (int)(th[0] & 0x1F);
|
||||||
|
|
||||||
|
// DataSize UI24
|
||||||
|
char* pp = (char*)pdata_size;
|
||||||
|
pp[2] = th[1];
|
||||||
|
pp[1] = th[2];
|
||||||
|
pp[0] = th[3];
|
||||||
|
|
||||||
|
// Timestamp UI24
|
||||||
|
pp = (char*)ptime;
|
||||||
|
pp[2] = th[4];
|
||||||
|
pp[1] = th[5];
|
||||||
|
pp[0] = th[6];
|
||||||
|
|
||||||
|
// TimestampExtended UI8
|
||||||
|
pp[3] = th[7];
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SrsFlvDecoder::read_tag_data(char* data, int32_t size)
|
||||||
|
{
|
||||||
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
if ((ret = _fs->read(data, size, NULL)) != ERROR_SUCCESS) {
|
||||||
|
if (ret != ERROR_SYSTEM_FILE_EOF) {
|
||||||
|
srs_error("read flv tag header failed. ret=%d", ret);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int SrsFlvDecoder::read_previous_tag_size(char ts[4])
|
||||||
|
{
|
||||||
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
// ignore 4bytes tag size.
|
||||||
|
if ((ret = _fs->read(ts, 4, NULL)) != ERROR_SUCCESS) {
|
||||||
|
if (ret != ERROR_SYSTEM_FILE_EOF) {
|
||||||
|
srs_error("read flv previous tag size failed. ret=%d", ret);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
#define SRS_APP_FLV_HPP
|
#define SRS_APP_FLV_HPP
|
||||||
|
|
||||||
/*
|
/*
|
||||||
#include <srs_app_flv.hpp>
|
#include <srs_kernel_flv.hpp>
|
||||||
*/
|
*/
|
||||||
#include <srs_core.hpp>
|
#include <srs_core.hpp>
|
||||||
|
|
||||||
|
@ -142,4 +142,29 @@ public:
|
||||||
virtual int lseek(int64_t offset);
|
virtual int lseek(int64_t offset);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* decode flv file.
|
||||||
|
*/
|
||||||
|
class SrsFlvDecoder
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
SrsFileStream* _fs;
|
||||||
|
private:
|
||||||
|
SrsStream* tag_stream;
|
||||||
|
public:
|
||||||
|
SrsFlvDecoder();
|
||||||
|
virtual ~SrsFlvDecoder();
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* initialize the underlayer file stream,
|
||||||
|
* user can initialize multiple times to decode multiple flv files.
|
||||||
|
*/
|
||||||
|
virtual int initialize(SrsFileStream* fs);
|
||||||
|
public:
|
||||||
|
virtual int read_header(char header[9]);
|
||||||
|
virtual int read_tag_header(char* ptype, int32_t* pdata_size, u_int32_t* ptime);
|
||||||
|
virtual int read_tag_data(char* data, int32_t size);
|
||||||
|
virtual int read_previous_tag_size(char ts[4]);
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -39,6 +39,7 @@ using namespace std;
|
||||||
#include <srs_kernel_utility.hpp>
|
#include <srs_kernel_utility.hpp>
|
||||||
#include <srs_kernel_stream.hpp>
|
#include <srs_kernel_stream.hpp>
|
||||||
#include <srs_protocol_amf0.hpp>
|
#include <srs_protocol_amf0.hpp>
|
||||||
|
#include <srs_kernel_flv.hpp>
|
||||||
|
|
||||||
// if user want to define log, define the folowing macro.
|
// if user want to define log, define the folowing macro.
|
||||||
#ifndef SRS_RTMP_USER_DEFINED_LOG
|
#ifndef SRS_RTMP_USER_DEFINED_LOG
|
||||||
|
@ -382,6 +383,124 @@ int64_t srs_get_time_ms()
|
||||||
return srs_get_system_time_ms();
|
return srs_get_system_time_ms();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct FlvContext
|
||||||
|
{
|
||||||
|
SrsFileStream fs;
|
||||||
|
SrsFlvEncoder enc;
|
||||||
|
SrsFlvDecoder dec;
|
||||||
|
};
|
||||||
|
|
||||||
|
srs_flv_t srs_flv_open_read(const char* file)
|
||||||
|
{
|
||||||
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
FlvContext* flv = new FlvContext();
|
||||||
|
|
||||||
|
if ((ret = flv->fs.open_read(file)) != ERROR_SUCCESS) {
|
||||||
|
srs_freep(flv);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ret = flv->enc.initialize(&flv->fs)) != ERROR_SUCCESS) {
|
||||||
|
srs_freep(flv);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ret = flv->dec.initialize(&flv->fs)) != ERROR_SUCCESS) {
|
||||||
|
srs_freep(flv);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return flv;
|
||||||
|
}
|
||||||
|
|
||||||
|
srs_flv_t srs_flv_open_write(const char* file)
|
||||||
|
{
|
||||||
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
FlvContext* flv = new FlvContext();
|
||||||
|
|
||||||
|
if ((ret = flv->fs.open_write(file)) != ERROR_SUCCESS) {
|
||||||
|
srs_freep(flv);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ret = flv->enc.initialize(&flv->fs)) != ERROR_SUCCESS) {
|
||||||
|
srs_freep(flv);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ret = flv->dec.initialize(&flv->fs)) != ERROR_SUCCESS) {
|
||||||
|
srs_freep(flv);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return flv;
|
||||||
|
}
|
||||||
|
|
||||||
|
void srs_flv_close(srs_flv_t flv)
|
||||||
|
{
|
||||||
|
FlvContext* context = (FlvContext*)flv;
|
||||||
|
srs_freep(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
int srs_flv_read_header(srs_flv_t flv, char header[9])
|
||||||
|
{
|
||||||
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
FlvContext* context = (FlvContext*)flv;
|
||||||
|
if ((ret = context->dec.read_header(header)) != ERROR_SUCCESS) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
char ts[4]; // tag size
|
||||||
|
if ((ret = context->dec.read_previous_tag_size(ts)) != ERROR_SUCCESS) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int srs_flv_read_tag_header(srs_flv_t flv, char* ptype, int32_t* pdata_size, u_int32_t* ptime)
|
||||||
|
{
|
||||||
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
FlvContext* context = (FlvContext*)flv;
|
||||||
|
if ((ret = context->dec.read_tag_header(ptype, pdata_size, ptime)) != ERROR_SUCCESS) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int srs_flv_read_tag_data(srs_flv_t flv, char* data, int32_t size)
|
||||||
|
{
|
||||||
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
FlvContext* context = (FlvContext*)flv;
|
||||||
|
if ((ret = context->dec.read_tag_data(data, size)) != ERROR_SUCCESS) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
char ts[4]; // tag size
|
||||||
|
if ((ret = context->dec.read_previous_tag_size(ts)) != ERROR_SUCCESS) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t srs_flv_tellg(srs_flv_t flv)
|
||||||
|
{
|
||||||
|
FlvContext* context = (FlvContext*)flv;
|
||||||
|
return context->fs.tellg();
|
||||||
|
}
|
||||||
|
|
||||||
|
flv_bool srs_flv_is_eof(int error_code)
|
||||||
|
{
|
||||||
|
return error_code == ERROR_SYSTEM_FILE_EOF;
|
||||||
|
}
|
||||||
|
|
||||||
srs_amf0_t srs_amf0_parse(char* data, int size, int* nparsed)
|
srs_amf0_t srs_amf0_parse(char* data, int size, int* nparsed)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
|
@ -151,6 +151,25 @@ int srs_version_revision();
|
||||||
*/
|
*/
|
||||||
int64_t srs_get_time_ms();
|
int64_t srs_get_time_ms();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* flv codec
|
||||||
|
*/
|
||||||
|
typedef void* srs_flv_t;
|
||||||
|
typedef int flv_bool;
|
||||||
|
srs_flv_t srs_flv_open_read(const char* file);
|
||||||
|
srs_flv_t srs_flv_open_write(const char* file);
|
||||||
|
void srs_flv_close(srs_flv_t flv);
|
||||||
|
/* read the flv header. 9bytes header. drop the 4bytes zero previous tag size */
|
||||||
|
int srs_flv_read_header(srs_flv_t flv, char header[9]);
|
||||||
|
/* read the flv tag header, 1bytes tag, 3bytes data_size, 4bytes time, 3bytes stream id. */
|
||||||
|
int srs_flv_read_tag_header(srs_flv_t flv, char* ptype, int32_t* pdata_size, u_int32_t* ptime);
|
||||||
|
/* read the tag data. drop the 4bytes previous tag size */
|
||||||
|
int srs_flv_read_tag_data(srs_flv_t flv, char* data, int32_t size);
|
||||||
|
/* file stream tellg to get offset */
|
||||||
|
int64_t srs_flv_tellg(srs_flv_t flv);
|
||||||
|
/* whether the error code indicates EOF */
|
||||||
|
flv_bool srs_flv_is_eof(int error_code);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* amf0 codec
|
* amf0 codec
|
||||||
*/
|
*/
|
||||||
|
@ -184,7 +203,12 @@ srs_amf0_t srs_amf0_ecma_array_property_value_at(srs_amf0_t amf0, int index);
|
||||||
/* strict array value converter */
|
/* strict array value converter */
|
||||||
int srs_amf0_strict_array_property_count(srs_amf0_t amf0);
|
int srs_amf0_strict_array_property_count(srs_amf0_t amf0);
|
||||||
srs_amf0_t srs_amf0_strict_array_property_at(srs_amf0_t amf0, int index);
|
srs_amf0_t srs_amf0_strict_array_property_at(srs_amf0_t amf0, int index);
|
||||||
/* human readable print */
|
/**
|
||||||
|
* human readable print
|
||||||
|
* @param pdata, output the heap data,
|
||||||
|
* user must use srs_amf0_free_bytes to free it.
|
||||||
|
* @return return the *pdata for print.
|
||||||
|
*/
|
||||||
char* srs_amf0_human_print(srs_amf0_t amf0, char** pdata, int* psize);
|
char* srs_amf0_human_print(srs_amf0_t amf0, char** pdata, int* psize);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -19,6 +19,8 @@ file
|
||||||
..\kernel\srs_kernel_buffer.cpp,
|
..\kernel\srs_kernel_buffer.cpp,
|
||||||
..\kernel\srs_kernel_error.hpp,
|
..\kernel\srs_kernel_error.hpp,
|
||||||
..\kernel\srs_kernel_error.cpp,
|
..\kernel\srs_kernel_error.cpp,
|
||||||
|
..\kernel\srs_kernel_flv.hpp,
|
||||||
|
..\kernel\srs_kernel_flv.cpp,
|
||||||
..\kernel\srs_kernel_log.hpp,
|
..\kernel\srs_kernel_log.hpp,
|
||||||
..\kernel\srs_kernel_log.cpp,
|
..\kernel\srs_kernel_log.cpp,
|
||||||
..\kernel\srs_kernel_stream.hpp,
|
..\kernel\srs_kernel_stream.hpp,
|
||||||
|
@ -57,8 +59,6 @@ file
|
||||||
..\app\srs_app_encoder.cpp,
|
..\app\srs_app_encoder.cpp,
|
||||||
..\app\srs_app_ffmpeg.hpp,
|
..\app\srs_app_ffmpeg.hpp,
|
||||||
..\app\srs_app_ffmpeg.cpp,
|
..\app\srs_app_ffmpeg.cpp,
|
||||||
..\app\srs_app_flv.hpp,
|
|
||||||
..\app\srs_app_flv.cpp,
|
|
||||||
..\app\srs_app_forward.hpp,
|
..\app\srs_app_forward.hpp,
|
||||||
..\app\srs_app_forward.cpp,
|
..\app\srs_app_forward.cpp,
|
||||||
..\app\srs_app_heartbeat.hpp,
|
..\app\srs_app_heartbeat.hpp,
|
||||||
|
@ -112,6 +112,7 @@ file
|
||||||
..\utest\srs_utest_handshake.cpp,
|
..\utest\srs_utest_handshake.cpp,
|
||||||
research readonly separator,
|
research readonly separator,
|
||||||
..\..\research\librtmp\srs_flv_codec.h,
|
..\..\research\librtmp\srs_flv_codec.h,
|
||||||
|
..\..\research\librtmp\srs_flv_injecter.c,
|
||||||
..\..\research\librtmp\srs_flv_parser.c,
|
..\..\research\librtmp\srs_flv_parser.c,
|
||||||
..\..\research\librtmp\srs_ingest_flv.c,
|
..\..\research\librtmp\srs_ingest_flv.c,
|
||||||
..\..\research\librtmp\srs_ingest_rtmp.c,
|
..\..\research\librtmp\srs_ingest_rtmp.c,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue