winlin

for #250, support h264 video for push mpegts over udp. 2.0.110

@@ -375,7 +375,8 @@ MODULE_ID="RTMP" @@ -375,7 +375,8 @@ MODULE_ID="RTMP"
375 MODULE_DEPENDS=("CORE" "KERNEL") 375 MODULE_DEPENDS=("CORE" "KERNEL")
376 ModuleLibIncs=(${SRS_OBJS_DIR} ${LibSSLRoot}) 376 ModuleLibIncs=(${SRS_OBJS_DIR} ${LibSSLRoot})
377 MODULE_FILES=("srs_rtmp_amf0" "srs_rtmp_io" "srs_rtmp_stack" "srs_rtmp_sdk" 377 MODULE_FILES=("srs_rtmp_amf0" "srs_rtmp_io" "srs_rtmp_stack" "srs_rtmp_sdk"
378 - "srs_rtmp_handshake" "srs_rtmp_utility" "srs_rtmp_msg_array" "srs_rtmp_buffer") 378 + "srs_rtmp_handshake" "srs_rtmp_utility" "srs_rtmp_msg_array" "srs_rtmp_buffer"
  379 + "srs_raw_avc")
379 RTMP_INCS="src/protocol"; MODULE_DIR=${RTMP_INCS} . auto/modules.sh 380 RTMP_INCS="src/protocol"; MODULE_DIR=${RTMP_INCS} . auto/modules.sh
380 RTMP_OBJS="${MODULE_OBJS[@]}" 381 RTMP_OBJS="${MODULE_OBJS[@]}"
381 # 382 #
@@ -45,6 +45,8 @@ file @@ -45,6 +45,8 @@ file
45 ../../src/kernel/srs_kernel_utility.hpp, 45 ../../src/kernel/srs_kernel_utility.hpp,
46 ../../src/kernel/srs_kernel_utility.cpp, 46 ../../src/kernel/srs_kernel_utility.cpp,
47 protocol readonly separator, 47 protocol readonly separator,
  48 + ../../src/protocol/srs_raw_avc.hpp,
  49 + ../../src/protocol/srs_raw_avc.cpp,
48 ../../src/protocol/srs_rtmp_amf0.hpp, 50 ../../src/protocol/srs_rtmp_amf0.hpp,
49 ../../src/protocol/srs_rtmp_amf0.cpp, 51 ../../src/protocol/srs_rtmp_amf0.cpp,
50 ../../src/protocol/srs_rtmp_buffer.hpp, 52 ../../src/protocol/srs_rtmp_buffer.hpp,
@@ -36,7 +36,7 @@ @@ -36,7 +36,7 @@
36 <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> 36 <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
37 </ImportGroup> 37 </ImportGroup>
38 <PropertyGroup Label="UserMacros" /> 38 <PropertyGroup Label="UserMacros" />
39 - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> 39 + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
40 <IncludePath>$(ProjectDir)/../../src/core;$(ProjectDir)/../../src/kernel;$(ProjectDir)/../../src/protocol;$(ProjectDir)/../../src/app;$(ProjectDir)/../../src/libs;$(ProjectDir)/../../objs;$(IncludePath)</IncludePath> 40 <IncludePath>$(ProjectDir)/../../src/core;$(ProjectDir)/../../src/kernel;$(ProjectDir)/../../src/protocol;$(ProjectDir)/../../src/app;$(ProjectDir)/../../src/libs;$(ProjectDir)/../../objs;$(IncludePath)</IncludePath>
41 </PropertyGroup> 41 </PropertyGroup>
42 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> 42 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
@@ -116,6 +116,7 @@ @@ -116,6 +116,7 @@
116 <ClInclude Include="..\..\src\libs\srs_librtmp.hpp" /> 116 <ClInclude Include="..\..\src\libs\srs_librtmp.hpp" />
117 <ClInclude Include="..\..\src\libs\srs_lib_bandwidth.hpp" /> 117 <ClInclude Include="..\..\src\libs\srs_lib_bandwidth.hpp" />
118 <ClInclude Include="..\..\src\libs\srs_lib_simple_socket.hpp" /> 118 <ClInclude Include="..\..\src\libs\srs_lib_simple_socket.hpp" />
  119 + <ClInclude Include="..\..\src\protocol\srs_raw_avc.hpp" />
119 <ClInclude Include="..\..\src\protocol\srs_rtmp_amf0.hpp" /> 120 <ClInclude Include="..\..\src\protocol\srs_rtmp_amf0.hpp" />
120 <ClInclude Include="..\..\src\protocol\srs_rtmp_buffer.hpp" /> 121 <ClInclude Include="..\..\src\protocol\srs_rtmp_buffer.hpp" />
121 <ClInclude Include="..\..\src\protocol\srs_rtmp_handshake.hpp" /> 122 <ClInclude Include="..\..\src\protocol\srs_rtmp_handshake.hpp" />
@@ -193,6 +194,7 @@ @@ -193,6 +194,7 @@
193 <ClCompile Include="..\..\src\libs\srs_lib_bandwidth.cpp" /> 194 <ClCompile Include="..\..\src\libs\srs_lib_bandwidth.cpp" />
194 <ClCompile Include="..\..\src\libs\srs_lib_simple_socket.cpp" /> 195 <ClCompile Include="..\..\src\libs\srs_lib_simple_socket.cpp" />
195 <ClCompile Include="..\..\src\main\srs_main_server.cpp" /> 196 <ClCompile Include="..\..\src\main\srs_main_server.cpp" />
  197 + <ClCompile Include="..\..\src\protocol\srs_raw_avc.cpp" />
196 <ClCompile Include="..\..\src\protocol\srs_rtmp_amf0.cpp" /> 198 <ClCompile Include="..\..\src\protocol\srs_rtmp_amf0.cpp" />
197 <ClCompile Include="..\..\src\protocol\srs_rtmp_buffer.cpp" /> 199 <ClCompile Include="..\..\src\protocol\srs_rtmp_buffer.cpp" />
198 <ClCompile Include="..\..\src\protocol\srs_rtmp_handshake.cpp" /> 200 <ClCompile Include="..\..\src\protocol\srs_rtmp_handshake.cpp" />
@@ -226,6 +226,9 @@ @@ -226,6 +226,9 @@
226 <ClCompile Include="..\..\src\app\srs_app_mpegts_udp.cpp"> 226 <ClCompile Include="..\..\src\app\srs_app_mpegts_udp.cpp">
227 <Filter>srs</Filter> 227 <Filter>srs</Filter>
228 </ClCompile> 228 </ClCompile>
  229 + <ClCompile Include="..\..\src\protocol\srs_raw_avc.cpp">
  230 + <Filter>srs</Filter>
  231 + </ClCompile>
229 </ItemGroup> 232 </ItemGroup>
230 <ItemGroup> 233 <ItemGroup>
231 <ClInclude Include="..\..\src\app\srs_app_bandwidth.hpp"> 234 <ClInclude Include="..\..\src\app\srs_app_bandwidth.hpp">
@@ -414,6 +417,9 @@ @@ -414,6 +417,9 @@
414 <ClInclude Include="..\..\src\app\srs_app_mpegts_udp.hpp"> 417 <ClInclude Include="..\..\src\app\srs_app_mpegts_udp.hpp">
415 <Filter>srs</Filter> 418 <Filter>srs</Filter>
416 </ClInclude> 419 </ClInclude>
  420 + <ClInclude Include="..\..\src\protocol\srs_raw_avc.hpp">
  421 + <Filter>srs</Filter>
  422 + </ClInclude>
417 </ItemGroup> 423 </ItemGroup>
418 <ItemGroup> 424 <ItemGroup>
419 <Filter Include="research"> 425 <Filter Include="research">
@@ -447,7 +447,7 @@ int SrsEdgeForwarder::start() @@ -447,7 +447,7 @@ int SrsEdgeForwarder::start()
447 } 447 }
448 448
449 if ((ret = client->publish(req->stream, stream_id)) != ERROR_SUCCESS) { 449 if ((ret = client->publish(req->stream, stream_id)) != ERROR_SUCCESS) {
450 - srs_error("connect with server failed, stream=%s, stream_id=%d. ret=%d", 450 + srs_error("publish failed, stream=%s, stream_id=%d. ret=%d",
451 req->stream.c_str(), stream_id, ret); 451 req->stream.c_str(), stream_id, ret);
452 return ret; 452 return ret;
453 } 453 }
@@ -23,6 +23,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -23,6 +23,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 23
24 #include <srs_app_mpegts_udp.hpp> 24 #include <srs_app_mpegts_udp.hpp>
25 25
  26 +#ifdef SRS_AUTO_STREAM_CASTER
  27 +
  28 +#include <stdlib.h>
26 #include <sys/socket.h> 29 #include <sys/socket.h>
27 #include <netinet/in.h> 30 #include <netinet/in.h>
28 #include <arpa/inet.h> 31 #include <arpa/inet.h>
@@ -39,8 +42,12 @@ using namespace std; @@ -39,8 +42,12 @@ using namespace std;
39 #include <srs_kernel_file.hpp> 42 #include <srs_kernel_file.hpp>
40 #include <srs_core_autofree.hpp> 43 #include <srs_core_autofree.hpp>
41 #include <srs_kernel_utility.hpp> 44 #include <srs_kernel_utility.hpp>
42 -  
43 -#ifdef SRS_AUTO_STREAM_CASTER 45 +#include <srs_rtmp_sdk.hpp>
  46 +#include <srs_app_st_socket.hpp>
  47 +#include <srs_rtmp_utility.hpp>
  48 +#include <srs_app_utility.hpp>
  49 +#include <srs_rtmp_amf0.hpp>
  50 +#include <srs_raw_avc.hpp>
44 51
45 ISrsUdpHandler::ISrsUdpHandler() 52 ISrsUdpHandler::ISrsUdpHandler()
46 { 53 {
@@ -56,13 +63,25 @@ SrsMpegtsOverUdp::SrsMpegtsOverUdp(SrsConfDirective* c) @@ -56,13 +63,25 @@ SrsMpegtsOverUdp::SrsMpegtsOverUdp(SrsConfDirective* c)
56 context = new SrsTsContext(); 63 context = new SrsTsContext();
57 buffer = new SrsSimpleBuffer(); 64 buffer = new SrsSimpleBuffer();
58 output = _srs_config->get_stream_caster_output(c); 65 output = _srs_config->get_stream_caster_output(c);
  66 + req = NULL;
  67 + io = NULL;
  68 + client = NULL;
  69 + stfd = NULL;
  70 + stream_id = 0;
  71 + avc = new SrsRawH264Stream();
  72 + h264_sps_changed = false;
  73 + h264_pps_changed = false;
  74 + h264_sps_pps_sent = false;
59 } 75 }
60 76
61 SrsMpegtsOverUdp::~SrsMpegtsOverUdp() 77 SrsMpegtsOverUdp::~SrsMpegtsOverUdp()
62 { 78 {
  79 + close();
  80 +
63 srs_freep(buffer); 81 srs_freep(buffer);
64 srs_freep(stream); 82 srs_freep(stream);
65 srs_freep(context); 83 srs_freep(context);
  84 + srs_freep(avc);
66 } 85 }
67 86
68 int SrsMpegtsOverUdp::on_udp_packet(sockaddr_in* from, char* buf, int nb_buf) 87 int SrsMpegtsOverUdp::on_udp_packet(sockaddr_in* from, char* buf, int nb_buf)
@@ -207,8 +226,311 @@ int SrsMpegtsOverUdp::on_ts_message(SrsTsMessage* msg) @@ -207,8 +226,311 @@ int SrsMpegtsOverUdp::on_ts_message(SrsTsMessage* msg)
207 return ret; 226 return ret;
208 } 227 }
209 228
  229 + // check supported codec
  230 + if (msg->channel->stream != SrsTsStreamVideoH264 && msg->channel->stream != SrsTsStreamAudioAAC) {
  231 + ret = ERROR_STREAM_CASTER_TS_CODEC;
  232 + srs_error("mpegts: unsupported stream codec=%d. ret=%d", msg->channel->stream, ret);
  233 + return ret;
  234 + }
  235 +
  236 + // parse the stream.
  237 + SrsStream avs;
  238 + if ((ret = avs.initialize(msg->payload->bytes(), msg->payload->length())) != ERROR_SUCCESS) {
  239 + srs_error("mpegts: initialize av stream failed. ret=%d", ret);
  240 + return ret;
  241 + }
  242 +
  243 + // publish audio or video.
  244 + if (msg->channel->stream == SrsTsStreamVideoH264) {
  245 + return on_ts_video(msg, &avs);
  246 + }
  247 +
210 // TODO: FIXME: implements it. 248 // TODO: FIXME: implements it.
211 return ret; 249 return ret;
212 } 250 }
213 251
  252 +int SrsMpegtsOverUdp::on_ts_video(SrsTsMessage* msg, SrsStream* avs)
  253 +{
  254 + int ret = ERROR_SUCCESS;
  255 +
  256 + // ensure rtmp connected.
  257 + if ((ret = connect()) != ERROR_SUCCESS) {
  258 + return ret;
  259 + }
  260 +
  261 + // ts tbn to flv tbn.
  262 + u_int32_t dts = msg->dts / 90;
  263 + u_int32_t pts = msg->dts / 90;
  264 +
  265 + // send each frame.
  266 + while (!avs->empty()) {
  267 + char* frame = NULL;
  268 + int frame_size = 0;
  269 + if ((ret = avc->annexb_demux(avs, &frame, &frame_size)) != ERROR_SUCCESS) {
  270 + return ret;
  271 + }
  272 +
  273 + // ignore invalid frame,
  274 + // * atleast 1bytes for SPS to decode the type
  275 + // * ignore the auth bytes '09f0'
  276 + if (frame_size <= 2) {
  277 + continue;
  278 + }
  279 +
  280 + // it may be return error, but we must process all packets.
  281 + if ((ret = write_h264_raw_frame(frame, frame_size, dts, pts)) != ERROR_SUCCESS) {
  282 + if (ret = ERROR_H264_DROP_BEFORE_SPS_PPS) {
  283 + continue;
  284 + }
  285 + return ret;
  286 + }
  287 + }
  288 +
  289 + return ret;
  290 +}
  291 +
  292 +int SrsMpegtsOverUdp::write_h264_raw_frame(char* frame, int frame_size, u_int32_t dts, u_int32_t pts)
  293 +{
  294 + int ret = ERROR_SUCCESS;
  295 +
  296 + // for sps
  297 + if (avc->is_sps(frame, frame_size)) {
  298 + std::string sps;
  299 + if ((ret = avc->sps_demux(frame, frame_size, sps)) != ERROR_SUCCESS) {
  300 + return ret;
  301 + }
  302 +
  303 + if (h264_sps == sps) {
  304 + return ret;
  305 + }
  306 + h264_sps_changed = true;
  307 + h264_sps = sps;
  308 +
  309 + return write_h264_sps_pps(dts, pts);
  310 + }
  311 +
  312 + // for pps
  313 + if (avc->is_pps(frame, frame_size)) {
  314 + std::string pps;
  315 + if ((ret = avc->pps_demux(frame, frame_size, pps)) != ERROR_SUCCESS) {
  316 + return ret;
  317 + }
  318 +
  319 + if (h264_pps == pps) {
  320 + return ret;
  321 + }
  322 + h264_pps_changed = true;
  323 + h264_pps = pps;
  324 +
  325 + return write_h264_sps_pps(dts, pts);
  326 + }
  327 +
  328 + // ibp frame.
  329 + return write_h264_ipb_frame(frame, frame_size, dts, pts);
  330 +}
  331 +
  332 +int SrsMpegtsOverUdp::write_h264_sps_pps(u_int32_t dts, u_int32_t pts)
  333 +{
  334 + int ret = ERROR_SUCCESS;
  335 +
  336 + // only send when both sps and pps changed.
  337 + if (!h264_sps_changed || !h264_pps_changed) {
  338 + return ret;
  339 + }
  340 +
  341 + // h264 raw to h264 packet.
  342 + std::string sh;
  343 + if ((ret = avc->mux_sequence_header(h264_sps, h264_pps, dts, pts, sh)) != ERROR_SUCCESS) {
  344 + return ret;
  345 + }
  346 +
  347 + // h264 packet to flv packet.
  348 + int8_t frame_type = SrsCodecVideoAVCFrameKeyFrame;
  349 + int8_t avc_packet_type = SrsCodecVideoAVCTypeSequenceHeader;
  350 + char* flv = NULL;
  351 + int nb_flv = 0;
  352 + if ((ret = avc->mux_avc2flv(sh, frame_type, avc_packet_type, dts, pts, &flv, &nb_flv)) != ERROR_SUCCESS) {
  353 + return ret;
  354 + }
  355 +
  356 + // reset sps and pps.
  357 + h264_sps_changed = false;
  358 + h264_pps_changed = false;
  359 + h264_sps_pps_sent = true;
  360 +
  361 + // the timestamp in rtmp message header is dts.
  362 + u_int32_t timestamp = dts;
  363 + return rtmp_write_packet(SrsCodecFlvTagVideo, timestamp, flv, nb_flv);
  364 +}
  365 +
  366 +int SrsMpegtsOverUdp::write_h264_ipb_frame(char* frame, int frame_size, u_int32_t dts, u_int32_t pts)
  367 +{
  368 + int ret = ERROR_SUCCESS;
  369 +
  370 + // when sps or pps not sent, ignore the packet.
  371 + // @see https://github.com/winlinvip/simple-rtmp-server/issues/203
  372 + if (!h264_sps_pps_sent) {
  373 + return ERROR_H264_DROP_BEFORE_SPS_PPS;
  374 + }
  375 +
  376 + std::string ibp;
  377 + int8_t frame_type;
  378 + if ((ret = avc->mux_ipb_frame(frame, frame_size, dts, pts, ibp, frame_type)) != ERROR_SUCCESS) {
  379 + return ret;
  380 + }
  381 +
  382 + int8_t avc_packet_type = SrsCodecVideoAVCTypeNALU;
  383 + char* flv = NULL;
  384 + int nb_flv = 0;
  385 + if ((ret = avc->mux_avc2flv(ibp, frame_type, avc_packet_type, dts, pts, &flv, &nb_flv)) != ERROR_SUCCESS) {
  386 + return ret;
  387 + }
  388 +
  389 + // the timestamp in rtmp message header is dts.
  390 + u_int32_t timestamp = dts;
  391 + return rtmp_write_packet(SrsCodecFlvTagVideo, timestamp, flv, nb_flv);
  392 +}
  393 +
  394 +int SrsMpegtsOverUdp::rtmp_write_packet(char type, u_int32_t timestamp, char* data, int size)
  395 +{
  396 + int ret = ERROR_SUCCESS;
  397 +
  398 + SrsSharedPtrMessage* msg = NULL;
  399 +
  400 + if ((ret = srs_rtmp_create_msg(type, timestamp, data, size, stream_id, &msg)) != ERROR_SUCCESS) {
  401 + return ret;
  402 + }
  403 +
  404 + srs_assert(msg);
  405 +
  406 + // send out encoded msg.
  407 + if ((ret = client->send_and_free_message(msg, stream_id)) != ERROR_SUCCESS) {
  408 + return ret;
  409 + }
  410 +
  411 + return ret;
  412 +}
  413 +
  414 +int SrsMpegtsOverUdp::connect()
  415 +{
  416 + int ret = ERROR_SUCCESS;
  417 +
  418 + // when ok, ignore.
  419 + if (io || client) {
  420 + return ret;
  421 + }
  422 +
  423 + // parse uri
  424 + if (!req) {
  425 + req = new SrsRequest();
  426 +
  427 + size_t pos = string::npos;
  428 + string uri = req->tcUrl = output;
  429 +
  430 + // tcUrl, stream
  431 + if ((pos = uri.rfind("/")) != string::npos) {
  432 + req->stream = uri.substr(pos + 1);
  433 + req->tcUrl = uri = uri.substr(0, pos);
  434 + }
  435 +
  436 + srs_discovery_tc_url(req->tcUrl,
  437 + req->schema, req->host, req->vhost, req->app, req->port,
  438 + req->param);
  439 + }
  440 +
  441 + // connect host.
  442 + if ((ret = srs_socket_connect(req->host, ::atoi(req->port.c_str()), ST_UTIME_NO_TIMEOUT, &stfd)) != ERROR_SUCCESS) {
  443 + srs_error("mpegts: connect server %s:%s failed. ret=%d", req->host.c_str(), req->port.c_str(), ret);
  444 + return ret;
  445 + }
  446 + io = new SrsStSocket(stfd);
  447 + client = new SrsRtmpClient(io);
  448 +
  449 + client->set_recv_timeout(SRS_CONSTS_RTMP_RECV_TIMEOUT_US);
  450 + client->set_send_timeout(SRS_CONSTS_RTMP_SEND_TIMEOUT_US);
  451 +
  452 + // connect to vhost/app
  453 + if ((ret = client->handshake()) != ERROR_SUCCESS) {
  454 + srs_error("mpegts: handshake with server failed. ret=%d", ret);
  455 + return ret;
  456 + }
  457 + if ((ret = connect_app(req->host, req->port)) != ERROR_SUCCESS) {
  458 + srs_error("mpegts: connect with server failed. ret=%d", ret);
  459 + return ret;
  460 + }
  461 + if ((ret = client->create_stream(stream_id)) != ERROR_SUCCESS) {
  462 + srs_error("mpegts: connect with server failed, stream_id=%d. ret=%d", stream_id, ret);
  463 + return ret;
  464 + }
  465 +
  466 + // publish.
  467 + if ((ret = client->publish(req->stream, stream_id)) != ERROR_SUCCESS) {
  468 + srs_error("mpegts: publish failed, stream=%s, stream_id=%d. ret=%d",
  469 + req->stream.c_str(), stream_id, ret);
  470 + return ret;
  471 + }
  472 +
  473 +
  474 + return ret;
  475 +}
  476 +
  477 +// TODO: FIXME: refine the connect_app.
  478 +int SrsMpegtsOverUdp::connect_app(string ep_server, string ep_port)
  479 +{
  480 + int ret = ERROR_SUCCESS;
  481 +
  482 + // args of request takes the srs info.
  483 + if (req->args == NULL) {
  484 + req->args = SrsAmf0Any::object();
  485 + }
  486 +
  487 + // notify server the edge identity,
  488 + // @see https://github.com/winlinvip/simple-rtmp-server/issues/147
  489 + SrsAmf0Object* data = req->args;
  490 + data->set("srs_sig", SrsAmf0Any::str(RTMP_SIG_SRS_KEY));
  491 + data->set("srs_server", SrsAmf0Any::str(RTMP_SIG_SRS_KEY" "RTMP_SIG_SRS_VERSION" ("RTMP_SIG_SRS_URL_SHORT")"));
  492 + data->set("srs_license", SrsAmf0Any::str(RTMP_SIG_SRS_LICENSE));
  493 + data->set("srs_role", SrsAmf0Any::str(RTMP_SIG_SRS_ROLE));
  494 + data->set("srs_url", SrsAmf0Any::str(RTMP_SIG_SRS_URL));
  495 + data->set("srs_version", SrsAmf0Any::str(RTMP_SIG_SRS_VERSION));
  496 + data->set("srs_site", SrsAmf0Any::str(RTMP_SIG_SRS_WEB));
  497 + data->set("srs_email", SrsAmf0Any::str(RTMP_SIG_SRS_EMAIL));
  498 + data->set("srs_copyright", SrsAmf0Any::str(RTMP_SIG_SRS_COPYRIGHT));
  499 + data->set("srs_primary", SrsAmf0Any::str(RTMP_SIG_SRS_PRIMARY));
  500 + data->set("srs_authors", SrsAmf0Any::str(RTMP_SIG_SRS_AUTHROS));
  501 + // for edge to directly get the id of client.
  502 + data->set("srs_pid", SrsAmf0Any::number(getpid()));
  503 + data->set("srs_id", SrsAmf0Any::number(_srs_context->get_id()));
  504 +
  505 + // local ip of edge
  506 + std::vector<std::string> ips = srs_get_local_ipv4_ips();
  507 + assert(_srs_config->get_stats_network() < (int)ips.size());
  508 + std::string local_ip = ips[_srs_config->get_stats_network()];
  509 + data->set("srs_server_ip", SrsAmf0Any::str(local_ip.c_str()));
  510 +
  511 + // generate the tcUrl
  512 + std::string param = "";
  513 + std::string tc_url = srs_generate_tc_url(ep_server, req->vhost, req->app, ep_port, param);
  514 +
  515 + // upnode server identity will show in the connect_app of client.
  516 + // @see https://github.com/winlinvip/simple-rtmp-server/issues/160
  517 + // the debug_srs_upnode is config in vhost and default to true.
  518 + bool debug_srs_upnode = _srs_config->get_debug_srs_upnode(req->vhost);
  519 + if ((ret = client->connect_app(req->app, tc_url, req, debug_srs_upnode)) != ERROR_SUCCESS) {
  520 + srs_error("mpegts: connect with server failed, tcUrl=%s, dsu=%d. ret=%d",
  521 + tc_url.c_str(), debug_srs_upnode, ret);
  522 + return ret;
  523 + }
  524 +
  525 + return ret;
  526 +}
  527 +
  528 +void SrsMpegtsOverUdp::close()
  529 +{
  530 + srs_freep(client);
  531 + srs_freep(io);
  532 + srs_freep(req);
  533 + srs_close_stfd(stfd);
  534 +}
  535 +
214 #endif 536 #endif
@@ -30,6 +30,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -30,6 +30,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 30
31 #include <srs_core.hpp> 31 #include <srs_core.hpp>
32 32
  33 +#ifdef SRS_AUTO_STREAM_CASTER
  34 +
33 class sockaddr_in; 35 class sockaddr_in;
34 #include <string> 36 #include <string>
35 37
@@ -37,9 +39,12 @@ class SrsStream; @@ -37,9 +39,12 @@ class SrsStream;
37 class SrsTsContext; 39 class SrsTsContext;
38 class SrsConfDirective; 40 class SrsConfDirective;
39 class SrsSimpleBuffer; 41 class SrsSimpleBuffer;
  42 +class SrsRtmpClient;
  43 +class SrsStSocket;
  44 +class SrsRequest;
  45 +class SrsRawH264Stream;
40 46
41 -#ifdef SRS_AUTO_STREAM_CASTER  
42 - 47 +#include <srs_app_st.hpp>
43 #include <srs_kernel_ts.hpp> 48 #include <srs_kernel_ts.hpp>
44 49
45 /** 50 /**
@@ -74,6 +79,19 @@ private: @@ -74,6 +79,19 @@ private:
74 SrsTsContext* context; 79 SrsTsContext* context;
75 SrsSimpleBuffer* buffer; 80 SrsSimpleBuffer* buffer;
76 std::string output; 81 std::string output;
  82 +private:
  83 + SrsRequest* req;
  84 + st_netfd_t stfd;
  85 + SrsStSocket* io;
  86 + SrsRtmpClient* client;
  87 + int stream_id;
  88 +private:
  89 + SrsRawH264Stream* avc;
  90 + std::string h264_sps;
  91 + bool h264_sps_changed;
  92 + std::string h264_pps;
  93 + bool h264_pps_changed;
  94 + bool h264_sps_pps_sent;
77 public: 95 public:
78 SrsMpegtsOverUdp(SrsConfDirective* c); 96 SrsMpegtsOverUdp(SrsConfDirective* c);
79 virtual ~SrsMpegtsOverUdp(); 97 virtual ~SrsMpegtsOverUdp();
@@ -83,6 +101,19 @@ public: @@ -83,6 +101,19 @@ public:
83 // interface ISrsTsHandler 101 // interface ISrsTsHandler
84 public: 102 public:
85 virtual int on_ts_message(SrsTsMessage* msg); 103 virtual int on_ts_message(SrsTsMessage* msg);
  104 +private:
  105 + virtual int on_ts_video(SrsTsMessage* msg, SrsStream* avs);
  106 + virtual int write_h264_raw_frame(char* frame, int frame_size, u_int32_t dts, u_int32_t pts);
  107 + virtual int write_h264_sps_pps(u_int32_t dts, u_int32_t pts);
  108 + virtual int write_h264_ipb_frame(char* frame, int frame_size, u_int32_t dts, u_int32_t pts);
  109 + virtual int rtmp_write_packet(char type, u_int32_t timestamp, char* data, int size);
  110 +private:
  111 + // connect to rtmp output url.
  112 + // @remark ignore when not connected, reconnect when disconnected.
  113 + virtual int connect();
  114 + virtual int connect_app(std::string ep_server, std::string ep_port);
  115 + // close the connected io and rtmp to ready to be re-connect.
  116 + virtual void close();
86 }; 117 };
87 118
88 #endif 119 #endif
@@ -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 2 32 #define VERSION_MAJOR 2
33 #define VERSION_MINOR 0 33 #define VERSION_MINOR 0
34 -#define VERSION_REVISION 109 34 +#define VERSION_REVISION 110
35 35
36 // server info. 36 // server info.
37 #define RTMP_SIG_SRS_KEY "SRS" 37 #define RTMP_SIG_SRS_KEY "SRS"
@@ -53,7 +53,7 @@ enum SrsCodecAudioType @@ -53,7 +53,7 @@ enum SrsCodecAudioType
53 // 5 = video info/command frame 53 // 5 = video info/command frame
54 enum SrsCodecVideoAVCFrame 54 enum SrsCodecVideoAVCFrame
55 { 55 {
56 - // set to the max value to reserved, for array map. 56 + // set to the zero to reserved, for array map.
57 SrsCodecVideoAVCFrameReserved = 0, 57 SrsCodecVideoAVCFrameReserved = 0,
58 SrsCodecVideoAVCFrameReserved1 = 6, 58 SrsCodecVideoAVCFrameReserved1 = 6,
59 59
@@ -91,7 +91,7 @@ enum SrsCodecVideoAVCType @@ -91,7 +91,7 @@ enum SrsCodecVideoAVCType
91 // 7 = AVC 91 // 7 = AVC
92 enum SrsCodecVideo 92 enum SrsCodecVideo
93 { 93 {
94 - // set to the max value to reserved, for array map. 94 + // set to the zero to reserved, for array map.
95 SrsCodecVideoReserved = 0, 95 SrsCodecVideoReserved = 0,
96 SrsCodecVideoReserved1 = 1, 96 SrsCodecVideoReserved1 = 1,
97 SrsCodecVideoReserved2 = 8, 97 SrsCodecVideoReserved2 = 8,
@@ -164,6 +164,22 @@ enum SrsCodecAudioSampleRate @@ -164,6 +164,22 @@ enum SrsCodecAudioSampleRate
164 }; 164 };
165 165
166 /** 166 /**
  167 +* E.4.1 FLV Tag, page 75
  168 +*/
  169 +enum SrsCodecFlvTag
  170 +{
  171 + // set to the zero to reserved, for array map.
  172 + SrsCodecFlvTagReserved = 0,
  173 +
  174 + // 8 = audio
  175 + SrsCodecFlvTagAudio = 8,
  176 + // 9 = video
  177 + SrsCodecFlvTagVideo = 9,
  178 + // 18 = script data
  179 + SrsCodecFlvTagScript = 18,
  180 +};
  181 +
  182 +/**
167 * Annex E. The FLV File Format 183 * Annex E. The FLV File Format
168 * @see SrsAvcAacCodec for the media stream codec. 184 * @see SrsAvcAacCodec for the media stream codec.
169 */ 185 */
@@ -228,6 +228,10 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -228,6 +228,10 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
228 #define ERROR_STREAM_CASTER_TS_PMT 4018 228 #define ERROR_STREAM_CASTER_TS_PMT 4018
229 #define ERROR_STREAM_CASTER_TS_PSE 4019 229 #define ERROR_STREAM_CASTER_TS_PSE 4019
230 #define ERROR_STREAM_CASTER_TS_ES 4020 230 #define ERROR_STREAM_CASTER_TS_ES 4020
  231 +#define ERROR_STREAM_CASTER_TS_CODEC 4021
  232 +#define ERROR_STREAM_CASTER_AVC_SPS 4022
  233 +#define ERROR_STREAM_CASTER_AVC_PPS 4023
  234 +#define ERROR_STREAM_CASTER_FLV_TAG 4024
231 235
232 /** 236 /**
233 * whether the error code is an system control error. 237 * whether the error code is an system control error.
@@ -47,6 +47,7 @@ using namespace std; @@ -47,6 +47,7 @@ using namespace std;
47 #include <srs_kernel_codec.hpp> 47 #include <srs_kernel_codec.hpp>
48 #include <srs_kernel_file.hpp> 48 #include <srs_kernel_file.hpp>
49 #include <srs_lib_bandwidth.hpp> 49 #include <srs_lib_bandwidth.hpp>
  50 +#include <srs_raw_avc.hpp>
50 51
51 // kernel module. 52 // kernel module.
52 ISrsLog* _srs_log = new ISrsLog(); 53 ISrsLog* _srs_log = new ISrsLog();
@@ -82,6 +83,9 @@ struct Context @@ -82,6 +83,9 @@ struct Context
82 83
83 // for h264 raw stream, 84 // for h264 raw stream,
84 // @see: https://github.com/winlinvip/simple-rtmp-server/issues/66#issuecomment-62240521 85 // @see: https://github.com/winlinvip/simple-rtmp-server/issues/66#issuecomment-62240521
  86 + SrsRawH264Stream avc_raw;
  87 + // for h264 raw stream,
  88 + // @see: https://github.com/winlinvip/simple-rtmp-server/issues/66#issuecomment-62240521
85 SrsStream h264_raw_stream; 89 SrsStream h264_raw_stream;
86 // about SPS, @see: 7.3.2.1.1, H.264-AVC-ISO_IEC_14496-10-2012.pdf, page 62 90 // about SPS, @see: 7.3.2.1.1, H.264-AVC-ISO_IEC_14496-10-2012.pdf, page 62
87 std::string h264_sps; 91 std::string h264_sps;
@@ -1021,44 +1025,16 @@ int srs_rtmp_write_packet(srs_rtmp_t rtmp, char type, u_int32_t timestamp, char* @@ -1021,44 +1025,16 @@ int srs_rtmp_write_packet(srs_rtmp_t rtmp, char type, u_int32_t timestamp, char*
1021 Context* context = (Context*)rtmp; 1025 Context* context = (Context*)rtmp;
1022 1026
1023 SrsSharedPtrMessage* msg = NULL; 1027 SrsSharedPtrMessage* msg = NULL;
1024 -  
1025 - if (type == SRS_RTMP_TYPE_AUDIO) {  
1026 - SrsMessageHeader header;  
1027 - header.initialize_audio(size, timestamp, context->stream_id);  
1028 -  
1029 - msg = new SrsSharedPtrMessage();  
1030 - if ((ret = msg->create(&header, data, size)) != ERROR_SUCCESS) {  
1031 - srs_freep(data);  
1032 - return ret;  
1033 - }  
1034 - } else if (type == SRS_RTMP_TYPE_VIDEO) {  
1035 - SrsMessageHeader header;  
1036 - header.initialize_video(size, timestamp, context->stream_id);  
1037 -  
1038 - msg = new SrsSharedPtrMessage();  
1039 - if ((ret = msg->create(&header, data, size)) != ERROR_SUCCESS) {  
1040 - srs_freep(data);  
1041 - return ret;  
1042 - }  
1043 - } else if (type == SRS_RTMP_TYPE_SCRIPT) {  
1044 - SrsMessageHeader header;  
1045 - header.initialize_amf0_script(size, context->stream_id);  
1046 -  
1047 - msg = new SrsSharedPtrMessage();  
1048 - if ((ret = msg->create(&header, data, size)) != ERROR_SUCCESS) {  
1049 - srs_freep(data);  
1050 - return ret;  
1051 - } 1028 +
  1029 + if ((ret = srs_rtmp_create_msg(type, timestamp, data, size, context->stream_id, &msg)) != ERROR_SUCCESS) {
  1030 + return ret;
1052 } 1031 }
1053 -  
1054 - if (msg) {  
1055 - // send out encoded msg.  
1056 - if ((ret = context->rtmp->send_and_free_message(msg, context->stream_id)) != ERROR_SUCCESS) {  
1057 - return ret;  
1058 - }  
1059 - } else {  
1060 - // directly free data if not sent out.  
1061 - srs_freep(data); 1032 +
  1033 + srs_assert(msg);
  1034 +
  1035 + // send out encoded msg.
  1036 + if ((ret = context->rtmp->send_and_free_message(msg, context->stream_id)) != ERROR_SUCCESS) {
  1037 + return ret;
1062 } 1038 }
1063 1039
1064 return ret; 1040 return ret;
@@ -1403,52 +1379,37 @@ int srs_aac_adts_frame_size(char* aac_raw_data, int ac_raw_size) @@ -1403,52 +1379,37 @@ int srs_aac_adts_frame_size(char* aac_raw_data, int ac_raw_size)
1403 1379
1404 return size; 1380 return size;
1405 } 1381 }
1406 - 1382 +
1407 /** 1383 /**
1408 -* write h264 packet, with rtmp header.  
1409 -* @param frame_type, SrsCodecVideoAVCFrameKeyFrame or SrsCodecVideoAVCFrameInterFrame.  
1410 -* @param avc_packet_type, SrsCodecVideoAVCTypeSequenceHeader or SrsCodecVideoAVCTypeNALU.  
1411 -* @param h264_raw_data the h.264 raw data, user must free it. 1384 +* write h264 IPB-frame.
1412 */ 1385 */
1413 -int __srs_write_h264_packet(Context* context,  
1414 - int8_t frame_type, int8_t avc_packet_type,  
1415 - char* h264_raw_data, int h264_raw_size, u_int32_t dts, u_int32_t pts 1386 +int __srs_write_h264_ipb_frame(Context* context,
  1387 + char* frame, int frame_size, u_int32_t dts, u_int32_t pts
1416 ) { 1388 ) {
1417 - // the timestamp in rtmp message header is dts.  
1418 - u_int32_t timestamp = dts;  
1419 -  
1420 - // for h264 in RTMP video payload, there is 5bytes header:  
1421 - // 1bytes, FrameType | CodecID  
1422 - // 1bytes, AVCPacketType  
1423 - // 3bytes, CompositionTime, the cts.  
1424 - // @see: E.4.3 Video Tags, video_file_format_spec_v10_1.pdf, page 78  
1425 - int size = h264_raw_size + 5;  
1426 - char* data = new char[size];  
1427 - char* p = data;  
1428 -  
1429 - // @see: E.4.3 Video Tags, video_file_format_spec_v10_1.pdf, page 78  
1430 - // Frame Type, Type of video frame.  
1431 - // CodecID, Codec Identifier.  
1432 - // set the rtmp header  
1433 - *p++ = (frame_type << 4) | SrsCodecVideoAVC; 1389 + int ret = ERROR_SUCCESS;
1434 1390
1435 - // AVCPacketType  
1436 - *p++ = avc_packet_type; 1391 + // when sps or pps not sent, ignore the packet.
  1392 + // @see https://github.com/winlinvip/simple-rtmp-server/issues/203
  1393 + if (!context->h264_sps_pps_sent) {
  1394 + return ERROR_H264_DROP_BEFORE_SPS_PPS;
  1395 + }
1437 1396
1438 - // CompositionTime  
1439 - // pts = dts + cts, or  
1440 - // cts = pts - dts.  
1441 - // where cts is the header in rtmp video packet payload header.  
1442 - u_int32_t cts = pts - dts;  
1443 - char* pp = (char*)&cts;  
1444 - *p++ = pp[2];  
1445 - *p++ = pp[1];  
1446 - *p++ = pp[0]; 1397 + std::string ibp;
  1398 + int8_t frame_type;
  1399 + if ((ret = context->avc_raw.mux_ipb_frame(frame, frame_size, dts, pts, ibp, frame_type)) != ERROR_SUCCESS) {
  1400 + return ret;
  1401 + }
1447 1402
1448 - // h.264 raw data.  
1449 - memcpy(p, h264_raw_data, h264_raw_size); 1403 + int8_t avc_packet_type = SrsCodecVideoAVCTypeNALU;
  1404 + char* flv = NULL;
  1405 + int nb_flv = 0;
  1406 + if ((ret = context->avc_raw.mux_avc2flv(ibp, frame_type, avc_packet_type, dts, pts, &flv, &nb_flv)) != ERROR_SUCCESS) {
  1407 + return ret;
  1408 + }
1450 1409
1451 - return srs_rtmp_write_packet(context, SRS_RTMP_TYPE_VIDEO, timestamp, data, size); 1410 + // the timestamp in rtmp message header is dts.
  1411 + u_int32_t timestamp = dts;
  1412 + return srs_rtmp_write_packet(context, SRS_RTMP_TYPE_VIDEO, timestamp, flv, nb_flv);
1452 } 1413 }
1453 1414
1454 /** 1415 /**
@@ -1463,78 +1424,19 @@ int __srs_write_h264_sps_pps(Context* context, u_int32_t dts, u_int32_t pts) @@ -1463,78 +1424,19 @@ int __srs_write_h264_sps_pps(Context* context, u_int32_t dts, u_int32_t pts)
1463 return ret; 1424 return ret;
1464 } 1425 }
1465 1426
1466 - // 5bytes sps/pps header:  
1467 - // configurationVersion, AVCProfileIndication, profile_compatibility,  
1468 - // AVCLevelIndication, lengthSizeMinusOne  
1469 - // 3bytes size of sps:  
1470 - // numOfSequenceParameterSets, sequenceParameterSetLength(2B)  
1471 - // Nbytes of sps.  
1472 - // sequenceParameterSetNALUnit  
1473 - // 3bytes size of pps:  
1474 - // numOfPictureParameterSets, pictureParameterSetLength  
1475 - // Nbytes of pps:  
1476 - // pictureParameterSetNALUnit  
1477 - int nb_packet = 5  
1478 - + 3 + (int)context->h264_sps.length()  
1479 - + 3 + (int)context->h264_pps.length();  
1480 - char* packet = new char[nb_packet];  
1481 - SrsAutoFree(char, packet);  
1482 -  
1483 - // use stream to generate the h264 packet.  
1484 - SrsStream stream;  
1485 - if ((ret = stream.initialize(packet, nb_packet)) != ERROR_SUCCESS) { 1427 + // h264 raw to h264 packet.
  1428 + std::string sh;
  1429 + if ((ret = context->avc_raw.mux_sequence_header(context->h264_sps, context->h264_pps, dts, pts, sh)) != ERROR_SUCCESS) {
1486 return ret; 1430 return ret;
1487 } 1431 }
1488 1432
1489 - // decode the SPS:  
1490 - // @see: 7.3.2.1.1, H.264-AVC-ISO_IEC_14496-10-2012.pdf, page 62  
1491 - if (true) {  
1492 - srs_assert((int)context->h264_sps.length() >= 4);  
1493 - char* frame = (char*)context->h264_sps.data();  
1494 -  
1495 - // @see: Annex A Profiles and levels, H.264-AVC-ISO_IEC_14496-10.pdf, page 205  
1496 - // Baseline profile profile_idc is 66(0x42).  
1497 - // Main profile profile_idc is 77(0x4d).  
1498 - // Extended profile profile_idc is 88(0x58).  
1499 - u_int8_t profile_idc = frame[1];  
1500 - //u_int8_t constraint_set = frame[2];  
1501 - u_int8_t level_idc = frame[3];  
1502 -  
1503 - // generate the sps/pps header  
1504 - // 5.3.4.2.1 Syntax, H.264-AVC-ISO_IEC_14496-15.pdf, page 16  
1505 - // configurationVersion  
1506 - stream.write_1bytes(0x01);  
1507 - // AVCProfileIndication  
1508 - stream.write_1bytes(profile_idc);  
1509 - // profile_compatibility  
1510 - stream.write_1bytes(0x00);  
1511 - // AVCLevelIndication  
1512 - stream.write_1bytes(level_idc);  
1513 - // lengthSizeMinusOne, or NAL_unit_length, always use 4bytes size,  
1514 - // so we always set it to 0x03.  
1515 - stream.write_1bytes(0x03);  
1516 - }  
1517 -  
1518 - // sps  
1519 - if (true) {  
1520 - // 5.3.4.2.1 Syntax, H.264-AVC-ISO_IEC_14496-15.pdf, page 16  
1521 - // numOfSequenceParameterSets, always 1  
1522 - stream.write_1bytes(0x01);  
1523 - // sequenceParameterSetLength  
1524 - stream.write_2bytes(context->h264_sps.length());  
1525 - // sequenceParameterSetNALUnit  
1526 - stream.write_string(context->h264_sps);  
1527 - }  
1528 -  
1529 - // pps  
1530 - if (true) {  
1531 - // 5.3.4.2.1 Syntax, H.264-AVC-ISO_IEC_14496-15.pdf, page 16  
1532 - // numOfPictureParameterSets, always 1  
1533 - stream.write_1bytes(0x01);  
1534 - // pictureParameterSetLength  
1535 - stream.write_2bytes(context->h264_pps.length());  
1536 - // pictureParameterSetNALUnit  
1537 - stream.write_string(context->h264_pps); 1433 + // h264 packet to flv packet.
  1434 + int8_t frame_type = SrsCodecVideoAVCFrameKeyFrame;
  1435 + int8_t avc_packet_type = SrsCodecVideoAVCTypeSequenceHeader;
  1436 + char* flv = NULL;
  1437 + int nb_flv = 0;
  1438 + if ((ret = context->avc_raw.mux_avc2flv(sh, frame_type, avc_packet_type, dts, pts, &flv, &nb_flv)) != ERROR_SUCCESS) {
  1439 + return ret;
1538 } 1440 }
1539 1441
1540 // reset sps and pps. 1442 // reset sps and pps.
@@ -1542,75 +1444,9 @@ int __srs_write_h264_sps_pps(Context* context, u_int32_t dts, u_int32_t pts) @@ -1542,75 +1444,9 @@ int __srs_write_h264_sps_pps(Context* context, u_int32_t dts, u_int32_t pts)
1542 context->h264_pps_changed = false; 1444 context->h264_pps_changed = false;
1543 context->h264_sps_pps_sent = true; 1445 context->h264_sps_pps_sent = true;
1544 1446
1545 - // TODO: FIXME: for more profile.  
1546 - // 5.3.4.2.1 Syntax, H.264-AVC-ISO_IEC_14496-15.pdf, page 16  
1547 - // profile_idc == 100 || profile_idc == 110 || profile_idc == 122 || profile_idc == 144  
1548 -  
1549 - // send out h264 packet.  
1550 - int8_t frame_type = SrsCodecVideoAVCFrameKeyFrame;  
1551 - int8_t avc_packet_type = SrsCodecVideoAVCTypeSequenceHeader;  
1552 - return __srs_write_h264_packet(  
1553 - context, frame_type, avc_packet_type,  
1554 - packet, nb_packet, dts, pts  
1555 - );  
1556 -}  
1557 -  
1558 -/**  
1559 -* write h264 IPB-frame.  
1560 -*/  
1561 -int __srs_write_h264_ipb_frame(Context* context,  
1562 - char* data, int size, u_int32_t dts, u_int32_t pts  
1563 -) {  
1564 - int ret = ERROR_SUCCESS;  
1565 -  
1566 - // when sps or pps not sent, ignore the packet.  
1567 - // @see https://github.com/winlinvip/simple-rtmp-server/issues/203  
1568 - if (!context->h264_sps_pps_sent) {  
1569 - return ERROR_H264_DROP_BEFORE_SPS_PPS;  
1570 - }  
1571 -  
1572 - // 5bits, 7.3.1 NAL unit syntax,  
1573 - // H.264-AVC-ISO_IEC_14496-10.pdf, page 44.  
1574 - // 7: SPS, 8: PPS, 5: I Frame, 1: P Frame  
1575 - u_int8_t nal_unit_type = (char)data[0] & 0x1f;  
1576 -  
1577 - // 4bytes size of nalu:  
1578 - // NALUnitLength  
1579 - // Nbytes of nalu.  
1580 - // NALUnit  
1581 - int nb_packet = 4 + size;  
1582 - char* packet = new char[nb_packet];  
1583 - SrsAutoFree(char, packet);  
1584 -  
1585 - // use stream to generate the h264 packet.  
1586 - SrsStream stream;  
1587 - if ((ret = stream.initialize(packet, nb_packet)) != ERROR_SUCCESS) {  
1588 - return ret;  
1589 - }  
1590 -  
1591 - // 5.3.4.2.1 Syntax, H.264-AVC-ISO_IEC_14496-15.pdf, page 16  
1592 - // lengthSizeMinusOne, or NAL_unit_length, always use 4bytes size  
1593 - u_int32_t NAL_unit_length = size;  
1594 -  
1595 - // mux the avc NALU in "ISO Base Media File Format"  
1596 - // from H.264-AVC-ISO_IEC_14496-15.pdf, page 20  
1597 - // NALUnitLength  
1598 - stream.write_4bytes(NAL_unit_length);  
1599 - // NALUnit  
1600 - stream.write_bytes(data, size);  
1601 -  
1602 - // send out h264 packet.  
1603 - int8_t frame_type = SrsCodecVideoAVCFrameInterFrame;  
1604 - if (nal_unit_type != 1) {  
1605 - frame_type = SrsCodecVideoAVCFrameKeyFrame;  
1606 - }  
1607 - int8_t avc_packet_type = SrsCodecVideoAVCTypeNALU;  
1608 - return __srs_write_h264_packet(  
1609 - context, frame_type, avc_packet_type,  
1610 - packet, nb_packet, dts, pts  
1611 - );  
1612 -  
1613 - return ret; 1447 + // the timestamp in rtmp message header is dts.
  1448 + u_int32_t timestamp = dts;
  1449 + return srs_rtmp_write_packet(context, SRS_RTMP_TYPE_VIDEO, timestamp, flv, nb_flv);
1614 } 1450 }
1615 1451
1616 /** 1452 /**
@@ -1620,27 +1456,14 @@ int __srs_write_h264_raw_frame(Context* context, @@ -1620,27 +1456,14 @@ int __srs_write_h264_raw_frame(Context* context,
1620 char* frame, int frame_size, u_int32_t dts, u_int32_t pts 1456 char* frame, int frame_size, u_int32_t dts, u_int32_t pts
1621 ) { 1457 ) {
1622 int ret = ERROR_SUCCESS; 1458 int ret = ERROR_SUCCESS;
1623 -  
1624 - // ignore invalid frame,  
1625 - // atleast 1bytes for SPS to decode the type  
1626 - if (frame_size < 1) {  
1627 - return ret;  
1628 - }  
1629 -  
1630 - // 5bits, 7.3.1 NAL unit syntax,  
1631 - // H.264-AVC-ISO_IEC_14496-10.pdf, page 44.  
1632 - // 7: SPS, 8: PPS, 5: I Frame, 1: P Frame  
1633 - u_int8_t nal_unit_type = (char)frame[0] & 0x1f;  
1634 -  
1635 - if (nal_unit_type == 7) {  
1636 - // atleast 1bytes for SPS to decode the type, profile, constrain and level.  
1637 - if (frame_size < 4) { 1459 +
  1460 + // for sps
  1461 + if (context->avc_raw.is_sps(frame, frame_size)) {
  1462 + std::string sps;
  1463 + if ((ret = context->avc_raw.sps_demux(frame, frame_size, sps)) != ERROR_SUCCESS) {
1638 return ret; 1464 return ret;
1639 } 1465 }
1640 1466
1641 - std::string sps;  
1642 - sps.append(frame, frame_size);  
1643 -  
1644 if (context->h264_sps == sps) { 1467 if (context->h264_sps == sps) {
1645 return ERROR_H264_DUPLICATED_SPS; 1468 return ERROR_H264_DUPLICATED_SPS;
1646 } 1469 }
@@ -1648,10 +1471,14 @@ int __srs_write_h264_raw_frame(Context* context, @@ -1648,10 +1471,14 @@ int __srs_write_h264_raw_frame(Context* context,
1648 context->h264_sps = sps; 1471 context->h264_sps = sps;
1649 1472
1650 return __srs_write_h264_sps_pps(context, dts, pts); 1473 return __srs_write_h264_sps_pps(context, dts, pts);
1651 - } else if (nal_unit_type == 8) {  
1652 - 1474 + }
  1475 +
  1476 + // for pps
  1477 + if (context->avc_raw.is_pps(frame, frame_size)) {
1653 std::string pps; 1478 std::string pps;
1654 - pps.append(frame, frame_size); 1479 + if ((ret = context->avc_raw.pps_demux(frame, frame_size, pps)) != ERROR_SUCCESS) {
  1480 + return ret;
  1481 + }
1655 1482
1656 if (context->h264_pps == pps) { 1483 if (context->h264_pps == pps) {
1657 return ERROR_H264_DUPLICATED_PPS; 1484 return ERROR_H264_DUPLICATED_PPS;
@@ -1660,11 +1487,10 @@ int __srs_write_h264_raw_frame(Context* context, @@ -1660,11 +1487,10 @@ int __srs_write_h264_raw_frame(Context* context,
1660 context->h264_pps = pps; 1487 context->h264_pps = pps;
1661 1488
1662 return __srs_write_h264_sps_pps(context, dts, pts); 1489 return __srs_write_h264_sps_pps(context, dts, pts);
1663 - } else {  
1664 - return __srs_write_h264_ipb_frame(context, frame, frame_size, dts, pts);  
1665 } 1490 }
1666 -  
1667 - return ret; 1491 +
  1492 + // ibp frame.
  1493 + return __srs_write_h264_ipb_frame(context, frame, frame_size, dts, pts);
1668 } 1494 }
1669 1495
1670 /** 1496 /**
@@ -1692,29 +1518,21 @@ int srs_h264_write_raw_frames(srs_rtmp_t rtmp, @@ -1692,29 +1518,21 @@ int srs_h264_write_raw_frames(srs_rtmp_t rtmp,
1692 1518
1693 // send each frame. 1519 // send each frame.
1694 while (!context->h264_raw_stream.empty()) { 1520 while (!context->h264_raw_stream.empty()) {
1695 - // each frame must prefixed by annexb format.  
1696 - // about annexb, @see H.264-AVC-ISO_IEC_14496-10.pdf, page 211.  
1697 - int pnb_start_code = 0;  
1698 - if (!srs_avc_startswith_annexb(&context->h264_raw_stream, &pnb_start_code)) {  
1699 - return ERROR_H264_API_NO_PREFIXED; 1521 + char* frame = NULL;
  1522 + int frame_size = 0;
  1523 + bool got_sps_pps = false;
  1524 + if ((ret = context->avc_raw.annexb_demux(&context->h264_raw_stream, &frame, &frame_size)) != ERROR_SUCCESS) {
  1525 + return ret;
1700 } 1526 }
1701 - int start = context->h264_raw_stream.pos() + pnb_start_code;  
1702 -  
1703 - // find the last frame prefixed by annexb format.  
1704 - context->h264_raw_stream.skip(pnb_start_code);  
1705 - while (!context->h264_raw_stream.empty()) {  
1706 - if (srs_avc_startswith_annexb(&context->h264_raw_stream, NULL)) {  
1707 - break;  
1708 - }  
1709 - context->h264_raw_stream.skip(1); 1527 +
  1528 + // ignore invalid frame,
  1529 + // atleast 1bytes for SPS to decode the type
  1530 + if (frame_size <= 0) {
  1531 + continue;
1710 } 1532 }
1711 - int size = context->h264_raw_stream.pos() - start;  
1712 -  
1713 - // send out the frame.  
1714 - char* frame = context->h264_raw_stream.data() + start;  
1715 1533
1716 // it may be return error, but we must process all packets. 1534 // it may be return error, but we must process all packets.
1717 - if ((ret = __srs_write_h264_raw_frame(context, frame, size, dts, pts)) != ERROR_SUCCESS) { 1535 + if ((ret = __srs_write_h264_raw_frame(context, frame, frame_size, dts, pts)) != ERROR_SUCCESS) {
1718 error_code_return = ret; 1536 error_code_return = ret;
1719 1537
1720 // ignore known error, process all packets. 1538 // ignore known error, process all packets.
  1 +/*
  2 +The MIT License (MIT)
  3 +
  4 +Copyright (c) 2013-2015 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 +#include <srs_raw_avc.hpp>
  25 +
  26 +#include <string.h>
  27 +using namespace std;
  28 +
  29 +#include <srs_kernel_error.hpp>
  30 +#include <srs_kernel_stream.hpp>
  31 +#include <srs_kernel_utility.hpp>
  32 +#include <srs_core_autofree.hpp>
  33 +#include <srs_kernel_codec.hpp>
  34 +
  35 +SrsRawH264Stream::SrsRawH264Stream()
  36 +{
  37 +}
  38 +
  39 +SrsRawH264Stream::~SrsRawH264Stream()
  40 +{
  41 +}
  42 +
  43 +int SrsRawH264Stream::annexb_demux(SrsStream* stream, char** pframe, int* pnb_frame)
  44 +{
  45 + int ret = ERROR_SUCCESS;
  46 +
  47 + *pframe = NULL;
  48 + *pnb_frame = 0;
  49 +
  50 + while (!stream->empty()) {
  51 + // each frame must prefixed by annexb format.
  52 + // about annexb, @see H.264-AVC-ISO_IEC_14496-10.pdf, page 211.
  53 + int pnb_start_code = 0;
  54 + if (!srs_avc_startswith_annexb(stream, &pnb_start_code)) {
  55 + return ERROR_H264_API_NO_PREFIXED;
  56 + }
  57 + int start = stream->pos() + pnb_start_code;
  58 +
  59 + // find the last frame prefixed by annexb format.
  60 + stream->skip(pnb_start_code);
  61 + while (!stream->empty()) {
  62 + if (srs_avc_startswith_annexb(stream, NULL)) {
  63 + break;
  64 + }
  65 + stream->skip(1);
  66 + }
  67 +
  68 + // demux the frame.
  69 + *pnb_frame = stream->pos() - start;
  70 + *pframe = stream->data() + start;
  71 + break;
  72 + }
  73 +
  74 + return ret;
  75 +}
  76 +
  77 +bool SrsRawH264Stream::is_sps(char* frame, int nb_frame)
  78 +{
  79 + srs_assert(nb_frame > 0);
  80 +
  81 + // 5bits, 7.3.1 NAL unit syntax,
  82 + // H.264-AVC-ISO_IEC_14496-10.pdf, page 44.
  83 + // 7: SPS, 8: PPS, 5: I Frame, 1: P Frame
  84 + u_int8_t nal_unit_type = (char)frame[0] & 0x1f;
  85 +
  86 + return nal_unit_type == 7;
  87 +}
  88 +
  89 +bool SrsRawH264Stream::is_pps(char* frame, int nb_frame)
  90 +{
  91 + srs_assert(nb_frame > 0);
  92 +
  93 + // 5bits, 7.3.1 NAL unit syntax,
  94 + // H.264-AVC-ISO_IEC_14496-10.pdf, page 44.
  95 + // 7: SPS, 8: PPS, 5: I Frame, 1: P Frame
  96 + u_int8_t nal_unit_type = (char)frame[0] & 0x1f;
  97 +
  98 + return nal_unit_type == 8;
  99 +}
  100 +
  101 +int SrsRawH264Stream::sps_demux(char* frame, int nb_frame, string& sps)
  102 +{
  103 + int ret = ERROR_SUCCESS;
  104 +
  105 + // atleast 1bytes for SPS to decode the type, profile, constrain and level.
  106 + if (nb_frame < 4) {
  107 + return ret;
  108 + }
  109 +
  110 + sps = "";
  111 + if (nb_frame > 0) {
  112 + sps.append(frame, nb_frame);
  113 + }
  114 +
  115 + // should never be empty.
  116 + if (sps.empty()) {
  117 + return ERROR_STREAM_CASTER_AVC_SPS;
  118 + }
  119 +
  120 + return ret;
  121 +}
  122 +
  123 +int SrsRawH264Stream::pps_demux(char* frame, int nb_frame, string& pps)
  124 +{
  125 + int ret = ERROR_SUCCESS;
  126 +
  127 + pps = "";
  128 + if (nb_frame > 0) {
  129 + pps.append(frame, nb_frame);
  130 + }
  131 +
  132 + // should never be empty.
  133 + if (pps.empty()) {
  134 + return ERROR_STREAM_CASTER_AVC_PPS;
  135 + }
  136 +
  137 + return ret;
  138 +}
  139 +
  140 +int SrsRawH264Stream::mux_sequence_header(string sps, string pps, u_int32_t dts, u_int32_t pts, string& sh)
  141 +{
  142 + int ret = ERROR_SUCCESS;
  143 +
  144 + // 5bytes sps/pps header:
  145 + // configurationVersion, AVCProfileIndication, profile_compatibility,
  146 + // AVCLevelIndication, lengthSizeMinusOne
  147 + // 3bytes size of sps:
  148 + // numOfSequenceParameterSets, sequenceParameterSetLength(2B)
  149 + // Nbytes of sps.
  150 + // sequenceParameterSetNALUnit
  151 + // 3bytes size of pps:
  152 + // numOfPictureParameterSets, pictureParameterSetLength
  153 + // Nbytes of pps:
  154 + // pictureParameterSetNALUnit
  155 + int nb_packet = 5
  156 + + 3 + (int)sps.length()
  157 + + 3 + (int)pps.length();
  158 + char* packet = new char[nb_packet];
  159 + SrsAutoFree(char, packet);
  160 +
  161 + // use stream to generate the h264 packet.
  162 + SrsStream stream;
  163 + if ((ret = stream.initialize(packet, nb_packet)) != ERROR_SUCCESS) {
  164 + return ret;
  165 + }
  166 +
  167 + // decode the SPS:
  168 + // @see: 7.3.2.1.1, H.264-AVC-ISO_IEC_14496-10-2012.pdf, page 62
  169 + if (true) {
  170 + srs_assert((int)sps.length() >= 4);
  171 + char* frame = (char*)sps.data();
  172 +
  173 + // @see: Annex A Profiles and levels, H.264-AVC-ISO_IEC_14496-10.pdf, page 205
  174 + // Baseline profile profile_idc is 66(0x42).
  175 + // Main profile profile_idc is 77(0x4d).
  176 + // Extended profile profile_idc is 88(0x58).
  177 + u_int8_t profile_idc = frame[1];
  178 + //u_int8_t constraint_set = frame[2];
  179 + u_int8_t level_idc = frame[3];
  180 +
  181 + // generate the sps/pps header
  182 + // 5.3.4.2.1 Syntax, H.264-AVC-ISO_IEC_14496-15.pdf, page 16
  183 + // configurationVersion
  184 + stream.write_1bytes(0x01);
  185 + // AVCProfileIndication
  186 + stream.write_1bytes(profile_idc);
  187 + // profile_compatibility
  188 + stream.write_1bytes(0x00);
  189 + // AVCLevelIndication
  190 + stream.write_1bytes(level_idc);
  191 + // lengthSizeMinusOne, or NAL_unit_length, always use 4bytes size,
  192 + // so we always set it to 0x03.
  193 + stream.write_1bytes(0x03);
  194 + }
  195 +
  196 + // sps
  197 + if (true) {
  198 + // 5.3.4.2.1 Syntax, H.264-AVC-ISO_IEC_14496-15.pdf, page 16
  199 + // numOfSequenceParameterSets, always 1
  200 + stream.write_1bytes(0x01);
  201 + // sequenceParameterSetLength
  202 + stream.write_2bytes(sps.length());
  203 + // sequenceParameterSetNALUnit
  204 + stream.write_string(sps);
  205 + }
  206 +
  207 + // pps
  208 + if (true) {
  209 + // 5.3.4.2.1 Syntax, H.264-AVC-ISO_IEC_14496-15.pdf, page 16
  210 + // numOfPictureParameterSets, always 1
  211 + stream.write_1bytes(0x01);
  212 + // pictureParameterSetLength
  213 + stream.write_2bytes(pps.length());
  214 + // pictureParameterSetNALUnit
  215 + stream.write_string(pps);
  216 + }
  217 +
  218 + // TODO: FIXME: for more profile.
  219 + // 5.3.4.2.1 Syntax, H.264-AVC-ISO_IEC_14496-15.pdf, page 16
  220 + // profile_idc == 100 || profile_idc == 110 || profile_idc == 122 || profile_idc == 144
  221 +
  222 + sh = "";
  223 + sh.append(packet, nb_packet);
  224 +
  225 + return ret;
  226 +}
  227 +
  228 +int SrsRawH264Stream::mux_ipb_frame(char* frame, int nb_frame, u_int32_t dts, u_int32_t pts, string& ibp, int8_t& frame_type)
  229 +{
  230 + int ret = ERROR_SUCCESS;
  231 +
  232 + // 5bits, 7.3.1 NAL unit syntax,
  233 + // H.264-AVC-ISO_IEC_14496-10.pdf, page 44.
  234 + // 7: SPS, 8: PPS, 5: I Frame, 1: P Frame
  235 + u_int8_t nal_unit_type = (char)frame[0] & 0x1f;
  236 +
  237 + // 4bytes size of nalu:
  238 + // NALUnitLength
  239 + // Nbytes of nalu.
  240 + // NALUnit
  241 + int nb_packet = 4 + nb_frame;
  242 + char* packet = new char[nb_packet];
  243 + SrsAutoFree(char, packet);
  244 +
  245 + // use stream to generate the h264 packet.
  246 + SrsStream stream;
  247 + if ((ret = stream.initialize(packet, nb_packet)) != ERROR_SUCCESS) {
  248 + return ret;
  249 + }
  250 +
  251 + // 5.3.4.2.1 Syntax, H.264-AVC-ISO_IEC_14496-15.pdf, page 16
  252 + // lengthSizeMinusOne, or NAL_unit_length, always use 4bytes size
  253 + u_int32_t NAL_unit_length = nb_frame;
  254 +
  255 + // mux the avc NALU in "ISO Base Media File Format"
  256 + // from H.264-AVC-ISO_IEC_14496-15.pdf, page 20
  257 + // NALUnitLength
  258 + stream.write_4bytes(NAL_unit_length);
  259 + // NALUnit
  260 + stream.write_bytes(frame, nb_frame);
  261 +
  262 + // send out h264 packet.
  263 + frame_type = SrsCodecVideoAVCFrameInterFrame;
  264 + if (nal_unit_type != 1) {
  265 + frame_type = SrsCodecVideoAVCFrameKeyFrame;
  266 + }
  267 +
  268 + ibp = "";
  269 + ibp.append(packet, nb_packet);
  270 +
  271 + return ret;
  272 +}
  273 +
  274 +int SrsRawH264Stream::mux_avc2flv(string video, int8_t frame_type, int8_t avc_packet_type, u_int32_t dts, u_int32_t pts, char** flv, int* nb_flv)
  275 +{
  276 + int ret = ERROR_SUCCESS;
  277 +
  278 + // for h264 in RTMP video payload, there is 5bytes header:
  279 + // 1bytes, FrameType | CodecID
  280 + // 1bytes, AVCPacketType
  281 + // 3bytes, CompositionTime, the cts.
  282 + // @see: E.4.3 Video Tags, video_file_format_spec_v10_1.pdf, page 78
  283 + int size = video.length() + 5;
  284 + char* data = new char[size];
  285 + char* p = data;
  286 +
  287 + // @see: E.4.3 Video Tags, video_file_format_spec_v10_1.pdf, page 78
  288 + // Frame Type, Type of video frame.
  289 + // CodecID, Codec Identifier.
  290 + // set the rtmp header
  291 + *p++ = (frame_type << 4) | SrsCodecVideoAVC;
  292 +
  293 + // AVCPacketType
  294 + *p++ = avc_packet_type;
  295 +
  296 + // CompositionTime
  297 + // pts = dts + cts, or
  298 + // cts = pts - dts.
  299 + // where cts is the header in rtmp video packet payload header.
  300 + u_int32_t cts = pts - dts;
  301 + char* pp = (char*)&cts;
  302 + *p++ = pp[2];
  303 + *p++ = pp[1];
  304 + *p++ = pp[0];
  305 +
  306 + // h.264 raw data.
  307 + memcpy(p, video.data(), video.length());
  308 +
  309 + *flv = data;
  310 + *nb_flv = size;
  311 +
  312 + return ret;
  313 +}
  314 +
  1 +/*
  2 +The MIT License (MIT)
  3 +
  4 +Copyright (c) 2013-2015 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_PROTOCOL_RAW_AVC_HPP
  25 +#define SRS_PROTOCOL_RAW_AVC_HPP
  26 +
  27 +/*
  28 +#include <srs_raw_avc.hpp>
  29 +*/
  30 +
  31 +#include <srs_core.hpp>
  32 +
  33 +#include <string>
  34 +
  35 +class SrsStream;
  36 +
  37 +/**
  38 +* the raw h.264 stream, in annexb.
  39 +*/
  40 +class SrsRawH264Stream
  41 +{
  42 +public:
  43 + SrsRawH264Stream();
  44 + virtual ~SrsRawH264Stream();
  45 +public:
  46 + /**
  47 + * demux the stream in annexb format.
  48 + * @param stream the input stream bytes.
  49 + * @param pframe the output h.264 frame in stream. user should never free it.
  50 + * @param pnb_frame the output h.264 frame size.
  51 + */
  52 + virtual int annexb_demux(SrsStream* stream, char** pframe, int* pnb_frame);
  53 + /**
  54 + * whether the frame is sps or pps.
  55 + */
  56 + virtual bool is_sps(char* frame, int nb_frame);
  57 + virtual bool is_pps(char* frame, int nb_frame);
  58 + /**
  59 + * demux the sps or pps to string.
  60 + * @param sps/pps output the sps/pps.
  61 + */
  62 + virtual int sps_demux(char* frame, int nb_frame, std::string& sps);
  63 + virtual int pps_demux(char* frame, int nb_frame, std::string& pps);
  64 +public:
  65 + /**
  66 + * h264 raw data to h264 packet, without flv payload header.
  67 + * mux the sps/pps to flv sequence header packet.
  68 + * @param sh output the sequence header.
  69 + */
  70 + virtual int mux_sequence_header(std::string sps, std::string pps, u_int32_t dts, u_int32_t pts, std::string& sh);
  71 + /**
  72 + * h264 raw data to h264 packet, without flv payload header.
  73 + * mux the ibp to flv ibp packet.
  74 + * @param ibp output the packet.
  75 + * @param frame_type output the frame type.
  76 + */
  77 + virtual int mux_ipb_frame(char* frame, int nb_frame, u_int32_t dts, u_int32_t pts, std::string& ibp, int8_t& frame_type);
  78 + /**
  79 + * mux the avc video packet to flv video packet.
  80 + * @param frame_type, SrsCodecVideoAVCFrameKeyFrame or SrsCodecVideoAVCFrameInterFrame.
  81 + * @param avc_packet_type, SrsCodecVideoAVCTypeSequenceHeader or SrsCodecVideoAVCTypeNALU.
  82 + * @param video the h.264 raw data.
  83 + * @param flv output the muxed flv packet.
  84 + * @param nb_flv output the muxed flv size.
  85 + */
  86 + virtual int mux_avc2flv(std::string video, int8_t frame_type, int8_t avc_packet_type, u_int32_t dts, u_int32_t pts, char** flv, int* nb_flv);
  87 +};
  88 +
  89 +#endif
@@ -30,6 +30,7 @@ using namespace std; @@ -30,6 +30,7 @@ using namespace std;
30 #include <srs_kernel_utility.hpp> 30 #include <srs_kernel_utility.hpp>
31 #include <srs_kernel_stream.hpp> 31 #include <srs_kernel_stream.hpp>
32 #include <srs_rtmp_stack.hpp> 32 #include <srs_rtmp_stack.hpp>
  33 +#include <srs_kernel_codec.hpp>
33 34
34 void srs_discovery_tc_url( 35 void srs_discovery_tc_url(
35 string tcUrl, 36 string tcUrl,
@@ -287,3 +288,61 @@ int srs_chunk_header_c3( @@ -287,3 +288,61 @@ int srs_chunk_header_c3(
287 return p - cache; 288 return p - cache;
288 } 289 }
289 290
  291 +int __srs_rtmp_create_msg(char type, u_int32_t timestamp, char* data, int size, int stream_id, SrsSharedPtrMessage** ppmsg)
  292 +{
  293 + int ret = ERROR_SUCCESS;
  294 +
  295 + *ppmsg = NULL;
  296 + SrsSharedPtrMessage* msg = NULL;
  297 +
  298 + if (type == SrsCodecFlvTagAudio) {
  299 + SrsMessageHeader header;
  300 + header.initialize_audio(size, timestamp, stream_id);
  301 +
  302 + msg = new SrsSharedPtrMessage();
  303 + if ((ret = msg->create(&header, data, size)) != ERROR_SUCCESS) {
  304 + srs_freep(msg);
  305 + return ret;
  306 + }
  307 + } else if (type == SrsCodecFlvTagVideo) {
  308 + SrsMessageHeader header;
  309 + header.initialize_video(size, timestamp, stream_id);
  310 +
  311 + msg = new SrsSharedPtrMessage();
  312 + if ((ret = msg->create(&header, data, size)) != ERROR_SUCCESS) {
  313 + srs_freep(msg);
  314 + return ret;
  315 + }
  316 + } else if (type == SrsCodecFlvTagScript) {
  317 + SrsMessageHeader header;
  318 + header.initialize_amf0_script(size, stream_id);
  319 +
  320 + msg = new SrsSharedPtrMessage();
  321 + if ((ret = msg->create(&header, data, size)) != ERROR_SUCCESS) {
  322 + srs_freep(msg);
  323 + return ret;
  324 + }
  325 + } else {
  326 + ret = ERROR_STREAM_CASTER_FLV_TAG;
  327 + srs_error("rtmp unknown tag type=%#x. ret=%d", type, ret);
  328 + return ret;
  329 + }
  330 +
  331 + *ppmsg = msg;
  332 +
  333 + return ret;
  334 +}
  335 +
  336 +int srs_rtmp_create_msg(char type, u_int32_t timestamp, char* data, int size, int stream_id, SrsSharedPtrMessage** ppmsg)
  337 +{
  338 + int ret = ERROR_SUCCESS;
  339 +
  340 + // only when failed, we must free the data.
  341 + if ((ret = __srs_rtmp_create_msg(type, timestamp, data, size, stream_id, ppmsg)) != ERROR_SUCCESS) {
  342 + srs_freep(data);
  343 + return ret;
  344 + }
  345 +
  346 + return ret;
  347 +}
  348 +
@@ -34,6 +34,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -34,6 +34,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 #include <srs_kernel_consts.hpp> 34 #include <srs_kernel_consts.hpp>
35 35
36 class SrsMessageHeader; 36 class SrsMessageHeader;
  37 +class SrsSharedPtrMessage;
37 38
38 /** 39 /**
39 * parse the tcUrl, output the schema, host, vhost, app and port. 40 * parse the tcUrl, output the schema, host, vhost, app and port.
@@ -110,5 +111,12 @@ extern int srs_chunk_header_c3( @@ -110,5 +111,12 @@ extern int srs_chunk_header_c3(
110 char* cache, int nb_cache 111 char* cache, int nb_cache
111 ); 112 );
112 113
  114 +/**
  115 +* create shared ptr message from bytes.
  116 +* @param data the packet bytes. user should never free it.
  117 +* @param ppmsg output the shared ptr message. user should free it.
  118 +*/
  119 +extern int srs_rtmp_create_msg(char type, u_int32_t timestamp, char* data, int size, int stream_id, SrsSharedPtrMessage** ppmsg);
  120 +
113 #endif 121 #endif
114 122