Skip to content

Commit 16afe7d

Browse files
committed
fix ossrs#250, support push MPEGTS over UDP to SRS. 2.0.111
1 parent 4246be9 commit 16afe7d

File tree

7 files changed

+505
-249
lines changed

7 files changed

+505
-249
lines changed

README.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -486,7 +486,7 @@ Supported operating systems and hardware:
486486
).
487487
1. Support HLS(h.264+mp3) streaming, read
488488
[#301](https://github.com/winlinvip/simple-rtmp-server/issues/301).
489-
1. [dev] Support push MPEG-TS over UDP to SRS, read
489+
1. Support push MPEG-TS over UDP to SRS, read
490490
[#250](https://github.com/winlinvip/simple-rtmp-server/issues/250).
491491
1. [no-plan] Support <500ms latency, FRSC(Fast RTMP-compatible Stream Channel tech).
492492
1. [no-plan] Support RTMP 302 redirect [#92](https://github.com/winlinvip/simple-rtmp-server/issues/92).
@@ -525,6 +525,7 @@ Supported operating systems and hardware:
525525

526526
### SRS 2.0 history
527527

528+
* v2.0, 2015-01-31, for [#250](https://github.com/winlinvip/simple-rtmp-server/issues/250), support push MPEGTS over UDP to SRS. 2.0.111
528529
* v2.0, 2015-01-29, build libfdk-aac in ffmpeg. 2.0.108
529530
* v2.0, 2015-01-25, for [#301](https://github.com/winlinvip/simple-rtmp-server/issues/301), hls support h.264+mp3, ok for vlc. 2.0.107
530531
* v2.0, 2015-01-25, for [#301](https://github.com/winlinvip/simple-rtmp-server/issues/301), http ts stream support h.264+mp3. 2.0.106

trunk/src/app/srs_app_mpegts_udp.cpp

+137-51
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,20 @@ int SrsMpegtsQueue::push(SrsSharedPtrMessage* msg)
7676
{
7777
int ret = ERROR_SUCCESS;
7878

79-
if (msgs.find(msg->timestamp) != msgs.end()) {
80-
srs_warn("mpegts: free the msg for dts exists, dts=%"PRId64, msg->timestamp);
81-
srs_freep(msg);
82-
return ret;
79+
// TODO: FIXME: use right way.
80+
for (int i = 0; i < 10; i++) {
81+
if (msgs.find(msg->timestamp) == msgs.end()) {
82+
break;
83+
}
84+
85+
// adjust the ts, add 1ms.
86+
msg->timestamp += 1;
87+
88+
if (i >= 5) {
89+
srs_warn("mpegts: free the msg for dts exists, dts=%"PRId64, msg->timestamp);
90+
srs_freep(msg);
91+
return ret;
92+
}
8393
}
8494

8595
if (msg->is_audio()) {
@@ -114,6 +124,8 @@ SrsSharedPtrMessage* SrsMpegtsQueue::dequeue()
114124
if (msg->is_video()) {
115125
nb_videos--;
116126
}
127+
128+
return msg;
117129
}
118130

119131
return NULL;
@@ -131,6 +143,7 @@ SrsMpegtsOverUdp::SrsMpegtsOverUdp(SrsConfDirective* c)
131143
stfd = NULL;
132144
stream_id = 0;
133145
avc = new SrsRawH264Stream();
146+
aac = new SrsRawAacStream();
134147
h264_sps_changed = false;
135148
h264_pps_changed = false;
136149
h264_sps_pps_sent = false;
@@ -145,6 +158,7 @@ SrsMpegtsOverUdp::~SrsMpegtsOverUdp()
145158
srs_freep(stream);
146159
srs_freep(context);
147160
srs_freep(avc);
161+
srs_freep(aac);
148162
srs_freep(queue);
149163
}
150164

@@ -309,6 +323,9 @@ int SrsMpegtsOverUdp::on_ts_message(SrsTsMessage* msg)
309323
if (msg->channel->stream == SrsTsStreamVideoH264) {
310324
return on_ts_video(msg, &avs);
311325
}
326+
if (msg->channel->stream == SrsTsStreamAudioAAC) {
327+
return on_ts_audio(msg, &avs);
328+
}
312329

313330
// TODO: FIXME: implements it.
314331
return ret;
@@ -326,6 +343,10 @@ int SrsMpegtsOverUdp::on_ts_video(SrsTsMessage* msg, SrsStream* avs)
326343
// ts tbn to flv tbn.
327344
u_int32_t dts = msg->dts / 90;
328345
u_int32_t pts = msg->dts / 90;
346+
347+
// the whole ts pes video packet must be a flv frame packet.
348+
char* ibpframe = avs->data() + avs->pos();
349+
int ibpframe_size = avs->size() - avs->pos();
329350

330351
// send each frame.
331352
while (!avs->empty()) {
@@ -342,59 +363,50 @@ int SrsMpegtsOverUdp::on_ts_video(SrsTsMessage* msg, SrsStream* avs)
342363
continue;
343364
}
344365

345-
// it may be return error, but we must process all packets.
346-
if ((ret = write_h264_raw_frame(frame, frame_size, dts, pts)) != ERROR_SUCCESS) {
347-
if (ret == ERROR_H264_DROP_BEFORE_SPS_PPS) {
366+
// for sps
367+
if (avc->is_sps(frame, frame_size)) {
368+
std::string sps;
369+
if ((ret = avc->sps_demux(frame, frame_size, sps)) != ERROR_SUCCESS) {
370+
return ret;
371+
}
372+
373+
if (h264_sps == sps) {
348374
continue;
349375
}
350-
return ret;
351-
}
352-
353-
// for video, drop others with same pts/dts.
354-
break;
355-
}
356-
357-
return ret;
358-
}
359-
360-
int SrsMpegtsOverUdp::write_h264_raw_frame(char* frame, int frame_size, u_int32_t dts, u_int32_t pts)
361-
{
362-
int ret = ERROR_SUCCESS;
363-
364-
// for sps
365-
if (avc->is_sps(frame, frame_size)) {
366-
std::string sps;
367-
if ((ret = avc->sps_demux(frame, frame_size, sps)) != ERROR_SUCCESS) {
368-
return ret;
369-
}
376+
h264_sps_changed = true;
377+
h264_sps = sps;
370378

371-
if (h264_sps == sps) {
372-
return ret;
379+
if ((ret = write_h264_sps_pps(dts, pts)) != ERROR_SUCCESS) {
380+
return ret;
381+
}
382+
continue;
373383
}
374-
h264_sps_changed = true;
375-
h264_sps = sps;
376-
377-
return write_h264_sps_pps(dts, pts);
378-
}
379384

380-
// for pps
381-
if (avc->is_pps(frame, frame_size)) {
382-
std::string pps;
383-
if ((ret = avc->pps_demux(frame, frame_size, pps)) != ERROR_SUCCESS) {
384-
return ret;
385-
}
385+
// for pps
386+
if (avc->is_pps(frame, frame_size)) {
387+
std::string pps;
388+
if ((ret = avc->pps_demux(frame, frame_size, pps)) != ERROR_SUCCESS) {
389+
return ret;
390+
}
386391

387-
if (h264_pps == pps) {
388-
return ret;
389-
}
390-
h264_pps_changed = true;
391-
h264_pps = pps;
392+
if (h264_pps == pps) {
393+
continue;
394+
}
395+
h264_pps_changed = true;
396+
h264_pps = pps;
392397

393-
return write_h264_sps_pps(dts, pts);
398+
if ((ret = write_h264_sps_pps(dts, pts)) != ERROR_SUCCESS) {
399+
return ret;
400+
}
401+
continue;
402+
}
403+
404+
break;
394405
}
395406

396407
// ibp frame.
397-
return write_h264_ipb_frame(frame, frame_size, dts, pts);
408+
srs_info("mpegts: demux avc ibp frame size=%d, dts=%d", ibpframe_size, dts);
409+
return write_h264_ipb_frame(ibpframe, ibpframe_size, dts, pts);
398410
}
399411

400412
int SrsMpegtsOverUdp::write_h264_sps_pps(u_int32_t dts, u_int32_t pts)
@@ -421,14 +433,18 @@ int SrsMpegtsOverUdp::write_h264_sps_pps(u_int32_t dts, u_int32_t pts)
421433
return ret;
422434
}
423435

436+
// the timestamp in rtmp message header is dts.
437+
u_int32_t timestamp = dts;
438+
if ((ret = rtmp_write_packet(SrsCodecFlvTagVideo, timestamp, flv, nb_flv)) != ERROR_SUCCESS) {
439+
return ret;
440+
}
441+
424442
// reset sps and pps.
425443
h264_sps_changed = false;
426444
h264_pps_changed = false;
427445
h264_sps_pps_sent = true;
428-
429-
// the timestamp in rtmp message header is dts.
430-
u_int32_t timestamp = dts;
431-
return rtmp_write_packet(SrsCodecFlvTagVideo, timestamp, flv, nb_flv);
446+
447+
return ret;
432448
}
433449

434450
int SrsMpegtsOverUdp::write_h264_ipb_frame(char* frame, int frame_size, u_int32_t dts, u_int32_t pts)
@@ -459,6 +475,72 @@ int SrsMpegtsOverUdp::write_h264_ipb_frame(char* frame, int frame_size, u_int32_
459475
return rtmp_write_packet(SrsCodecFlvTagVideo, timestamp, flv, nb_flv);
460476
}
461477

478+
int SrsMpegtsOverUdp::on_ts_audio(SrsTsMessage* msg, SrsStream* avs)
479+
{
480+
int ret = ERROR_SUCCESS;
481+
482+
// ensure rtmp connected.
483+
if ((ret = connect()) != ERROR_SUCCESS) {
484+
return ret;
485+
}
486+
487+
// ts tbn to flv tbn.
488+
u_int32_t dts = msg->dts / 90;
489+
490+
// send each frame.
491+
while (!avs->empty()) {
492+
char* frame = NULL;
493+
int frame_size = 0;
494+
SrsRawAacStreamCodec codec;
495+
if ((ret = aac->adts_demux(avs, &frame, &frame_size, codec)) != ERROR_SUCCESS) {
496+
return ret;
497+
}
498+
499+
// ignore invalid frame,
500+
// * atleast 1bytes for aac to decode the data.
501+
if (frame_size <= 0) {
502+
continue;
503+
}
504+
srs_info("mpegts: demux aac frame size=%d, dts=%d", frame_size, dts);
505+
506+
// generate sh.
507+
if (aac_specific_config.empty()) {
508+
std::string sh;
509+
if ((ret = aac->mux_sequence_header(&codec, sh)) != ERROR_SUCCESS) {
510+
return ret;
511+
}
512+
aac_specific_config = sh;
513+
514+
codec.aac_packet_type = 0;
515+
516+
if ((ret = write_audio_raw_frame((char*)sh.data(), (int)sh.length(), &codec, dts)) != ERROR_SUCCESS) {
517+
return ret;
518+
}
519+
}
520+
521+
// audio raw data.
522+
codec.aac_packet_type = 1;
523+
if ((ret = write_audio_raw_frame(frame, frame_size, &codec, dts)) != ERROR_SUCCESS) {
524+
return ret;
525+
}
526+
}
527+
528+
return ret;
529+
}
530+
531+
int SrsMpegtsOverUdp::write_audio_raw_frame(char* frame, int frame_size, SrsRawAacStreamCodec* codec, u_int32_t dts)
532+
{
533+
int ret = ERROR_SUCCESS;
534+
535+
char* data = NULL;
536+
int size = 0;
537+
if ((ret = aac->mux_aac2flv(frame, frame_size, codec, dts, &data, &size)) != ERROR_SUCCESS) {
538+
return ret;
539+
}
540+
541+
return rtmp_write_packet(SrsCodecFlvTagAudio, dts, data, size);
542+
}
543+
462544
int SrsMpegtsOverUdp::rtmp_write_packet(char type, u_int32_t timestamp, char* data, int size)
463545
{
464546
int ret = ERROR_SUCCESS;
@@ -482,6 +564,10 @@ int SrsMpegtsOverUdp::rtmp_write_packet(char type, u_int32_t timestamp, char* da
482564
if ((msg = queue->dequeue()) == NULL) {
483565
break;
484566
}
567+
568+
// TODO: FIXME: use pithy print.
569+
srs_info("mpegts: send msg %s dts=%"PRId64", size=%d",
570+
msg->is_audio()? "A":msg->is_video()? "V":"N", msg->timestamp, msg->size);
485571

486572
// send out encoded msg.
487573
if ((ret = client->send_and_free_message(msg, stream_id)) != ERROR_SUCCESS) {

trunk/src/app/srs_app_mpegts_udp.hpp

+9-1
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ class SrsStSocket;
4545
class SrsRequest;
4646
class SrsRawH264Stream;
4747
class SrsSharedPtrMessage;
48+
class SrsRawAacStream;
49+
class SrsRawAacStreamCodec;
4850

4951
#include <srs_app_st.hpp>
5052
#include <srs_kernel_ts.hpp>
@@ -114,6 +116,10 @@ class SrsMpegtsOverUdp : virtual public ISrsTsHandler
114116
std::string h264_pps;
115117
bool h264_pps_changed;
116118
bool h264_sps_pps_sent;
119+
private:
120+
SrsRawAacStream* aac;
121+
std::string aac_specific_config;
122+
private:
117123
SrsMpegtsQueue* queue;
118124
public:
119125
SrsMpegtsOverUdp(SrsConfDirective* c);
@@ -126,9 +132,11 @@ class SrsMpegtsOverUdp : virtual public ISrsTsHandler
126132
virtual int on_ts_message(SrsTsMessage* msg);
127133
private:
128134
virtual int on_ts_video(SrsTsMessage* msg, SrsStream* avs);
129-
virtual int write_h264_raw_frame(char* frame, int frame_size, u_int32_t dts, u_int32_t pts);
130135
virtual int write_h264_sps_pps(u_int32_t dts, u_int32_t pts);
131136
virtual int write_h264_ipb_frame(char* frame, int frame_size, u_int32_t dts, u_int32_t pts);
137+
virtual int on_ts_audio(SrsTsMessage* msg, SrsStream* avs);
138+
virtual int write_audio_raw_frame(char* frame, int frame_size, SrsRawAacStreamCodec* codec, u_int32_t dts);
139+
private:
132140
virtual int rtmp_write_packet(char type, u_int32_t timestamp, char* data, int size);
133141
private:
134142
// connect to rtmp output url.

trunk/src/core/srs_core.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
3131
// current release version
3232
#define VERSION_MAJOR 2
3333
#define VERSION_MINOR 0
34-
#define VERSION_REVISION 110
34+
#define VERSION_REVISION 111
3535

3636
// server info.
3737
#define RTMP_SIG_SRS_KEY "SRS"

0 commit comments

Comments
 (0)