winlin

for #293, #250, move the ts codec to kernel ts.

@@ -50,6 +50,7 @@ using namespace std; @@ -50,6 +50,7 @@ using namespace std;
50 #include <srs_kernel_avc.hpp> 50 #include <srs_kernel_avc.hpp>
51 #include <srs_kernel_file.hpp> 51 #include <srs_kernel_file.hpp>
52 #include <srs_rtmp_buffer.hpp> 52 #include <srs_rtmp_buffer.hpp>
  53 +#include <srs_kernel_ts.hpp>
53 54
54 // drop the segment when duration of ts too small. 55 // drop the segment when duration of ts too small.
55 #define SRS_AUTO_HLS_SEGMENT_MIN_DURATION_MS 100 56 #define SRS_AUTO_HLS_SEGMENT_MIN_DURATION_MS 100
@@ -33,6 +33,9 @@ using namespace std; @@ -33,6 +33,9 @@ using namespace std;
33 #include <srs_kernel_log.hpp> 33 #include <srs_kernel_log.hpp>
34 #include <srs_app_config.hpp> 34 #include <srs_app_config.hpp>
35 35
  36 +// Transport Stream packets are 188 bytes in length.
  37 +#define TS_PACKET_SIZE 188
  38 +
36 #ifdef SRS_AUTO_STREAM_CASTER 39 #ifdef SRS_AUTO_STREAM_CASTER
37 40
38 SrsMpegtsOverUdp::SrsMpegtsOverUdp(SrsConfDirective* c) 41 SrsMpegtsOverUdp::SrsMpegtsOverUdp(SrsConfDirective* c)
@@ -51,10 +54,28 @@ int SrsMpegtsOverUdp::on_udp_packet(sockaddr_in* from, char* buf, int nb_buf) @@ -51,10 +54,28 @@ int SrsMpegtsOverUdp::on_udp_packet(sockaddr_in* from, char* buf, int nb_buf)
51 std::string peer_ip = inet_ntoa(from->sin_addr); 54 std::string peer_ip = inet_ntoa(from->sin_addr);
52 int peer_port = ntohs(from->sin_port); 55 int peer_port = ntohs(from->sin_port);
53 56
  57 + // drop ts packet when size not modulus by 188
  58 + if (nb_buf < TS_PACKET_SIZE || (nb_buf % TS_PACKET_SIZE) != 0) {
  59 + srs_warn("udp: drop %s:%d packet %d bytes", peer_ip.c_str(), peer_port, nb_buf);
  60 + return ret;
  61 + }
54 srs_info("udp: got %s:%d packet %d bytes", peer_ip.c_str(), peer_port, nb_buf); 62 srs_info("udp: got %s:%d packet %d bytes", peer_ip.c_str(), peer_port, nb_buf);
55 63
56 - // TODO: FIXME: implements it. 64 + // process each ts packet
  65 + for (int i = 0; i < nb_buf; i += TS_PACKET_SIZE) {
  66 + char* ts_packet = buf + i;
  67 + if ((ret = on_ts_packet(ts_packet)) != ERROR_SUCCESS) {
  68 + srs_warn("mpegts: ignore ts packet error. ret=%d", ret);
  69 + continue;
  70 + }
  71 + }
  72 +
  73 + return ret;
  74 +}
57 75
  76 +int SrsMpegtsOverUdp::on_ts_packet(char* ts_packet)
  77 +{
  78 + int ret = ERROR_SUCCESS;
58 return ret; 79 return ret;
59 } 80 }
60 81
@@ -58,6 +58,11 @@ public: @@ -58,6 +58,11 @@ public:
58 * @remark user should never use the buf, for it's a shared memory bytes. 58 * @remark user should never use the buf, for it's a shared memory bytes.
59 */ 59 */
60 virtual int on_udp_packet(sockaddr_in* from, char* buf, int nb_buf); 60 virtual int on_udp_packet(sockaddr_in* from, char* buf, int nb_buf);
  61 +private:
  62 + /**
  63 + * when got a ts packet, in size TS_PACKET_SIZE.
  64 + */
  65 + virtual int on_ts_packet(char* ts_packet);
61 }; 66 };
62 67
63 #endif 68 #endif
@@ -32,702 +32,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -32,702 +32,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 32
33 using namespace std; 33 using namespace std;
34 34
35 -// in ms, for HLS aac sync time.  
36 -#define SRS_CONF_DEFAULT_AAC_SYNC 100  
37 -  
38 -// @see: ngx_rtmp_hls_audio  
39 -/* We assume here AAC frame size is 1024  
40 - * Need to handle AAC frames with frame size of 960 */  
41 -#define _SRS_AAC_SAMPLE_SIZE 1024  
42 -  
43 -// the mpegts header specifed the video/audio pid.  
44 -#define TS_VIDEO_PID 256  
45 -#define TS_AUDIO_PID 257  
46 -  
47 -// ts aac stream id.  
48 -#define TS_AUDIO_AAC 0xc0  
49 -// ts avc stream id.  
50 -#define TS_VIDEO_AVC 0xe0  
51 -  
52 -/**  
53 -* the public data, event HLS disable, others can use it.  
54 -*/  
55 -// 0 = 5.5 kHz = 5512 Hz  
56 -// 1 = 11 kHz = 11025 Hz  
57 -// 2 = 22 kHz = 22050 Hz  
58 -// 3 = 44 kHz = 44100 Hz  
59 -int flv_sample_rates[] = {5512, 11025, 22050, 44100};  
60 -  
61 -// the sample rates in the codec,  
62 -// in the sequence header.  
63 -int aac_sample_rates[] =  
64 -{  
65 - 96000, 88200, 64000, 48000,  
66 - 44100, 32000, 24000, 22050,  
67 - 16000, 12000, 11025, 8000,  
68 - 7350, 0, 0, 0  
69 -};  
70 -  
71 -// @see: NGX_RTMP_HLS_DELAY,  
72 -// 63000: 700ms, ts_tbn=90000  
73 -#define SRS_AUTO_HLS_DELAY 63000  
74 -  
75 -// @see: ngx_rtmp_mpegts_header  
76 -u_int8_t mpegts_header[] = {  
77 - /* TS */  
78 - 0x47, 0x40, 0x00, 0x10, 0x00,  
79 - /* PSI */  
80 - 0x00, 0xb0, 0x0d, 0x00, 0x01, 0xc1, 0x00, 0x00,  
81 - /* PAT */  
82 - 0x00, 0x01, 0xf0, 0x01,  
83 - /* CRC */  
84 - 0x2e, 0x70, 0x19, 0x05,  
85 - /* stuffing 167 bytes */  
86 - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  
87 - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  
88 - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  
89 - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  
90 - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  
91 - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  
92 - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  
93 - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  
94 - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  
95 - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  
96 - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  
97 - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  
98 - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  
99 - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  
100 - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  
101 - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  
102 - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  
103 -  
104 - /* TS */  
105 - 0x47, 0x50, 0x01, 0x10, 0x00,  
106 - /* PSI */  
107 - 0x02, 0xb0, 0x17, 0x00, 0x01, 0xc1, 0x00, 0x00,  
108 - /* PMT */  
109 - 0xe1, 0x00,  
110 - 0xf0, 0x00,  
111 - // must generate header with/without video, @see:  
112 - // https://github.com/winlinvip/simple-rtmp-server/issues/40  
113 - 0x1b, 0xe1, 0x00, 0xf0, 0x00, /* h264, pid=0x100=256 */  
114 - 0x0f, 0xe1, 0x01, 0xf0, 0x00, /* aac, pid=0x101=257 */  
115 - /*0x03, 0xe1, 0x01, 0xf0, 0x00,*/ /* mp3 */  
116 - /* CRC */  
117 - 0x2f, 0x44, 0xb9, 0x9b, /* crc for aac */  
118 - /*0x4e, 0x59, 0x3d, 0x1e,*/ /* crc for mp3 */  
119 - /* stuffing 157 bytes */  
120 - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  
121 - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  
122 - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  
123 - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  
124 - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  
125 - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  
126 - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  
127 - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  
128 - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  
129 - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  
130 - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  
131 - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  
132 - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  
133 - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  
134 - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  
135 - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff  
136 -};  
137 -  
138 -// @see: ngx_rtmp_mpegts.c  
139 -// TODO: support full mpegts feature in future.  
140 -class SrsMpegtsWriter  
141 -{  
142 -public:  
143 - static int write_header(SrsFileWriter* writer)  
144 - {  
145 - int ret = ERROR_SUCCESS;  
146 -  
147 - if ((ret = writer->write(mpegts_header, sizeof(mpegts_header), NULL)) != ERROR_SUCCESS) {  
148 - ret = ERROR_HLS_WRITE_FAILED;  
149 - srs_error("write ts file header failed. ret=%d", ret);  
150 - return ret;  
151 - }  
152 -  
153 - return ret;  
154 - }  
155 - static int write_frame(SrsFileWriter* writer, SrsMpegtsFrame* frame, SrsSimpleBuffer* buffer)  
156 - {  
157 - int ret = ERROR_SUCCESS;  
158 -  
159 - if (!buffer->bytes() || buffer->length() <= 0) {  
160 - return ret;  
161 - }  
162 -  
163 - char* last = buffer->bytes() + buffer->length();  
164 - char* pos = buffer->bytes();  
165 -  
166 - bool first = true;  
167 - while (pos < last) {  
168 - static char packet[188];  
169 - char* p = packet;  
170 -  
171 - frame->cc++;  
172 -  
173 - // sync_byte; //8bits  
174 - *p++ = 0x47;  
175 - // pid; //13bits  
176 - *p++ = (frame->pid >> 8) & 0x1f;  
177 - // payload_unit_start_indicator; //1bit  
178 - if (first) {  
179 - p[-1] |= 0x40;  
180 - }  
181 - *p++ = frame->pid;  
182 -  
183 - // transport_scrambling_control; //2bits  
184 - // adaption_field_control; //2bits, 0x01: PayloadOnly  
185 - // continuity_counter; //4bits  
186 - *p++ = 0x10 | (frame->cc & 0x0f);  
187 -  
188 - if (first) {  
189 - first = false;  
190 - if (frame->key) {  
191 - p[-1] |= 0x20; // Both Adaption and Payload  
192 - *p++ = 7; // size  
193 - *p++ = 0x50; // random access + PCR  
194 - p = write_pcr(p, frame->dts - SRS_AUTO_HLS_DELAY);  
195 - }  
196 -  
197 - // PES header  
198 - // packet_start_code_prefix; //24bits, '00 00 01'  
199 - *p++ = 0x00;  
200 - *p++ = 0x00;  
201 - *p++ = 0x01;  
202 - //8bits  
203 - *p++ = frame->sid;  
204 -  
205 - // pts(33bits) need 5bytes.  
206 - u_int8_t header_size = 5;  
207 - u_int8_t flags = 0x80; // pts  
208 -  
209 - // dts(33bits) need 5bytes also  
210 - if (frame->dts != frame->pts) {  
211 - header_size += 5;  
212 - flags |= 0x40; // dts  
213 - }  
214 -  
215 - // 3bytes: flag fields from PES_packet_length to PES_header_data_length  
216 - int pes_size = (last - pos) + header_size + 3;  
217 - if (pes_size > 0xffff) {  
218 - /**  
219 - * when actual packet length > 0xffff(65535),  
220 - * which exceed the max u_int16_t packet length,  
221 - * use 0 packet length, the next unit start indicates the end of packet.  
222 - */  
223 - pes_size = 0;  
224 - }  
225 -  
226 - // PES_packet_length; //16bits  
227 - *p++ = (pes_size >> 8);  
228 - *p++ = pes_size;  
229 -  
230 - // PES_scrambling_control; //2bits, '10'  
231 - // PES_priority; //1bit  
232 - // data_alignment_indicator; //1bit  
233 - // copyright; //1bit  
234 - // original_or_copy; //1bit  
235 - *p++ = 0x80; /* H222 */  
236 -  
237 - // PTS_DTS_flags; //2bits  
238 - // ESCR_flag; //1bit  
239 - // ES_rate_flag; //1bit  
240 - // DSM_trick_mode_flag; //1bit  
241 - // additional_copy_info_flag; //1bit  
242 - // PES_CRC_flag; //1bit  
243 - // PES_extension_flag; //1bit  
244 - *p++ = flags;  
245 -  
246 - // PES_header_data_length; //8bits  
247 - *p++ = header_size;  
248 -  
249 - // pts; // 33bits  
250 - p = write_pts(p, flags >> 6, frame->pts + SRS_AUTO_HLS_DELAY);  
251 -  
252 - // dts; // 33bits  
253 - if (frame->dts != frame->pts) {  
254 - p = write_pts(p, 1, frame->dts + SRS_AUTO_HLS_DELAY);  
255 - }  
256 - }  
257 -  
258 - int body_size = sizeof(packet) - (p - packet);  
259 - int in_size = last - pos;  
260 -  
261 - if (body_size <= in_size) {  
262 - memcpy(p, pos, body_size);  
263 - pos += body_size;  
264 - } else {  
265 - p = fill_stuff(p, packet, body_size, in_size);  
266 - memcpy(p, pos, in_size);  
267 - pos = last;  
268 - }  
269 -  
270 - // write ts packet  
271 - if ((ret = writer->write(packet, sizeof(packet), NULL)) != ERROR_SUCCESS) {  
272 - if (!srs_is_client_gracefully_close(ret)) {  
273 - srs_error("write ts file failed. ret=%d", ret);  
274 - }  
275 - return ret;  
276 - }  
277 - }  
278 -  
279 - return ret;  
280 - }  
281 -private:  
282 - static char* fill_stuff(char* pes_body_end, char* packet, int body_size, int in_size)  
283 - {  
284 - char* p = pes_body_end;  
285 -  
286 - // insert the stuff bytes before PES body  
287 - int stuff_size = (body_size - in_size);  
288 -  
289 - // adaption_field_control; //2bits  
290 - if (packet[3] & 0x20) {  
291 - // has adaptation  
292 - // packet[4]: adaption_field_length  
293 - // packet[5]: adaption field data  
294 - // base: start of PES body  
295 - char* base = &packet[5] + packet[4];  
296 - int len = p - base;  
297 - p = (char*)memmove(base + stuff_size, base, len) + len;  
298 - // increase the adaption field size.  
299 - packet[4] += stuff_size;  
300 -  
301 - return p;  
302 - }  
303 -  
304 - // create adaption field.  
305 - // adaption_field_control; //2bits  
306 - packet[3] |= 0x20;  
307 - // base: start of PES body  
308 - char* base = &packet[4];  
309 - int len = p - base;  
310 - p = (char*)memmove(base + stuff_size, base, len) + len;  
311 - // adaption_field_length; //8bits  
312 - packet[4] = (stuff_size - 1);  
313 - if (stuff_size >= 2) {  
314 - // adaption field flags.  
315 - packet[5] = 0;  
316 - // adaption data.  
317 - if (stuff_size > 2) {  
318 - memset(&packet[6], 0xff, stuff_size - 2);  
319 - }  
320 - }  
321 -  
322 - return p;  
323 - }  
324 - static char* write_pcr(char* p, int64_t pcr)  
325 - {  
326 - // the pcr=dts-delay  
327 - // and the pcr maybe negative  
328 - // @see https://github.com/winlinvip/simple-rtmp-server/issues/268  
329 - int64_t v = srs_max(0, pcr);  
330 -  
331 - *p++ = (char) (v >> 25);  
332 - *p++ = (char) (v >> 17);  
333 - *p++ = (char) (v >> 9);  
334 - *p++ = (char) (v >> 1);  
335 - *p++ = (char) (v << 7 | 0x7e);  
336 - *p++ = 0;  
337 -  
338 - return p;  
339 - }  
340 - static char* write_pts(char* p, u_int8_t fb, int64_t pts)  
341 - {  
342 - int32_t val;  
343 -  
344 - val = fb << 4 | (((pts >> 30) & 0x07) << 1) | 1;  
345 - *p++ = val;  
346 -  
347 - val = (((pts >> 15) & 0x7fff) << 1) | 1;  
348 - *p++ = (val >> 8);  
349 - *p++ = val;  
350 -  
351 - val = (((pts) & 0x7fff) << 1) | 1;  
352 - *p++ = (val >> 8);  
353 - *p++ = val;  
354 -  
355 - return p;  
356 - }  
357 -};  
358 -  
359 -SrsMpegtsFrame::SrsMpegtsFrame()  
360 -{  
361 - pts = dts = 0;  
362 - pid = sid = cc = 0;  
363 - key = false;  
364 -}  
365 -  
366 -SrsTSMuxer::SrsTSMuxer(SrsFileWriter* w)  
367 -{  
368 - writer = w;  
369 -}  
370 -  
371 -SrsTSMuxer::~SrsTSMuxer()  
372 -{  
373 - close();  
374 -}  
375 -  
376 -int SrsTSMuxer::open(string _path)  
377 -{  
378 - int ret = ERROR_SUCCESS;  
379 -  
380 - path = _path;  
381 -  
382 - close();  
383 -  
384 - if ((ret = writer->open(path)) != ERROR_SUCCESS) {  
385 - return ret;  
386 - }  
387 -  
388 - // write mpegts header  
389 - if ((ret = SrsMpegtsWriter::write_header(writer)) != ERROR_SUCCESS) {  
390 - return ret;  
391 - }  
392 -  
393 - return ret;  
394 -}  
395 -  
396 -int SrsTSMuxer::write_audio(SrsMpegtsFrame* af, SrsSimpleBuffer* ab)  
397 -{  
398 - int ret = ERROR_SUCCESS;  
399 -  
400 - if ((ret = SrsMpegtsWriter::write_frame(writer, af, ab)) != ERROR_SUCCESS) {  
401 - return ret;  
402 - }  
403 -  
404 - return ret;  
405 -}  
406 -  
407 -int SrsTSMuxer::write_video(SrsMpegtsFrame* vf, SrsSimpleBuffer* vb)  
408 -{  
409 - int ret = ERROR_SUCCESS;  
410 -  
411 - if ((ret = SrsMpegtsWriter::write_frame(writer, vf, vb)) != ERROR_SUCCESS) {  
412 - return ret;  
413 - }  
414 -  
415 - return ret;  
416 -}  
417 -  
418 -void SrsTSMuxer::close()  
419 -{  
420 - writer->close();  
421 -}  
422 -  
423 -SrsTsAacJitter::SrsTsAacJitter()  
424 -{  
425 - base_pts = 0;  
426 - nb_samples = 0;  
427 -  
428 - // TODO: config it, 0 means no adjust  
429 - sync_ms = SRS_CONF_DEFAULT_AAC_SYNC;  
430 -}  
431 -  
432 -SrsTsAacJitter::~SrsTsAacJitter()  
433 -{  
434 -}  
435 -  
436 -int64_t SrsTsAacJitter::on_buffer_start(int64_t flv_pts, int sample_rate, int aac_sample_rate)  
437 -{  
438 - // use sample rate in flv/RTMP.  
439 - int flv_sample_rate = flv_sample_rates[sample_rate & 0x03];  
440 -  
441 - // override the sample rate by sequence header  
442 - if (aac_sample_rate != __SRS_AAC_SAMPLE_RATE_UNSET) {  
443 - flv_sample_rate = aac_sample_rates[aac_sample_rate];  
444 - }  
445 -  
446 - // sync time set to 0, donot adjust the aac timestamp.  
447 - if (!sync_ms) {  
448 - return flv_pts;  
449 - }  
450 -  
451 - // @see: ngx_rtmp_hls_audio  
452 - // drop the rtmp audio packet timestamp, re-calc it by sample rate.  
453 - //  
454 - // resample for the tbn of ts is 90000, flv is 1000,  
455 - // we will lost timestamp if use audio packet timestamp,  
456 - // so we must resample. or audio will corupt in IOS.  
457 - int64_t est_pts = base_pts + nb_samples * 90000LL * _SRS_AAC_SAMPLE_SIZE / flv_sample_rate;  
458 - int64_t dpts = (int64_t) (est_pts - flv_pts);  
459 -  
460 - if (dpts <= (int64_t) sync_ms * 90 && dpts >= (int64_t) sync_ms * -90) {  
461 - srs_info("HLS correct aac pts "  
462 - "from %"PRId64" to %"PRId64", base=%"PRId64", nb_samples=%d, sample_rate=%d",  
463 - flv_pts, est_pts, nb_samples, flv_sample_rate, base_pts);  
464 -  
465 - nb_samples++;  
466 -  
467 - return est_pts;  
468 - }  
469 -  
470 - // resync  
471 - srs_trace("HLS aac resync, dpts=%"PRId64", pts=%"PRId64  
472 - ", base=%"PRId64", nb_samples=%"PRId64", sample_rate=%d",  
473 - dpts, flv_pts, base_pts, nb_samples, flv_sample_rate);  
474 -  
475 - base_pts = flv_pts;  
476 - nb_samples = 1;  
477 -  
478 - return flv_pts;  
479 -}  
480 -  
481 -void SrsTsAacJitter::on_buffer_continue()  
482 -{  
483 - nb_samples++;  
484 -}  
485 -  
486 -SrsTsCache::SrsTsCache()  
487 -{  
488 - aac_jitter = new SrsTsAacJitter();  
489 -  
490 - ab = new SrsSimpleBuffer();  
491 - vb = new SrsSimpleBuffer();  
492 -  
493 - af = new SrsMpegtsFrame();  
494 - vf = new SrsMpegtsFrame();  
495 -}  
496 -  
497 -SrsTsCache::~SrsTsCache()  
498 -{  
499 - srs_freep(aac_jitter);  
500 -  
501 - ab->erase(ab->length());  
502 - vb->erase(vb->length());  
503 -  
504 - srs_freep(ab);  
505 - srs_freep(vb);  
506 -  
507 - srs_freep(af);  
508 - srs_freep(vf);  
509 -}  
510 -  
511 -int SrsTsCache::cache_audio(SrsAvcAacCodec* codec, int64_t pts, SrsCodecSample* sample)  
512 -{  
513 - int ret = ERROR_SUCCESS;  
514 -  
515 - // start buffer, set the af  
516 - if (ab->length() == 0) {  
517 - pts = aac_jitter->on_buffer_start(pts, sample->sound_rate, codec->aac_sample_rate);  
518 -  
519 - af->dts = af->pts = pts;  
520 - af->pid = TS_AUDIO_PID;  
521 - af->sid = TS_AUDIO_AAC;  
522 - } else {  
523 - aac_jitter->on_buffer_continue();  
524 - }  
525 -  
526 - // write audio to cache.  
527 - if ((ret = do_cache_audio(codec, sample)) != ERROR_SUCCESS) {  
528 - return ret;  
529 - }  
530 -  
531 - return ret;  
532 -}  
533 -  
534 -int SrsTsCache::cache_video(SrsAvcAacCodec* codec, int64_t dts, SrsCodecSample* sample)  
535 -{  
536 - int ret = ERROR_SUCCESS;  
537 -  
538 - // write video to cache.  
539 - if ((ret = do_cache_video(codec, sample)) != ERROR_SUCCESS) {  
540 - return ret;  
541 - }  
542 -  
543 - vf->dts = dts;  
544 - vf->pts = vf->dts + sample->cts * 90;  
545 - vf->pid = TS_VIDEO_PID;  
546 - vf->sid = TS_VIDEO_AVC;  
547 - vf->key = sample->frame_type == SrsCodecVideoAVCFrameKeyFrame;  
548 -  
549 - return ret;  
550 -}  
551 -  
552 -int SrsTsCache::do_cache_audio(SrsAvcAacCodec* codec, SrsCodecSample* sample)  
553 -{  
554 - int ret = ERROR_SUCCESS;  
555 -  
556 - for (int i = 0; i < sample->nb_sample_units; i++) {  
557 - SrsCodecSampleUnit* sample_unit = &sample->sample_units[i];  
558 - int32_t size = sample_unit->size;  
559 -  
560 - if (!sample_unit->bytes || size <= 0 || size > 0x1fff) {  
561 - ret = ERROR_HLS_AAC_FRAME_LENGTH;  
562 - srs_error("invalid aac frame length=%d, ret=%d", size, ret);  
563 - return ret;  
564 - }  
565 -  
566 - // the frame length is the AAC raw data plus the adts header size.  
567 - int32_t frame_length = size + 7;  
568 -  
569 - // AAC-ADTS  
570 - // 6.2 Audio Data Transport Stream, ADTS  
571 - // in aac-iso-13818-7.pdf, page 26.  
572 - // fixed 7bytes header  
573 - static u_int8_t adts_header[7] = {0xff, 0xf1, 0x00, 0x00, 0x00, 0x0f, 0xfc};  
574 - /*  
575 - // adts_fixed_header  
576 - // 2B, 16bits  
577 - int16_t syncword; //12bits, '1111 1111 1111'  
578 - int8_t ID; //1bit, '0'  
579 - int8_t layer; //2bits, '00'  
580 - int8_t protection_absent; //1bit, can be '1'  
581 - // 12bits  
582 - int8_t profile; //2bit, 7.1 Profiles, page 40  
583 - TSAacSampleFrequency sampling_frequency_index; //4bits, Table 35, page 46  
584 - int8_t private_bit; //1bit, can be '0'  
585 - int8_t channel_configuration; //3bits, Table 8  
586 - int8_t original_or_copy; //1bit, can be '0'  
587 - int8_t home; //1bit, can be '0'  
588 -  
589 - // adts_variable_header  
590 - // 28bits  
591 - int8_t copyright_identification_bit; //1bit, can be '0'  
592 - int8_t copyright_identification_start; //1bit, can be '0'  
593 - int16_t frame_length; //13bits  
594 - int16_t adts_buffer_fullness; //11bits, 7FF signals that the bitstream is a variable rate bitstream.  
595 - int8_t number_of_raw_data_blocks_in_frame; //2bits, 0 indicating 1 raw_data_block()  
596 - */  
597 - // profile, 2bits  
598 - adts_header[2] = (codec->aac_profile << 6) & 0xc0;  
599 - // sampling_frequency_index 4bits  
600 - adts_header[2] |= (codec->aac_sample_rate << 2) & 0x3c;  
601 - // channel_configuration 3bits  
602 - adts_header[2] |= (codec->aac_channels >> 2) & 0x01;  
603 - adts_header[3] = (codec->aac_channels << 6) & 0xc0;  
604 - // frame_length 13bits  
605 - adts_header[3] |= (frame_length >> 11) & 0x03;  
606 - adts_header[4] = (frame_length >> 3) & 0xff;  
607 - adts_header[5] = ((frame_length << 5) & 0xe0);  
608 - // adts_buffer_fullness; //11bits  
609 - adts_header[5] |= 0x1f;  
610 -  
611 - // copy to audio buffer  
612 - ab->append((const char*)adts_header, sizeof(adts_header));  
613 - ab->append(sample_unit->bytes, sample_unit->size);  
614 - }  
615 -  
616 - return ret;  
617 -}  
618 -  
619 -int SrsTsCache::do_cache_video(SrsAvcAacCodec* codec, SrsCodecSample* sample)  
620 -{  
621 - int ret = ERROR_SUCCESS;  
622 -  
623 - // for type1/5/6, insert aud packet.  
624 - static u_int8_t aud_nal[] = { 0x00, 0x00, 0x00, 0x01, 0x09, 0xf0 };  
625 -  
626 - bool sps_pps_sent = false;  
627 - bool aud_sent = false;  
628 - /**  
629 - * a ts sample is format as:  
630 - * 00 00 00 01 // header  
631 - * xxxxxxx // data bytes  
632 - * 00 00 01 // continue header  
633 - * xxxxxxx // data bytes.  
634 - * so, for each sample, we append header in aud_nal, then appends the bytes in sample.  
635 - */  
636 - for (int i = 0; i < sample->nb_sample_units; i++) {  
637 - SrsCodecSampleUnit* sample_unit = &sample->sample_units[i];  
638 - int32_t size = sample_unit->size;  
639 -  
640 - if (!sample_unit->bytes || size <= 0) {  
641 - ret = ERROR_HLS_AVC_SAMPLE_SIZE;  
642 - srs_error("invalid avc sample length=%d, ret=%d", size, ret);  
643 - return ret;  
644 - }  
645 -  
646 - /**  
647 - * step 1:  
648 - * first, before each "real" sample,  
649 - * we add some packets according to the nal_unit_type,  
650 - * for example, when got nal_unit_type=5, insert SPS/PPS before sample.  
651 - */  
652 -  
653 - // 5bits, 7.3.1 NAL unit syntax,  
654 - // H.264-AVC-ISO_IEC_14496-10.pdf, page 44.  
655 - u_int8_t nal_unit_type;  
656 - nal_unit_type = *sample_unit->bytes;  
657 - nal_unit_type &= 0x1f;  
658 -  
659 - // @see: ngx_rtmp_hls_video  
660 - // Table 7-1 C NAL unit type codes, page 61  
661 - // 1: Coded slice  
662 - if (nal_unit_type == 1) {  
663 - sps_pps_sent = false;  
664 - }  
665 -  
666 - // 6: Supplemental enhancement information (SEI) sei_rbsp( ), page 61  
667 - // @see: ngx_rtmp_hls_append_aud  
668 - if (!aud_sent) {  
669 - // @remark, when got type 9, we donot send aud_nal, but it will make  
670 - // ios unhappy, so we remove it.  
671 - // @see https://github.com/winlinvip/simple-rtmp-server/issues/281  
672 - /*if (nal_unit_type == 9) {  
673 - aud_sent = true;  
674 - }*/  
675 -  
676 - if (nal_unit_type == 1 || nal_unit_type == 5 || nal_unit_type == 6) {  
677 - // for type 6, append a aud with type 9.  
678 - vb->append((const char*)aud_nal, sizeof(aud_nal));  
679 - aud_sent = true;  
680 - }  
681 - }  
682 -  
683 - // 5: Coded slice of an IDR picture.  
684 - // insert sps/pps before IDR or key frame is ok.  
685 - if (nal_unit_type == 5 && !sps_pps_sent) {  
686 - sps_pps_sent = true;  
687 -  
688 - // @see: ngx_rtmp_hls_append_sps_pps  
689 - if (codec->sequenceParameterSetLength > 0) {  
690 - // AnnexB prefix, for sps always 4 bytes header  
691 - vb->append((const char*)aud_nal, 4);  
692 - // sps  
693 - vb->append(codec->sequenceParameterSetNALUnit, codec->sequenceParameterSetLength);  
694 - }  
695 - if (codec->pictureParameterSetLength > 0) {  
696 - // AnnexB prefix, for pps always 4 bytes header  
697 - vb->append((const char*)aud_nal, 4);  
698 - // pps  
699 - vb->append(codec->pictureParameterSetNALUnit, codec->pictureParameterSetLength);  
700 - }  
701 - }  
702 -  
703 - // 7-9, ignore, @see: ngx_rtmp_hls_video  
704 - if (nal_unit_type >= 7 && nal_unit_type <= 9) {  
705 - continue;  
706 - }  
707 -  
708 - /**  
709 - * step 2:  
710 - * output the "real" sample, in buf.  
711 - * when we output some special assist packets according to nal_unit_type  
712 - */  
713 -  
714 - // sample start prefix, '00 00 00 01' or '00 00 01'  
715 - u_int8_t* p = aud_nal + 1;  
716 - u_int8_t* end = p + 3;  
717 -  
718 - // first AnnexB prefix is long (4 bytes)  
719 - if (vb->length() == 0) {  
720 - p = aud_nal;  
721 - }  
722 - vb->append((const char*)p, end - p);  
723 -  
724 - // sample data  
725 - vb->append(sample_unit->bytes, sample_unit->size);  
726 - }  
727 -  
728 - return ret;  
729 -}  
730 -  
731 SrsCodecSampleUnit::SrsCodecSampleUnit() 35 SrsCodecSampleUnit::SrsCodecSampleUnit()
732 { 36 {
733 size = 0; 37 size = 0;
@@ -95,109 +95,6 @@ enum SrsCodecAudioSoundType @@ -95,109 +95,6 @@ enum SrsCodecAudioSoundType
95 SrsCodecAudioSoundTypeStereo = 1, 95 SrsCodecAudioSoundTypeStereo = 1,
96 }; 96 };
97 97
98 -// @see: ngx_rtmp_SrsMpegtsFrame_t  
99 -class SrsMpegtsFrame  
100 -{  
101 -public:  
102 - int64_t pts;  
103 - int64_t dts;  
104 - int pid;  
105 - int sid;  
106 - int cc;  
107 - bool key;  
108 -  
109 - SrsMpegtsFrame();  
110 -};  
111 -  
112 -/**  
113 -* write data from frame(header info) and buffer(data) to ts file.  
114 -* it's a simple object wrapper for utility from nginx-rtmp: SrsMpegtsWriter  
115 -*/  
116 -class SrsTSMuxer  
117 -{  
118 -private:  
119 - SrsFileWriter* writer;  
120 - std::string path;  
121 -public:  
122 - SrsTSMuxer(SrsFileWriter* w);  
123 - virtual ~SrsTSMuxer();  
124 -public:  
125 - virtual int open(std::string _path);  
126 - virtual int write_audio(SrsMpegtsFrame* af, SrsSimpleBuffer* ab);  
127 - virtual int write_video(SrsMpegtsFrame* vf, SrsSimpleBuffer* vb);  
128 - virtual void close();  
129 -};  
130 -  
131 -/**  
132 -* jitter correct for audio,  
133 -* the sample rate 44100/32000 will lost precise,  
134 -* when mp4/ts(tbn=90000) covert to flv/rtmp(1000),  
135 -* so the Hls on ipad or iphone will corrupt,  
136 -* @see nginx-rtmp: est_pts  
137 -*/  
138 -class SrsTsAacJitter  
139 -{  
140 -private:  
141 - int64_t base_pts;  
142 - int64_t nb_samples;  
143 - int sync_ms;  
144 -public:  
145 - SrsTsAacJitter();  
146 - virtual ~SrsTsAacJitter();  
147 - /**  
148 - * when buffer start, calc the "correct" pts for ts,  
149 - * @param flv_pts, the flv pts calc from flv header timestamp,  
150 - * @param sample_rate, the sample rate in format(flv/RTMP packet header).  
151 - * @param aac_sample_rate, the sample rate in codec(sequence header).  
152 - * @return the calc correct pts.  
153 - */  
154 - virtual int64_t on_buffer_start(int64_t flv_pts, int sample_rate, int aac_sample_rate);  
155 - /**  
156 - * when buffer continue, muxer donot write to file,  
157 - * the audio buffer continue grow and donot need a pts,  
158 - * for the ts audio PES packet only has one pts at the first time.  
159 - */  
160 - virtual void on_buffer_continue();  
161 -};  
162 -  
163 -/**  
164 -* ts stream cache,  
165 -* use to cache ts stream.  
166 -*  
167 -* about the flv tbn problem:  
168 -* flv tbn is 1/1000, ts tbn is 1/90000,  
169 -* when timestamp convert to flv tbn, it will loose precise,  
170 -* so we must gather audio frame together, and recalc the timestamp @see SrsTsAacJitter,  
171 -* we use a aac jitter to correct the audio pts.  
172 -*/  
173 -class SrsTsCache  
174 -{  
175 -public:  
176 - // current frame and buffer  
177 - SrsMpegtsFrame* af;  
178 - SrsSimpleBuffer* ab;  
179 - SrsMpegtsFrame* vf;  
180 - SrsSimpleBuffer* vb;  
181 -protected:  
182 - // time jitter for aac  
183 - SrsTsAacJitter* aac_jitter;  
184 -public:  
185 - SrsTsCache();  
186 - virtual ~SrsTsCache();  
187 -public:  
188 - /**  
189 - * write audio to cache  
190 - */  
191 - virtual int cache_audio(SrsAvcAacCodec* codec, int64_t pts, SrsCodecSample* sample);  
192 - /**  
193 - * write video to muxer.  
194 - */  
195 - virtual int cache_video(SrsAvcAacCodec* codec, int64_t dts, SrsCodecSample* sample);  
196 -private:  
197 - virtual int do_cache_audio(SrsAvcAacCodec* codec, SrsCodecSample* sample);  
198 - virtual int do_cache_video(SrsAvcAacCodec* codec, SrsCodecSample* sample);  
199 -};  
200 -  
201 /** 98 /**
202 * the codec sample unit. 99 * the codec sample unit.
203 * for h.264 video packet, a NALU is a sample unit. 100 * for h.264 video packet, a NALU is a sample unit.
@@ -37,6 +37,703 @@ using namespace std; @@ -37,6 +37,703 @@ using namespace std;
37 #include <srs_kernel_file.hpp> 37 #include <srs_kernel_file.hpp>
38 #include <srs_kernel_avc.hpp> 38 #include <srs_kernel_avc.hpp>
39 #include <srs_kernel_buffer.hpp> 39 #include <srs_kernel_buffer.hpp>
  40 +#include <srs_kernel_utility.hpp>
  41 +
  42 +// in ms, for HLS aac sync time.
  43 +#define SRS_CONF_DEFAULT_AAC_SYNC 100
  44 +
  45 +// @see: ngx_rtmp_hls_audio
  46 +/* We assume here AAC frame size is 1024
  47 + * Need to handle AAC frames with frame size of 960 */
  48 +#define _SRS_AAC_SAMPLE_SIZE 1024
  49 +
  50 +// the mpegts header specifed the video/audio pid.
  51 +#define TS_VIDEO_PID 256
  52 +#define TS_AUDIO_PID 257
  53 +
  54 +// ts aac stream id.
  55 +#define TS_AUDIO_AAC 0xc0
  56 +// ts avc stream id.
  57 +#define TS_VIDEO_AVC 0xe0
  58 +
  59 +/**
  60 +* the public data, event HLS disable, others can use it.
  61 +*/
  62 +// 0 = 5.5 kHz = 5512 Hz
  63 +// 1 = 11 kHz = 11025 Hz
  64 +// 2 = 22 kHz = 22050 Hz
  65 +// 3 = 44 kHz = 44100 Hz
  66 +int flv_sample_rates[] = {5512, 11025, 22050, 44100};
  67 +
  68 +// the sample rates in the codec,
  69 +// in the sequence header.
  70 +int aac_sample_rates[] =
  71 +{
  72 + 96000, 88200, 64000, 48000,
  73 + 44100, 32000, 24000, 22050,
  74 + 16000, 12000, 11025, 8000,
  75 + 7350, 0, 0, 0
  76 +};
  77 +
  78 +// @see: NGX_RTMP_HLS_DELAY,
  79 +// 63000: 700ms, ts_tbn=90000
  80 +#define SRS_AUTO_HLS_DELAY 63000
  81 +
  82 +// @see: ngx_rtmp_mpegts_header
  83 +u_int8_t mpegts_header[] = {
  84 + /* TS */
  85 + 0x47, 0x40, 0x00, 0x10, 0x00,
  86 + /* PSI */
  87 + 0x00, 0xb0, 0x0d, 0x00, 0x01, 0xc1, 0x00, 0x00,
  88 + /* PAT */
  89 + 0x00, 0x01, 0xf0, 0x01,
  90 + /* CRC */
  91 + 0x2e, 0x70, 0x19, 0x05,
  92 + /* stuffing 167 bytes */
  93 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  94 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  95 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  96 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  97 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  98 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  99 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  100 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  101 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  102 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  103 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  104 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  105 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  106 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  107 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  108 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  109 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  110 +
  111 + /* TS */
  112 + 0x47, 0x50, 0x01, 0x10, 0x00,
  113 + /* PSI */
  114 + 0x02, 0xb0, 0x17, 0x00, 0x01, 0xc1, 0x00, 0x00,
  115 + /* PMT */
  116 + 0xe1, 0x00,
  117 + 0xf0, 0x00,
  118 + // must generate header with/without video, @see:
  119 + // https://github.com/winlinvip/simple-rtmp-server/issues/40
  120 + 0x1b, 0xe1, 0x00, 0xf0, 0x00, /* h264, pid=0x100=256 */
  121 + 0x0f, 0xe1, 0x01, 0xf0, 0x00, /* aac, pid=0x101=257 */
  122 + /*0x03, 0xe1, 0x01, 0xf0, 0x00,*/ /* mp3 */
  123 + /* CRC */
  124 + 0x2f, 0x44, 0xb9, 0x9b, /* crc for aac */
  125 + /*0x4e, 0x59, 0x3d, 0x1e,*/ /* crc for mp3 */
  126 + /* stuffing 157 bytes */
  127 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  128 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  129 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  130 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  131 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  132 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  133 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  134 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  135 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  136 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  137 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  138 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  139 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  140 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  141 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  142 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
  143 +};
  144 +
  145 +// @see: ngx_rtmp_mpegts.c
  146 +// TODO: support full mpegts feature in future.
  147 +class SrsMpegtsWriter
  148 +{
  149 +public:
  150 + static int write_header(SrsFileWriter* writer)
  151 + {
  152 + int ret = ERROR_SUCCESS;
  153 +
  154 + if ((ret = writer->write(mpegts_header, sizeof(mpegts_header), NULL)) != ERROR_SUCCESS) {
  155 + ret = ERROR_HLS_WRITE_FAILED;
  156 + srs_error("write ts file header failed. ret=%d", ret);
  157 + return ret;
  158 + }
  159 +
  160 + return ret;
  161 + }
  162 + static int write_frame(SrsFileWriter* writer, SrsMpegtsFrame* frame, SrsSimpleBuffer* buffer)
  163 + {
  164 + int ret = ERROR_SUCCESS;
  165 +
  166 + if (!buffer->bytes() || buffer->length() <= 0) {
  167 + return ret;
  168 + }
  169 +
  170 + char* last = buffer->bytes() + buffer->length();
  171 + char* pos = buffer->bytes();
  172 +
  173 + bool first = true;
  174 + while (pos < last) {
  175 + static char packet[188];
  176 + char* p = packet;
  177 +
  178 + frame->cc++;
  179 +
  180 + // sync_byte; //8bits
  181 + *p++ = 0x47;
  182 + // pid; //13bits
  183 + *p++ = (frame->pid >> 8) & 0x1f;
  184 + // payload_unit_start_indicator; //1bit
  185 + if (first) {
  186 + p[-1] |= 0x40;
  187 + }
  188 + *p++ = frame->pid;
  189 +
  190 + // transport_scrambling_control; //2bits
  191 + // adaption_field_control; //2bits, 0x01: PayloadOnly
  192 + // continuity_counter; //4bits
  193 + *p++ = 0x10 | (frame->cc & 0x0f);
  194 +
  195 + if (first) {
  196 + first = false;
  197 + if (frame->key) {
  198 + p[-1] |= 0x20; // Both Adaption and Payload
  199 + *p++ = 7; // size
  200 + *p++ = 0x50; // random access + PCR
  201 + p = write_pcr(p, frame->dts - SRS_AUTO_HLS_DELAY);
  202 + }
  203 +
  204 + // PES header
  205 + // packet_start_code_prefix; //24bits, '00 00 01'
  206 + *p++ = 0x00;
  207 + *p++ = 0x00;
  208 + *p++ = 0x01;
  209 + //8bits
  210 + *p++ = frame->sid;
  211 +
  212 + // pts(33bits) need 5bytes.
  213 + u_int8_t header_size = 5;
  214 + u_int8_t flags = 0x80; // pts
  215 +
  216 + // dts(33bits) need 5bytes also
  217 + if (frame->dts != frame->pts) {
  218 + header_size += 5;
  219 + flags |= 0x40; // dts
  220 + }
  221 +
  222 + // 3bytes: flag fields from PES_packet_length to PES_header_data_length
  223 + int pes_size = (last - pos) + header_size + 3;
  224 + if (pes_size > 0xffff) {
  225 + /**
  226 + * when actual packet length > 0xffff(65535),
  227 + * which exceed the max u_int16_t packet length,
  228 + * use 0 packet length, the next unit start indicates the end of packet.
  229 + */
  230 + pes_size = 0;
  231 + }
  232 +
  233 + // PES_packet_length; //16bits
  234 + *p++ = (pes_size >> 8);
  235 + *p++ = pes_size;
  236 +
  237 + // PES_scrambling_control; //2bits, '10'
  238 + // PES_priority; //1bit
  239 + // data_alignment_indicator; //1bit
  240 + // copyright; //1bit
  241 + // original_or_copy; //1bit
  242 + *p++ = 0x80; /* H222 */
  243 +
  244 + // PTS_DTS_flags; //2bits
  245 + // ESCR_flag; //1bit
  246 + // ES_rate_flag; //1bit
  247 + // DSM_trick_mode_flag; //1bit
  248 + // additional_copy_info_flag; //1bit
  249 + // PES_CRC_flag; //1bit
  250 + // PES_extension_flag; //1bit
  251 + *p++ = flags;
  252 +
  253 + // PES_header_data_length; //8bits
  254 + *p++ = header_size;
  255 +
  256 + // pts; // 33bits
  257 + p = write_pts(p, flags >> 6, frame->pts + SRS_AUTO_HLS_DELAY);
  258 +
  259 + // dts; // 33bits
  260 + if (frame->dts != frame->pts) {
  261 + p = write_pts(p, 1, frame->dts + SRS_AUTO_HLS_DELAY);
  262 + }
  263 + }
  264 +
  265 + int body_size = sizeof(packet) - (p - packet);
  266 + int in_size = last - pos;
  267 +
  268 + if (body_size <= in_size) {
  269 + memcpy(p, pos, body_size);
  270 + pos += body_size;
  271 + } else {
  272 + p = fill_stuff(p, packet, body_size, in_size);
  273 + memcpy(p, pos, in_size);
  274 + pos = last;
  275 + }
  276 +
  277 + // write ts packet
  278 + if ((ret = writer->write(packet, sizeof(packet), NULL)) != ERROR_SUCCESS) {
  279 + if (!srs_is_client_gracefully_close(ret)) {
  280 + srs_error("write ts file failed. ret=%d", ret);
  281 + }
  282 + return ret;
  283 + }
  284 + }
  285 +
  286 + return ret;
  287 + }
  288 +private:
  289 + static char* fill_stuff(char* pes_body_end, char* packet, int body_size, int in_size)
  290 + {
  291 + char* p = pes_body_end;
  292 +
  293 + // insert the stuff bytes before PES body
  294 + int stuff_size = (body_size - in_size);
  295 +
  296 + // adaption_field_control; //2bits
  297 + if (packet[3] & 0x20) {
  298 + // has adaptation
  299 + // packet[4]: adaption_field_length
  300 + // packet[5]: adaption field data
  301 + // base: start of PES body
  302 + char* base = &packet[5] + packet[4];
  303 + int len = p - base;
  304 + p = (char*)memmove(base + stuff_size, base, len) + len;
  305 + // increase the adaption field size.
  306 + packet[4] += stuff_size;
  307 +
  308 + return p;
  309 + }
  310 +
  311 + // create adaption field.
  312 + // adaption_field_control; //2bits
  313 + packet[3] |= 0x20;
  314 + // base: start of PES body
  315 + char* base = &packet[4];
  316 + int len = p - base;
  317 + p = (char*)memmove(base + stuff_size, base, len) + len;
  318 + // adaption_field_length; //8bits
  319 + packet[4] = (stuff_size - 1);
  320 + if (stuff_size >= 2) {
  321 + // adaption field flags.
  322 + packet[5] = 0;
  323 + // adaption data.
  324 + if (stuff_size > 2) {
  325 + memset(&packet[6], 0xff, stuff_size - 2);
  326 + }
  327 + }
  328 +
  329 + return p;
  330 + }
  331 + static char* write_pcr(char* p, int64_t pcr)
  332 + {
  333 + // the pcr=dts-delay
  334 + // and the pcr maybe negative
  335 + // @see https://github.com/winlinvip/simple-rtmp-server/issues/268
  336 + int64_t v = srs_max(0, pcr);
  337 +
  338 + *p++ = (char) (v >> 25);
  339 + *p++ = (char) (v >> 17);
  340 + *p++ = (char) (v >> 9);
  341 + *p++ = (char) (v >> 1);
  342 + *p++ = (char) (v << 7 | 0x7e);
  343 + *p++ = 0;
  344 +
  345 + return p;
  346 + }
  347 + static char* write_pts(char* p, u_int8_t fb, int64_t pts)
  348 + {
  349 + int32_t val;
  350 +
  351 + val = fb << 4 | (((pts >> 30) & 0x07) << 1) | 1;
  352 + *p++ = val;
  353 +
  354 + val = (((pts >> 15) & 0x7fff) << 1) | 1;
  355 + *p++ = (val >> 8);
  356 + *p++ = val;
  357 +
  358 + val = (((pts) & 0x7fff) << 1) | 1;
  359 + *p++ = (val >> 8);
  360 + *p++ = val;
  361 +
  362 + return p;
  363 + }
  364 +};
  365 +
  366 +SrsMpegtsFrame::SrsMpegtsFrame()
  367 +{
  368 + pts = dts = 0;
  369 + pid = sid = cc = 0;
  370 + key = false;
  371 +}
  372 +
  373 +SrsTSMuxer::SrsTSMuxer(SrsFileWriter* w)
  374 +{
  375 + writer = w;
  376 +}
  377 +
  378 +SrsTSMuxer::~SrsTSMuxer()
  379 +{
  380 + close();
  381 +}
  382 +
  383 +int SrsTSMuxer::open(string _path)
  384 +{
  385 + int ret = ERROR_SUCCESS;
  386 +
  387 + path = _path;
  388 +
  389 + close();
  390 +
  391 + if ((ret = writer->open(path)) != ERROR_SUCCESS) {
  392 + return ret;
  393 + }
  394 +
  395 + // write mpegts header
  396 + if ((ret = SrsMpegtsWriter::write_header(writer)) != ERROR_SUCCESS) {
  397 + return ret;
  398 + }
  399 +
  400 + return ret;
  401 +}
  402 +
  403 +int SrsTSMuxer::write_audio(SrsMpegtsFrame* af, SrsSimpleBuffer* ab)
  404 +{
  405 + int ret = ERROR_SUCCESS;
  406 +
  407 + if ((ret = SrsMpegtsWriter::write_frame(writer, af, ab)) != ERROR_SUCCESS) {
  408 + return ret;
  409 + }
  410 +
  411 + return ret;
  412 +}
  413 +
  414 +int SrsTSMuxer::write_video(SrsMpegtsFrame* vf, SrsSimpleBuffer* vb)
  415 +{
  416 + int ret = ERROR_SUCCESS;
  417 +
  418 + if ((ret = SrsMpegtsWriter::write_frame(writer, vf, vb)) != ERROR_SUCCESS) {
  419 + return ret;
  420 + }
  421 +
  422 + return ret;
  423 +}
  424 +
  425 +void SrsTSMuxer::close()
  426 +{
  427 + writer->close();
  428 +}
  429 +
  430 +SrsTsAacJitter::SrsTsAacJitter()
  431 +{
  432 + base_pts = 0;
  433 + nb_samples = 0;
  434 +
  435 + // TODO: config it, 0 means no adjust
  436 + sync_ms = SRS_CONF_DEFAULT_AAC_SYNC;
  437 +}
  438 +
  439 +SrsTsAacJitter::~SrsTsAacJitter()
  440 +{
  441 +}
  442 +
  443 +int64_t SrsTsAacJitter::on_buffer_start(int64_t flv_pts, int sample_rate, int aac_sample_rate)
  444 +{
  445 + // use sample rate in flv/RTMP.
  446 + int flv_sample_rate = flv_sample_rates[sample_rate & 0x03];
  447 +
  448 + // override the sample rate by sequence header
  449 + if (aac_sample_rate != __SRS_AAC_SAMPLE_RATE_UNSET) {
  450 + flv_sample_rate = aac_sample_rates[aac_sample_rate];
  451 + }
  452 +
  453 + // sync time set to 0, donot adjust the aac timestamp.
  454 + if (!sync_ms) {
  455 + return flv_pts;
  456 + }
  457 +
  458 + // @see: ngx_rtmp_hls_audio
  459 + // drop the rtmp audio packet timestamp, re-calc it by sample rate.
  460 + //
  461 + // resample for the tbn of ts is 90000, flv is 1000,
  462 + // we will lost timestamp if use audio packet timestamp,
  463 + // so we must resample. or audio will corupt in IOS.
  464 + int64_t est_pts = base_pts + nb_samples * 90000LL * _SRS_AAC_SAMPLE_SIZE / flv_sample_rate;
  465 + int64_t dpts = (int64_t) (est_pts - flv_pts);
  466 +
  467 + if (dpts <= (int64_t) sync_ms * 90 && dpts >= (int64_t) sync_ms * -90) {
  468 + srs_info("HLS correct aac pts "
  469 + "from %"PRId64" to %"PRId64", base=%"PRId64", nb_samples=%d, sample_rate=%d",
  470 + flv_pts, est_pts, nb_samples, flv_sample_rate, base_pts);
  471 +
  472 + nb_samples++;
  473 +
  474 + return est_pts;
  475 + }
  476 +
  477 + // resync
  478 + srs_trace("HLS aac resync, dpts=%"PRId64", pts=%"PRId64
  479 + ", base=%"PRId64", nb_samples=%"PRId64", sample_rate=%d",
  480 + dpts, flv_pts, base_pts, nb_samples, flv_sample_rate);
  481 +
  482 + base_pts = flv_pts;
  483 + nb_samples = 1;
  484 +
  485 + return flv_pts;
  486 +}
  487 +
  488 +void SrsTsAacJitter::on_buffer_continue()
  489 +{
  490 + nb_samples++;
  491 +}
  492 +
  493 +SrsTsCache::SrsTsCache()
  494 +{
  495 + aac_jitter = new SrsTsAacJitter();
  496 +
  497 + ab = new SrsSimpleBuffer();
  498 + vb = new SrsSimpleBuffer();
  499 +
  500 + af = new SrsMpegtsFrame();
  501 + vf = new SrsMpegtsFrame();
  502 +}
  503 +
  504 +SrsTsCache::~SrsTsCache()
  505 +{
  506 + srs_freep(aac_jitter);
  507 +
  508 + ab->erase(ab->length());
  509 + vb->erase(vb->length());
  510 +
  511 + srs_freep(ab);
  512 + srs_freep(vb);
  513 +
  514 + srs_freep(af);
  515 + srs_freep(vf);
  516 +}
  517 +
  518 +int SrsTsCache::cache_audio(SrsAvcAacCodec* codec, int64_t pts, SrsCodecSample* sample)
  519 +{
  520 + int ret = ERROR_SUCCESS;
  521 +
  522 + // start buffer, set the af
  523 + if (ab->length() == 0) {
  524 + pts = aac_jitter->on_buffer_start(pts, sample->sound_rate, codec->aac_sample_rate);
  525 +
  526 + af->dts = af->pts = pts;
  527 + af->pid = TS_AUDIO_PID;
  528 + af->sid = TS_AUDIO_AAC;
  529 + } else {
  530 + aac_jitter->on_buffer_continue();
  531 + }
  532 +
  533 + // write audio to cache.
  534 + if ((ret = do_cache_audio(codec, sample)) != ERROR_SUCCESS) {
  535 + return ret;
  536 + }
  537 +
  538 + return ret;
  539 +}
  540 +
  541 +int SrsTsCache::cache_video(SrsAvcAacCodec* codec, int64_t dts, SrsCodecSample* sample)
  542 +{
  543 + int ret = ERROR_SUCCESS;
  544 +
  545 + // write video to cache.
  546 + if ((ret = do_cache_video(codec, sample)) != ERROR_SUCCESS) {
  547 + return ret;
  548 + }
  549 +
  550 + vf->dts = dts;
  551 + vf->pts = vf->dts + sample->cts * 90;
  552 + vf->pid = TS_VIDEO_PID;
  553 + vf->sid = TS_VIDEO_AVC;
  554 + vf->key = sample->frame_type == SrsCodecVideoAVCFrameKeyFrame;
  555 +
  556 + return ret;
  557 +}
  558 +
  559 +int SrsTsCache::do_cache_audio(SrsAvcAacCodec* codec, SrsCodecSample* sample)
  560 +{
  561 + int ret = ERROR_SUCCESS;
  562 +
  563 + for (int i = 0; i < sample->nb_sample_units; i++) {
  564 + SrsCodecSampleUnit* sample_unit = &sample->sample_units[i];
  565 + int32_t size = sample_unit->size;
  566 +
  567 + if (!sample_unit->bytes || size <= 0 || size > 0x1fff) {
  568 + ret = ERROR_HLS_AAC_FRAME_LENGTH;
  569 + srs_error("invalid aac frame length=%d, ret=%d", size, ret);
  570 + return ret;
  571 + }
  572 +
  573 + // the frame length is the AAC raw data plus the adts header size.
  574 + int32_t frame_length = size + 7;
  575 +
  576 + // AAC-ADTS
  577 + // 6.2 Audio Data Transport Stream, ADTS
  578 + // in aac-iso-13818-7.pdf, page 26.
  579 + // fixed 7bytes header
  580 + static u_int8_t adts_header[7] = {0xff, 0xf1, 0x00, 0x00, 0x00, 0x0f, 0xfc};
  581 + /*
  582 + // adts_fixed_header
  583 + // 2B, 16bits
  584 + int16_t syncword; //12bits, '1111 1111 1111'
  585 + int8_t ID; //1bit, '0'
  586 + int8_t layer; //2bits, '00'
  587 + int8_t protection_absent; //1bit, can be '1'
  588 + // 12bits
  589 + int8_t profile; //2bit, 7.1 Profiles, page 40
  590 + TSAacSampleFrequency sampling_frequency_index; //4bits, Table 35, page 46
  591 + int8_t private_bit; //1bit, can be '0'
  592 + int8_t channel_configuration; //3bits, Table 8
  593 + int8_t original_or_copy; //1bit, can be '0'
  594 + int8_t home; //1bit, can be '0'
  595 +
  596 + // adts_variable_header
  597 + // 28bits
  598 + int8_t copyright_identification_bit; //1bit, can be '0'
  599 + int8_t copyright_identification_start; //1bit, can be '0'
  600 + int16_t frame_length; //13bits
  601 + int16_t adts_buffer_fullness; //11bits, 7FF signals that the bitstream is a variable rate bitstream.
  602 + int8_t number_of_raw_data_blocks_in_frame; //2bits, 0 indicating 1 raw_data_block()
  603 + */
  604 + // profile, 2bits
  605 + adts_header[2] = (codec->aac_profile << 6) & 0xc0;
  606 + // sampling_frequency_index 4bits
  607 + adts_header[2] |= (codec->aac_sample_rate << 2) & 0x3c;
  608 + // channel_configuration 3bits
  609 + adts_header[2] |= (codec->aac_channels >> 2) & 0x01;
  610 + adts_header[3] = (codec->aac_channels << 6) & 0xc0;
  611 + // frame_length 13bits
  612 + adts_header[3] |= (frame_length >> 11) & 0x03;
  613 + adts_header[4] = (frame_length >> 3) & 0xff;
  614 + adts_header[5] = ((frame_length << 5) & 0xe0);
  615 + // adts_buffer_fullness; //11bits
  616 + adts_header[5] |= 0x1f;
  617 +
  618 + // copy to audio buffer
  619 + ab->append((const char*)adts_header, sizeof(adts_header));
  620 + ab->append(sample_unit->bytes, sample_unit->size);
  621 + }
  622 +
  623 + return ret;
  624 +}
  625 +
  626 +int SrsTsCache::do_cache_video(SrsAvcAacCodec* codec, SrsCodecSample* sample)
  627 +{
  628 + int ret = ERROR_SUCCESS;
  629 +
  630 + // for type1/5/6, insert aud packet.
  631 + static u_int8_t aud_nal[] = { 0x00, 0x00, 0x00, 0x01, 0x09, 0xf0 };
  632 +
  633 + bool sps_pps_sent = false;
  634 + bool aud_sent = false;
  635 + /**
  636 + * a ts sample is format as:
  637 + * 00 00 00 01 // header
  638 + * xxxxxxx // data bytes
  639 + * 00 00 01 // continue header
  640 + * xxxxxxx // data bytes.
  641 + * so, for each sample, we append header in aud_nal, then appends the bytes in sample.
  642 + */
  643 + for (int i = 0; i < sample->nb_sample_units; i++) {
  644 + SrsCodecSampleUnit* sample_unit = &sample->sample_units[i];
  645 + int32_t size = sample_unit->size;
  646 +
  647 + if (!sample_unit->bytes || size <= 0) {
  648 + ret = ERROR_HLS_AVC_SAMPLE_SIZE;
  649 + srs_error("invalid avc sample length=%d, ret=%d", size, ret);
  650 + return ret;
  651 + }
  652 +
  653 + /**
  654 + * step 1:
  655 + * first, before each "real" sample,
  656 + * we add some packets according to the nal_unit_type,
  657 + * for example, when got nal_unit_type=5, insert SPS/PPS before sample.
  658 + */
  659 +
  660 + // 5bits, 7.3.1 NAL unit syntax,
  661 + // H.264-AVC-ISO_IEC_14496-10.pdf, page 44.
  662 + u_int8_t nal_unit_type;
  663 + nal_unit_type = *sample_unit->bytes;
  664 + nal_unit_type &= 0x1f;
  665 +
  666 + // @see: ngx_rtmp_hls_video
  667 + // Table 7-1 C NAL unit type codes, page 61
  668 + // 1: Coded slice
  669 + if (nal_unit_type == 1) {
  670 + sps_pps_sent = false;
  671 + }
  672 +
  673 + // 6: Supplemental enhancement information (SEI) sei_rbsp( ), page 61
  674 + // @see: ngx_rtmp_hls_append_aud
  675 + if (!aud_sent) {
  676 + // @remark, when got type 9, we donot send aud_nal, but it will make
  677 + // ios unhappy, so we remove it.
  678 + // @see https://github.com/winlinvip/simple-rtmp-server/issues/281
  679 + /*if (nal_unit_type == 9) {
  680 + aud_sent = true;
  681 + }*/
  682 +
  683 + if (nal_unit_type == 1 || nal_unit_type == 5 || nal_unit_type == 6) {
  684 + // for type 6, append a aud with type 9.
  685 + vb->append((const char*)aud_nal, sizeof(aud_nal));
  686 + aud_sent = true;
  687 + }
  688 + }
  689 +
  690 + // 5: Coded slice of an IDR picture.
  691 + // insert sps/pps before IDR or key frame is ok.
  692 + if (nal_unit_type == 5 && !sps_pps_sent) {
  693 + sps_pps_sent = true;
  694 +
  695 + // @see: ngx_rtmp_hls_append_sps_pps
  696 + if (codec->sequenceParameterSetLength > 0) {
  697 + // AnnexB prefix, for sps always 4 bytes header
  698 + vb->append((const char*)aud_nal, 4);
  699 + // sps
  700 + vb->append(codec->sequenceParameterSetNALUnit, codec->sequenceParameterSetLength);
  701 + }
  702 + if (codec->pictureParameterSetLength > 0) {
  703 + // AnnexB prefix, for pps always 4 bytes header
  704 + vb->append((const char*)aud_nal, 4);
  705 + // pps
  706 + vb->append(codec->pictureParameterSetNALUnit, codec->pictureParameterSetLength);
  707 + }
  708 + }
  709 +
  710 + // 7-9, ignore, @see: ngx_rtmp_hls_video
  711 + if (nal_unit_type >= 7 && nal_unit_type <= 9) {
  712 + continue;
  713 + }
  714 +
  715 + /**
  716 + * step 2:
  717 + * output the "real" sample, in buf.
  718 + * when we output some special assist packets according to nal_unit_type
  719 + */
  720 +
  721 + // sample start prefix, '00 00 00 01' or '00 00 01'
  722 + u_int8_t* p = aud_nal + 1;
  723 + u_int8_t* end = p + 3;
  724 +
  725 + // first AnnexB prefix is long (4 bytes)
  726 + if (vb->length() == 0) {
  727 + p = aud_nal;
  728 + }
  729 + vb->append((const char*)p, end - p);
  730 +
  731 + // sample data
  732 + vb->append(sample_unit->bytes, sample_unit->size);
  733 + }
  734 +
  735 + return ret;
  736 +}
40 737
41 SrsTsEncoder::SrsTsEncoder() 738 SrsTsEncoder::SrsTsEncoder()
42 { 739 {
@@ -37,6 +37,110 @@ class SrsFileWriter; @@ -37,6 +37,110 @@ class SrsFileWriter;
37 class SrsFileReader; 37 class SrsFileReader;
38 class SrsAvcAacCodec; 38 class SrsAvcAacCodec;
39 class SrsCodecSample; 39 class SrsCodecSample;
  40 +class SrsSimpleBuffer;
  41 +
  42 +// @see: ngx_rtmp_SrsMpegtsFrame_t
  43 +class SrsMpegtsFrame
  44 +{
  45 +public:
  46 + int64_t pts;
  47 + int64_t dts;
  48 + int pid;
  49 + int sid;
  50 + int cc;
  51 + bool key;
  52 +
  53 + SrsMpegtsFrame();
  54 +};
  55 +
  56 +/**
  57 +* write data from frame(header info) and buffer(data) to ts file.
  58 +* it's a simple object wrapper for utility from nginx-rtmp: SrsMpegtsWriter
  59 +*/
  60 +class SrsTSMuxer
  61 +{
  62 +private:
  63 + SrsFileWriter* writer;
  64 + std::string path;
  65 +public:
  66 + SrsTSMuxer(SrsFileWriter* w);
  67 + virtual ~SrsTSMuxer();
  68 +public:
  69 + virtual int open(std::string _path);
  70 + virtual int write_audio(SrsMpegtsFrame* af, SrsSimpleBuffer* ab);
  71 + virtual int write_video(SrsMpegtsFrame* vf, SrsSimpleBuffer* vb);
  72 + virtual void close();
  73 +};
  74 +
  75 +/**
  76 +* jitter correct for audio,
  77 +* the sample rate 44100/32000 will lost precise,
  78 +* when mp4/ts(tbn=90000) covert to flv/rtmp(1000),
  79 +* so the Hls on ipad or iphone will corrupt,
  80 +* @see nginx-rtmp: est_pts
  81 +*/
  82 +class SrsTsAacJitter
  83 +{
  84 +private:
  85 + int64_t base_pts;
  86 + int64_t nb_samples;
  87 + int sync_ms;
  88 +public:
  89 + SrsTsAacJitter();
  90 + virtual ~SrsTsAacJitter();
  91 + /**
  92 + * when buffer start, calc the "correct" pts for ts,
  93 + * @param flv_pts, the flv pts calc from flv header timestamp,
  94 + * @param sample_rate, the sample rate in format(flv/RTMP packet header).
  95 + * @param aac_sample_rate, the sample rate in codec(sequence header).
  96 + * @return the calc correct pts.
  97 + */
  98 + virtual int64_t on_buffer_start(int64_t flv_pts, int sample_rate, int aac_sample_rate);
  99 + /**
  100 + * when buffer continue, muxer donot write to file,
  101 + * the audio buffer continue grow and donot need a pts,
  102 + * for the ts audio PES packet only has one pts at the first time.
  103 + */
  104 + virtual void on_buffer_continue();
  105 +};
  106 +
  107 +/**
  108 +* ts stream cache,
  109 +* use to cache ts stream.
  110 +*
  111 +* about the flv tbn problem:
  112 +* flv tbn is 1/1000, ts tbn is 1/90000,
  113 +* when timestamp convert to flv tbn, it will loose precise,
  114 +* so we must gather audio frame together, and recalc the timestamp @see SrsTsAacJitter,
  115 +* we use a aac jitter to correct the audio pts.
  116 +*/
  117 +class SrsTsCache
  118 +{
  119 +public:
  120 + // current frame and buffer
  121 + SrsMpegtsFrame* af;
  122 + SrsSimpleBuffer* ab;
  123 + SrsMpegtsFrame* vf;
  124 + SrsSimpleBuffer* vb;
  125 +protected:
  126 + // time jitter for aac
  127 + SrsTsAacJitter* aac_jitter;
  128 +public:
  129 + SrsTsCache();
  130 + virtual ~SrsTsCache();
  131 +public:
  132 + /**
  133 + * write audio to cache
  134 + */
  135 + virtual int cache_audio(SrsAvcAacCodec* codec, int64_t pts, SrsCodecSample* sample);
  136 + /**
  137 + * write video to muxer.
  138 + */
  139 + virtual int cache_video(SrsAvcAacCodec* codec, int64_t dts, SrsCodecSample* sample);
  140 +private:
  141 + virtual int do_cache_audio(SrsAvcAacCodec* codec, SrsCodecSample* sample);
  142 + virtual int do_cache_video(SrsAvcAacCodec* codec, SrsCodecSample* sample);
  143 +};
40 144
41 /** 145 /**
42 * encode data to ts file. 146 * encode data to ts file.