winlin

support write ts file

@@ -50,6 +50,7 @@ url: rtmp://127.0.0.1:1935/live/livestream @@ -50,6 +50,7 @@ url: rtmp://127.0.0.1:1935/live/livestream
50 * nginx v1.5.0: 139524 lines <br/> 50 * nginx v1.5.0: 139524 lines <br/>
51 51
52 ### History 52 ### History
  53 +* v0.5, 2013-11-24, support write ts file.
53 * v0.5, 2013-11-21, add ts_info tool to demux ts file. 54 * v0.5, 2013-11-21, add ts_info tool to demux ts file.
54 * v0.5, 2013-11-16, add rtmp players(OSMF/jwplayer5/jwplayer6). 55 * v0.5, 2013-11-16, add rtmp players(OSMF/jwplayer5/jwplayer6).
55 * v0.4, 2013-11-10, v0.4 released. 12500 lines. 56 * v0.4, 2013-11-10, v0.4 released. 12500 lines.
@@ -24,12 +24,35 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -24,12 +24,35 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 #include <srs_core_codec.hpp> 24 #include <srs_core_codec.hpp>
25 25
26 #include <string.h> 26 #include <string.h>
  27 +#include <stdlib.h>
27 28
28 #include <srs_core_error.hpp> 29 #include <srs_core_error.hpp>
29 #include <srs_core_stream.hpp> 30 #include <srs_core_stream.hpp>
30 #include <srs_core_log.hpp> 31 #include <srs_core_log.hpp>
31 #include <srs_core_autofree.hpp> 32 #include <srs_core_autofree.hpp>
32 33
  34 +SrsCodecBuffer::SrsCodecBuffer()
  35 +{
  36 + size = 0;
  37 + bytes = NULL;
  38 +}
  39 +
  40 +void SrsCodecBuffer::append(void* data, int len)
  41 +{
  42 + srs_assert(data);
  43 + srs_assert(len > 0);
  44 +
  45 + bytes = (char*)realloc(bytes, size + len);
  46 + memcpy(bytes + size, data, len);
  47 + size += len;
  48 +}
  49 +
  50 +void SrsCodecBuffer::free()
  51 +{
  52 + size = 0;
  53 + srs_freepa(bytes);
  54 +}
  55 +
33 SrsCodecSample::SrsCodecSample() 56 SrsCodecSample::SrsCodecSample()
34 { 57 {
35 clear(); 58 clear();
@@ -83,8 +106,11 @@ SrsCodec::SrsCodec() @@ -83,8 +106,11 @@ SrsCodec::SrsCodec()
83 video_codec_id = 0; 106 video_codec_id = 0;
84 audio_data_rate = 0; 107 audio_data_rate = 0;
85 audio_codec_id = 0; 108 audio_codec_id = 0;
86 - profile = 0;  
87 - level = 0; 109 + avc_profile = 0;
  110 + avc_level = 0;
  111 + aac_profile = 0;
  112 + aac_sample_rate = 0;
  113 + aac_channels = 0;
88 avc_extra_size = 0; 114 avc_extra_size = 0;
89 avc_extra_data = NULL; 115 avc_extra_data = NULL;
90 aac_extra_size = 0; 116 aac_extra_size = 0;
@@ -160,6 +186,39 @@ int SrsCodec::audio_aac_demux(int8_t* data, int size, SrsCodecSample* sample) @@ -160,6 +186,39 @@ int SrsCodec::audio_aac_demux(int8_t* data, int size, SrsCodecSample* sample)
160 aac_extra_data = new char[aac_extra_size]; 186 aac_extra_data = new char[aac_extra_size];
161 memcpy(aac_extra_data, stream->current(), aac_extra_size); 187 memcpy(aac_extra_data, stream->current(), aac_extra_size);
162 } 188 }
  189 +
  190 + // only need to decode the first 2bytes:
  191 + // audioObjectType, aac_profile, 5bits.
  192 + // samplingFrequencyIndex, aac_sample_rate, 4bits.
  193 + // channelConfiguration, aac_channels, 4bits
  194 + if (!stream->require(2)) {
  195 + ret = ERROR_HLS_DECODE_ERROR;
  196 + srs_error("hls decode audio aac sequence header failed. ret=%d", ret);
  197 + return ret;
  198 + }
  199 + aac_profile = stream->read_1bytes();
  200 + aac_sample_rate = stream->read_1bytes();
  201 +
  202 + aac_channels = (aac_sample_rate >> 3) & 0x0f;
  203 + aac_sample_rate = ((aac_profile << 1) & 0x0e) | ((aac_sample_rate >> 7) & 0x01);
  204 + aac_profile = (aac_profile >> 3) & 0x1f;
  205 +
  206 + if (aac_profile == 0 || aac_profile == 0x1f) {
  207 + ret = ERROR_HLS_DECODE_ERROR;
  208 + srs_error("hls decode audio aac sequence header failed, "
  209 + "adts object=%d invalid. ret=%d", aac_profile, ret);
  210 + return ret;
  211 + }
  212 +
  213 + // aac_profile = audioObjectType - 1
  214 + aac_profile--;
  215 +
  216 + if (aac_profile > 3) {
  217 + // Mark all extended profiles as LC
  218 + // to make Android as happy as possible.
  219 + // @see: ngx_rtmp_hls_parse_aac_header
  220 + aac_profile = 1;
  221 + }
163 } else if (aac_packet_type == SrsCodecAudioTypeRawData) { 222 } else if (aac_packet_type == SrsCodecAudioTypeRawData) {
164 // ensure the sequence header demuxed 223 // ensure the sequence header demuxed
165 if (aac_extra_size <= 0 || !aac_extra_data) { 224 if (aac_extra_size <= 0 || !aac_extra_data) {
@@ -181,8 +181,21 @@ enum SrsCodecAudioSoundType @@ -181,8 +181,21 @@ enum SrsCodecAudioSoundType
181 */ 181 */
182 struct SrsCodecBuffer 182 struct SrsCodecBuffer
183 { 183 {
  184 + /**
  185 + * @remark user must manage the bytes.
  186 + */
184 int size; 187 int size;
185 char* bytes; 188 char* bytes;
  189 +
  190 + SrsCodecBuffer();
  191 + void append(void* data, int len);
  192 +
  193 + /**
  194 + * free the bytes,
  195 + * user can invoke it to free the bytes,
  196 + * the SrsCodecBuffer never free automatically.
  197 + */
  198 + void free();
186 }; 199 };
187 200
188 /** 201 /**
@@ -227,9 +240,9 @@ public: @@ -227,9 +240,9 @@ public:
227 // @see: SrsCodecVideo 240 // @see: SrsCodecVideo
228 int video_codec_id; 241 int video_codec_id;
229 // profile_idc, H.264-AVC-ISO_IEC_14496-10.pdf, page 45. 242 // profile_idc, H.264-AVC-ISO_IEC_14496-10.pdf, page 45.
230 - u_int8_t profile; 243 + u_int8_t avc_profile;
231 // level_idc, H.264-AVC-ISO_IEC_14496-10.pdf, page 45. 244 // level_idc, H.264-AVC-ISO_IEC_14496-10.pdf, page 45.
232 - u_int8_t level; 245 + u_int8_t avc_level;
233 int width; 246 int width;
234 int height; 247 int height;
235 int video_data_rate; // in bps 248 int video_data_rate; // in bps
@@ -243,6 +256,13 @@ public: @@ -243,6 +256,13 @@ public:
243 // @see: SrsCodecAudioType 256 // @see: SrsCodecAudioType
244 int audio_codec_id; 257 int audio_codec_id;
245 int audio_data_rate; // in bps 258 int audio_data_rate; // in bps
  259 + // 1.6.2.1 AudioSpecificConfig, in aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 33.
  260 + // audioObjectType, value defines in 7.1 Profiles, aac-iso-13818-7.pdf, page 40.
  261 + u_int8_t aac_profile;
  262 + // samplingFrequencyIndex
  263 + u_int8_t aac_sample_rate;
  264 + // channelConfiguration
  265 + u_int8_t aac_channels;
246 // the avc extra data, the AVC sequence header, 266 // the avc extra data, the AVC sequence header,
247 // without the flv codec header, 267 // without the flv codec header,
248 // @see: ffmpeg, AVCodecContext::extradata 268 // @see: ffmpeg, AVCodecContext::extradata
@@ -112,5 +112,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -112,5 +112,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
112 #define ERROR_HLS_BUSY 602 112 #define ERROR_HLS_BUSY 602
113 #define ERROR_HLS_OPEN_FAILED 603 113 #define ERROR_HLS_OPEN_FAILED 603
114 #define ERROR_HLS_WRITE_FAILED 604 114 #define ERROR_HLS_WRITE_FAILED 604
  115 +#define ERROR_HLS_AAC_FRAME_LENGTH 605
  116 +#define ERROR_HLS_AVC_SAMPLE_SIZE 606
115 117
116 #endif 118 #endif
@@ -26,6 +26,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -26,6 +26,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 #include <sys/types.h> 26 #include <sys/types.h>
27 #include <sys/stat.h> 27 #include <sys/stat.h>
28 #include <fcntl.h> 28 #include <fcntl.h>
  29 +#include <stdlib.h>
  30 +#include <string.h>
29 31
30 #include <srs_core_error.hpp> 32 #include <srs_core_error.hpp>
31 #include <srs_core_codec.hpp> 33 #include <srs_core_codec.hpp>
@@ -275,18 +277,249 @@ u_int8_t mpegts_header[] = { @@ -275,18 +277,249 @@ u_int8_t mpegts_header[] = {
275 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff 277 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
276 }; 278 };
277 279
  280 +// @see: NGX_RTMP_HLS_DELAY, 700ms, ts_tbn=90000
  281 +#define SRS_HLS_DELAY 63000
  282 +
  283 +// @see: ngx_rtmp_mpegts.c
  284 +// TODO: support full mpegts feature in future.
  285 +class SrsMpegtsWriter
  286 +{
  287 +public:
  288 + static int write_header(int fd)
  289 + {
  290 + int ret = ERROR_SUCCESS;
  291 +
  292 + if (::write(fd, mpegts_header, sizeof(mpegts_header)) != sizeof(mpegts_header)) {
  293 + ret = ERROR_HLS_WRITE_FAILED;
  294 + srs_error("write ts file header failed. ret=%d", ret);
  295 + return ret;
  296 + }
  297 +
  298 + return ret;
  299 + }
  300 + static int write_frame(int fd, mpegts_frame* frame, SrsCodecBuffer* buffer)
  301 + {
  302 + int ret = ERROR_SUCCESS;
  303 +
  304 + char* last = buffer->bytes + buffer->size;
  305 + char* pos = buffer->bytes;
  306 +
  307 + bool first = true;
  308 + while (pos < last) {
  309 + static char packet[188];
  310 + char* p = packet;
  311 +
  312 + frame->cc++;
  313 +
  314 + // sync_byte; //8bits
  315 + *p++ = 0x47;
  316 + // pid; //13bits
  317 + *p++ = (frame->pid >> 8) & 0x1f;
  318 + // payload_unit_start_indicator; //1bit
  319 + if (first) {
  320 + p[-1] |= 0x40;
  321 + }
  322 + *p++ = frame->pid;
  323 +
  324 + // transport_scrambling_control; //2bits
  325 + // adaption_field_control; //2bits, 0x01: PayloadOnly
  326 + // continuity_counter; //4bits
  327 + *p++ = 0x10 | (frame->cc & 0x0f);
  328 +
  329 + if (first) {
  330 + first = false;
  331 + if (frame->key) {
  332 + p[-1] |= 0x20; // Both Adaption and Payload
  333 + *p++ = 7; // size
  334 + *p++ = 0x50; // random access + PCR
  335 + p = write_pcr(p, frame->dts - SRS_HLS_DELAY);
  336 + }
  337 +
  338 + // PES header
  339 + // packet_start_code_prefix; //24bits, '00 00 01'
  340 + *p++ = 0x00;
  341 + *p++ = 0x00;
  342 + *p++ = 0x01;
  343 + //8bits
  344 + *p++ = frame->sid;
  345 +
  346 + // pts(33bits) need 5bytes.
  347 + u_int8_t header_size = 5;
  348 + u_int8_t flags = 0x80; // pts
  349 +
  350 + // dts(33bits) need 5bytes also
  351 + if (frame->dts != frame->pts) {
  352 + header_size += 5;
  353 + flags |= 0x40; // dts
  354 + }
  355 +
  356 + // 3bytes: flag fields from PES_packet_length to PES_header_data_length
  357 + int pes_size = (last - pos) + header_size + 3;
  358 + if (pes_size > 0xffff) {
  359 + /**
  360 + * when actual packet length > 0xffff(65535),
  361 + * which exceed the max u_int16_t packet length,
  362 + * use 0 packet length, the next unit start indicates the end of packet.
  363 + */
  364 + pes_size = 0;
  365 + }
  366 +
  367 + // PES_packet_length; //16bits
  368 + *p++ = (pes_size >> 8);
  369 + *p++ = pes_size;
  370 +
  371 + // PES_scrambling_control; //2bits, '10'
  372 + // PES_priority; //1bit
  373 + // data_alignment_indicator; //1bit
  374 + // copyright; //1bit
  375 + // original_or_copy; //1bit
  376 + *p++ = 0x80; /* H222 */
  377 +
  378 + // PTS_DTS_flags; //2bits
  379 + // ESCR_flag; //1bit
  380 + // ES_rate_flag; //1bit
  381 + // DSM_trick_mode_flag; //1bit
  382 + // additional_copy_info_flag; //1bit
  383 + // PES_CRC_flag; //1bit
  384 + // PES_extension_flag; //1bit
  385 + *p++ = flags;
  386 +
  387 + // PES_header_data_length; //8bits
  388 + *p++ = header_size;
  389 +
  390 + // pts; // 33bits
  391 + p = write_pts(p, flags >> 6, frame->pts + SRS_HLS_DELAY);
  392 +
  393 + // dts; // 33bits
  394 + if (frame->dts != frame->pts) {
  395 + p = write_pts(p, 1, frame->dts + SRS_HLS_DELAY);
  396 + }
  397 + }
  398 +
  399 + int body_size = sizeof(packet) - (p - packet);
  400 + int in_size = last - pos;
  401 +
  402 + if (body_size <= in_size) {
  403 + memcpy(p, pos, body_size);
  404 + pos += body_size;
  405 + } else {
  406 + p = fill_stuff(p, packet, body_size, in_size);
  407 + memcpy(p, pos, in_size);
  408 + pos = last;
  409 + }
  410 +
  411 + // write ts packet
  412 + if (::write(fd, packet, sizeof(packet)) != sizeof(packet)) {
  413 + ret = ERROR_HLS_WRITE_FAILED;
  414 + srs_error("write ts file failed. ret=%d", ret);
  415 + return ret;
  416 + }
  417 + }
  418 +
  419 + // write success, clear and free the buffer
  420 + buffer->free();
  421 +
  422 + return ret;
  423 + }
  424 +private:
  425 + static char* fill_stuff(char* pes_body_end, char* packet, int body_size, int in_size)
  426 + {
  427 + char* p = pes_body_end;
  428 +
  429 + // insert the stuff bytes before PES body
  430 + int stuff_size = (body_size - in_size);
  431 +
  432 + // adaption_field_control; //2bits
  433 + if (packet[3] & 0x20) {
  434 + // has adaptation
  435 + // packet[4]: adaption_field_length
  436 + // packet[5]: adaption field data
  437 + // base: start of PES body
  438 + char* base = &packet[5] + packet[4];
  439 + int len = p - base;
  440 + p = (char*)memmove(base + stuff_size, base, len) + len;
  441 + // increase the adaption field size.
  442 + packet[4] += stuff_size;
  443 +
  444 + return p;
  445 + }
  446 +
  447 + // create adaption field.
  448 + // adaption_field_control; //2bits
  449 + packet[3] |= 0x20;
  450 + // base: start of PES body
  451 + char* base = &packet[4];
  452 + int len = p - base;
  453 + p = (char*)memmove(base + stuff_size, base, len) + len;
  454 + // adaption_field_length; //8bits
  455 + packet[4] = (stuff_size - 1);
  456 + if (stuff_size >= 2) {
  457 + // adaption field flags.
  458 + packet[5] = 0;
  459 + // adaption data.
  460 + if (stuff_size > 2) {
  461 + memset(&packet[6], 0xff, stuff_size - 2);
  462 + }
  463 + }
  464 +
  465 + return p;
  466 + }
  467 + static char* write_pcr(char* p, int64_t pcr)
  468 + {
  469 + *p++ = (char) (pcr >> 25);
  470 + *p++ = (char) (pcr >> 17);
  471 + *p++ = (char) (pcr >> 9);
  472 + *p++ = (char) (pcr >> 1);
  473 + *p++ = (char) (pcr << 7 | 0x7e);
  474 + *p++ = 0;
  475 +
  476 + return p;
  477 + }
  478 + static char* write_pts(char* p, u_int8_t fb, int64_t pts)
  479 + {
  480 + int32_t val;
  481 +
  482 + val = fb << 4 | (((pts >> 30) & 0x07) << 1) | 1;
  483 + *p++ = val;
  484 +
  485 + val = (((pts >> 15) & 0x7fff) << 1) | 1;
  486 + *p++ = (val >> 8);
  487 + *p++ = val;
  488 +
  489 + val = (((pts) & 0x7fff) << 1) | 1;
  490 + *p++ = (val >> 8);
  491 + *p++ = val;
  492 +
  493 + return p;
  494 + }
  495 +};
  496 +
278 // the mpegts header specifed the video/audio pid. 497 // the mpegts header specifed the video/audio pid.
279 #define TS_VIDEO_PID 256 498 #define TS_VIDEO_PID 256
280 #define TS_AUDIO_PID 257 499 #define TS_AUDIO_PID 257
281 500
  501 +// ts aac stream id.
  502 +#define TS_AUDIO_AAC 0xc0
  503 +// ts avc stream id.
  504 +#define TS_VIDEO_AVC 0xe0
  505 +
282 SrsTSMuxer::SrsTSMuxer() 506 SrsTSMuxer::SrsTSMuxer()
283 { 507 {
284 fd = -1; 508 fd = -1;
  509 +
  510 + audio_buffer = new SrsCodecBuffer();
  511 + video_buffer = new SrsCodecBuffer();
285 } 512 }
286 513
287 SrsTSMuxer::~SrsTSMuxer() 514 SrsTSMuxer::~SrsTSMuxer()
288 { 515 {
289 close(); 516 close();
  517 +
  518 + audio_buffer->free();
  519 + video_buffer->free();
  520 +
  521 + srs_freep(audio_buffer);
  522 + srs_freep(video_buffer);
290 } 523 }
291 524
292 int SrsTSMuxer::open(std::string _path) 525 int SrsTSMuxer::open(std::string _path)
@@ -306,9 +539,7 @@ int SrsTSMuxer::open(std::string _path) @@ -306,9 +539,7 @@ int SrsTSMuxer::open(std::string _path)
306 } 539 }
307 540
308 // write mpegts header 541 // write mpegts header
309 - if (::write(fd, mpegts_header, sizeof(mpegts_header)) != sizeof(mpegts_header)) {  
310 - ret = ERROR_HLS_WRITE_FAILED;  
311 - srs_error("write ts file header %s failed. ret=%d", path.c_str(), ret); 542 + if ((ret = SrsMpegtsWriter::write_header(fd)) != ERROR_SUCCESS) {
312 return ret; 543 return ret;
313 } 544 }
314 545
@@ -319,7 +550,64 @@ int SrsTSMuxer::write_audio(u_int32_t time, SrsCodec* codec, SrsCodecSample* sam @@ -319,7 +550,64 @@ int SrsTSMuxer::write_audio(u_int32_t time, SrsCodec* codec, SrsCodecSample* sam
319 { 550 {
320 int ret = ERROR_SUCCESS; 551 int ret = ERROR_SUCCESS;
321 552
322 - static u_int8_t packet[188]; 553 + for (int i = 0; i < sample->nb_buffers; i++) {
  554 + SrsCodecBuffer* buf = &sample->buffers[i];
  555 + int32_t size = buf->size;
  556 +
  557 + if (!buf->bytes || size <= 0 || size > 0x1fff) {
  558 + ret = ERROR_HLS_AAC_FRAME_LENGTH;
  559 + srs_error("invalid aac frame length=%d, ret=%d", size, ret);
  560 + return ret;
  561 + }
  562 +
  563 + // AAC-ADTS
  564 + // 6.2 Audio Data Transport Stream, ADTS
  565 + // in aac-iso-13818-7.pdf, page 26.
  566 + // fixed 7bytes header
  567 + static u_int8_t adts_header[7] = {0xff, 0xf1, 0x00, 0x00, 0x00, 0x0f, 0xfc};
  568 + /*
  569 + // adts_fixed_header
  570 + // 2B, 16bits
  571 + int16_t syncword; //12bits, '1111 1111 1111'
  572 + int8_t ID; //1bit, '0'
  573 + int8_t layer; //2bits, '00'
  574 + int8_t protection_absent; //1bit, can be '1'
  575 + // 12bits
  576 + int8_t profile; //2bit, 7.1 Profiles, page 40
  577 + TSAacSampleFrequency sampling_frequency_index; //4bits, Table 35, page 46
  578 + int8_t private_bit; //1bit, can be '0'
  579 + int8_t channel_configuration; //3bits, Table 8
  580 + int8_t original_or_copy; //1bit, can be '0'
  581 + int8_t home; //1bit, can be '0'
  582 +
  583 + // adts_variable_header
  584 + // 28bits
  585 + int8_t copyright_identification_bit; //1bit, can be '0'
  586 + int8_t copyright_identification_start; //1bit, can be '0'
  587 + int16_t frame_length; //13bits
  588 + int16_t adts_buffer_fullness; //11bits, 7FF signals that the bitstream is a variable rate bitstream.
  589 + int8_t number_of_raw_data_blocks_in_frame; //2bits, 0 indicating 1 raw_data_block()
  590 + */
  591 + // profile, 2bits
  592 + adts_header[2] = (codec->aac_profile << 6) & 0xc0;
  593 + // sampling_frequency_index 4bits
  594 + adts_header[2] |= (codec->aac_sample_rate << 2) & 0x3c;
  595 + // channel_configuration 3bits
  596 + adts_header[2] |= (codec->aac_channels >> 1) & 0x01;
  597 + adts_header[3] = (codec->aac_channels << 5) & 0xc0;
  598 + // frame_length 13bits
  599 + adts_header[3] |= (size >> 11) & 0x03;
  600 + adts_header[4] = (size >> 3) & 0xff;
  601 + adts_header[5] = (size << 5) & 0xcf;
  602 +
  603 + // copy to audio buffer
  604 + audio_buffer->append(adts_header, sizeof(adts_header));
  605 + audio_buffer->append(buf->bytes, buf->size);
  606 + }
  607 +
  608 + audio_frame.dts = audio_frame.pts = time * 90;
  609 + audio_frame.pid = TS_AUDIO_PID;
  610 + audio_frame.sid = TS_AUDIO_AAC;
323 611
324 return ret; 612 return ret;
325 } 613 }
@@ -328,7 +616,45 @@ int SrsTSMuxer::write_video(u_int32_t time, SrsCodec* codec, SrsCodecSample* sam @@ -328,7 +616,45 @@ int SrsTSMuxer::write_video(u_int32_t time, SrsCodec* codec, SrsCodecSample* sam
328 { 616 {
329 int ret = ERROR_SUCCESS; 617 int ret = ERROR_SUCCESS;
330 618
331 - static u_int8_t packet[188]; 619 + static u_int8_t aud_nal[] = { 0x00, 0x00, 0x00, 0x01, 0x09, 0xf0 };
  620 + video_buffer->append(aud_nal, sizeof(aud_nal));
  621 +
  622 + for (int i = 0; i < sample->nb_buffers; i++) {
  623 + SrsCodecBuffer* buf = &sample->buffers[i];
  624 + int32_t size = buf->size;
  625 +
  626 + if (!buf->bytes || size <= 0) {
  627 + ret = ERROR_HLS_AVC_SAMPLE_SIZE;
  628 + srs_error("invalid avc sample length=%d, ret=%d", size, ret);
  629 + return ret;
  630 + }
  631 +
  632 + // sample start prefix, '00 00 00 01' or '00 00 01'
  633 + u_int8_t* p = aud_nal + 1;
  634 + u_int8_t* end = p + 3;
  635 +
  636 + // first AnnexB prefix is long (4 bytes)
  637 + if (i == 0) {
  638 + p = aud_nal;
  639 + }
  640 + video_buffer->append(p, end - p);
  641 +
  642 + // sample data
  643 + video_buffer->append(buf->bytes, buf->size);
  644 + }
  645 +
  646 + video_frame.dts = time * 90;
  647 + video_frame.pts = video_frame.dts + sample->cts * 90;
  648 + video_frame.pid = TS_VIDEO_PID;
  649 + video_frame.sid = TS_VIDEO_AVC;
  650 + video_frame.key = sample->frame_type == SrsCodecVideoAVCFrameKeyFrame;
  651 +
  652 + if ((ret = SrsMpegtsWriter::write_frame(fd, &video_frame, video_buffer)) != ERROR_SUCCESS) {
  653 + return ret;
  654 + }
  655 + if ((ret = SrsMpegtsWriter::write_frame(fd, &audio_frame, audio_buffer)) != ERROR_SUCCESS) {
  656 + return ret;
  657 + }
332 658
333 return ret; 659 return ret;
334 } 660 }
@@ -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 class SrsOnMetaDataPacket; 34 class SrsOnMetaDataPacket;
35 class SrsCommonMessage; 35 class SrsCommonMessage;
36 class SrsCodecSample; 36 class SrsCodecSample;
  37 +class SrsCodecBuffer;
37 class SrsTSMuxer; 38 class SrsTSMuxer;
38 class SrsCodec; 39 class SrsCodec;
39 40
@@ -56,11 +57,34 @@ public: @@ -56,11 +57,34 @@ public:
56 virtual int on_video(SrsCommonMessage* video); 57 virtual int on_video(SrsCommonMessage* video);
57 }; 58 };
58 59
  60 +// @see: ngx_rtmp_mpegts_frame_t
  61 +struct mpegts_frame
  62 +{
  63 + int64_t pts;
  64 + int64_t dts;
  65 + int pid;
  66 + int sid;
  67 + int cc;
  68 + bool key;
  69 +
  70 + mpegts_frame()
  71 + {
  72 + pts = dts = 0;
  73 + pid = sid = cc = 0;
  74 + key = false;
  75 + }
  76 +};
  77 +
59 class SrsTSMuxer 78 class SrsTSMuxer
60 { 79 {
61 private: 80 private:
62 int fd; 81 int fd;
63 std::string path; 82 std::string path;
  83 +private:
  84 + mpegts_frame audio_frame;
  85 + SrsCodecBuffer* audio_buffer;
  86 + mpegts_frame video_frame;
  87 + SrsCodecBuffer* video_buffer;
64 public: 88 public:
65 SrsTSMuxer(); 89 SrsTSMuxer();
66 virtual ~SrsTSMuxer(); 90 virtual ~SrsTSMuxer();