winlin

for #293, support http ts stream. 2.0.101

@@ -51,369 +51,23 @@ using namespace std; @@ -51,369 +51,23 @@ using namespace std;
51 #include <srs_kernel_file.hpp> 51 #include <srs_kernel_file.hpp>
52 #include <srs_protocol_buffer.hpp> 52 #include <srs_protocol_buffer.hpp>
53 53
54 -// max PES packets size to flush the video.  
55 -#define SRS_AUTO_HLS_AUDIO_CACHE_SIZE 1024 * 1024  
56 -  
57 // drop the segment when duration of ts too small. 54 // drop the segment when duration of ts too small.
58 #define SRS_AUTO_HLS_SEGMENT_MIN_DURATION_MS 100 55 #define SRS_AUTO_HLS_SEGMENT_MIN_DURATION_MS 100
59 56
60 -// @see: NGX_RTMP_HLS_DELAY,  
61 -// 63000: 700ms, ts_tbn=90000  
62 -#define SRS_AUTO_HLS_DELAY 63000  
63 -  
64 -// @see: ngx_rtmp_mpegts_header  
65 -u_int8_t mpegts_header[] = {  
66 - /* TS */  
67 - 0x47, 0x40, 0x00, 0x10, 0x00,  
68 - /* PSI */  
69 - 0x00, 0xb0, 0x0d, 0x00, 0x01, 0xc1, 0x00, 0x00,  
70 - /* PAT */  
71 - 0x00, 0x01, 0xf0, 0x01,  
72 - /* CRC */  
73 - 0x2e, 0x70, 0x19, 0x05,  
74 - /* stuffing 167 bytes */  
75 - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  
76 - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  
77 - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  
78 - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  
79 - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  
80 - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  
81 - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  
82 - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  
83 - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  
84 - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  
85 - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  
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,  
92 -  
93 - /* TS */  
94 - 0x47, 0x50, 0x01, 0x10, 0x00,  
95 - /* PSI */  
96 - 0x02, 0xb0, 0x17, 0x00, 0x01, 0xc1, 0x00, 0x00,  
97 - /* PMT */  
98 - 0xe1, 0x00,  
99 - 0xf0, 0x00,  
100 - // must generate header with/without video, @see:  
101 - // https://github.com/winlinvip/simple-rtmp-server/issues/40  
102 - 0x1b, 0xe1, 0x00, 0xf0, 0x00, /* h264, pid=0x100=256 */  
103 - 0x0f, 0xe1, 0x01, 0xf0, 0x00, /* aac, pid=0x101=257 */  
104 - /*0x03, 0xe1, 0x01, 0xf0, 0x00,*/ /* mp3 */  
105 - /* CRC */  
106 - 0x2f, 0x44, 0xb9, 0x9b, /* crc for aac */  
107 - /*0x4e, 0x59, 0x3d, 0x1e,*/ /* crc for mp3 */  
108 - /* stuffing 157 bytes */  
109 - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  
110 - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  
111 - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  
112 - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  
113 - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  
114 - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  
115 - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  
116 - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  
117 - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  
118 - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  
119 - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  
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  
125 -};  
126 -  
127 -// @see: ngx_rtmp_mpegts.c  
128 -// TODO: support full mpegts feature in future.  
129 -class SrsMpegtsWriter  
130 -{  
131 -public:  
132 - static int write_header(SrsFileWriter* writer)  
133 - {  
134 - int ret = ERROR_SUCCESS;  
135 -  
136 - if ((ret = writer->write(mpegts_header, sizeof(mpegts_header), NULL)) != ERROR_SUCCESS) {  
137 - ret = ERROR_HLS_WRITE_FAILED;  
138 - srs_error("write ts file header failed. ret=%d", ret);  
139 - return ret;  
140 - }  
141 -  
142 - return ret;  
143 - }  
144 - static int write_frame(SrsFileWriter* writer, SrsMpegtsFrame* frame, SrsSimpleBuffer* buffer)  
145 - {  
146 - int ret = ERROR_SUCCESS;  
147 -  
148 - if (!buffer->bytes() || buffer->length() <= 0) {  
149 - return ret;  
150 - }  
151 -  
152 - char* last = buffer->bytes() + buffer->length();  
153 - char* pos = buffer->bytes();  
154 -  
155 - bool first = true;  
156 - while (pos < last) {  
157 - static char packet[188];  
158 - char* p = packet;  
159 -  
160 - frame->cc++;  
161 -  
162 - // sync_byte; //8bits  
163 - *p++ = 0x47;  
164 - // pid; //13bits  
165 - *p++ = (frame->pid >> 8) & 0x1f;  
166 - // payload_unit_start_indicator; //1bit  
167 - if (first) {  
168 - p[-1] |= 0x40;  
169 - }  
170 - *p++ = frame->pid;  
171 -  
172 - // transport_scrambling_control; //2bits  
173 - // adaption_field_control; //2bits, 0x01: PayloadOnly  
174 - // continuity_counter; //4bits  
175 - *p++ = 0x10 | (frame->cc & 0x0f);  
176 -  
177 - if (first) {  
178 - first = false;  
179 - if (frame->key) {  
180 - p[-1] |= 0x20; // Both Adaption and Payload  
181 - *p++ = 7; // size  
182 - *p++ = 0x50; // random access + PCR  
183 - p = write_pcr(p, frame->dts - SRS_AUTO_HLS_DELAY);  
184 - }  
185 -  
186 - // PES header  
187 - // packet_start_code_prefix; //24bits, '00 00 01'  
188 - *p++ = 0x00;  
189 - *p++ = 0x00;  
190 - *p++ = 0x01;  
191 - //8bits  
192 - *p++ = frame->sid;  
193 -  
194 - // pts(33bits) need 5bytes.  
195 - u_int8_t header_size = 5;  
196 - u_int8_t flags = 0x80; // pts  
197 -  
198 - // dts(33bits) need 5bytes also  
199 - if (frame->dts != frame->pts) {  
200 - header_size += 5;  
201 - flags |= 0x40; // dts  
202 - }  
203 -  
204 - // 3bytes: flag fields from PES_packet_length to PES_header_data_length  
205 - int pes_size = (last - pos) + header_size + 3;  
206 - if (pes_size > 0xffff) {  
207 - /**  
208 - * when actual packet length > 0xffff(65535),  
209 - * which exceed the max u_int16_t packet length,  
210 - * use 0 packet length, the next unit start indicates the end of packet.  
211 - */  
212 - pes_size = 0;  
213 - }  
214 -  
215 - // PES_packet_length; //16bits  
216 - *p++ = (pes_size >> 8);  
217 - *p++ = pes_size;  
218 -  
219 - // PES_scrambling_control; //2bits, '10'  
220 - // PES_priority; //1bit  
221 - // data_alignment_indicator; //1bit  
222 - // copyright; //1bit  
223 - // original_or_copy; //1bit  
224 - *p++ = 0x80; /* H222 */  
225 -  
226 - // PTS_DTS_flags; //2bits  
227 - // ESCR_flag; //1bit  
228 - // ES_rate_flag; //1bit  
229 - // DSM_trick_mode_flag; //1bit  
230 - // additional_copy_info_flag; //1bit  
231 - // PES_CRC_flag; //1bit  
232 - // PES_extension_flag; //1bit  
233 - *p++ = flags;  
234 -  
235 - // PES_header_data_length; //8bits  
236 - *p++ = header_size;  
237 -  
238 - // pts; // 33bits  
239 - p = write_pts(p, flags >> 6, frame->pts + SRS_AUTO_HLS_DELAY);  
240 -  
241 - // dts; // 33bits  
242 - if (frame->dts != frame->pts) {  
243 - p = write_pts(p, 1, frame->dts + SRS_AUTO_HLS_DELAY);  
244 - }  
245 - }  
246 -  
247 - int body_size = sizeof(packet) - (p - packet);  
248 - int in_size = last - pos;  
249 -  
250 - if (body_size <= in_size) {  
251 - memcpy(p, pos, body_size);  
252 - pos += body_size;  
253 - } else {  
254 - p = fill_stuff(p, packet, body_size, in_size);  
255 - memcpy(p, pos, in_size);  
256 - pos = last;  
257 - }  
258 -  
259 - // write ts packet  
260 - if ((ret = writer->write(packet, sizeof(packet), NULL)) != ERROR_SUCCESS) {  
261 - ret = ERROR_HLS_WRITE_FAILED;  
262 - srs_error("write ts file failed. ret=%d", ret);  
263 - return ret;  
264 - }  
265 - }  
266 -  
267 - return ret;  
268 - }  
269 -private:  
270 - static char* fill_stuff(char* pes_body_end, char* packet, int body_size, int in_size)  
271 - {  
272 - char* p = pes_body_end;  
273 -  
274 - // insert the stuff bytes before PES body  
275 - int stuff_size = (body_size - in_size);  
276 -  
277 - // adaption_field_control; //2bits  
278 - if (packet[3] & 0x20) {  
279 - // has adaptation  
280 - // packet[4]: adaption_field_length  
281 - // packet[5]: adaption field data  
282 - // base: start of PES body  
283 - char* base = &packet[5] + packet[4];  
284 - int len = p - base;  
285 - p = (char*)memmove(base + stuff_size, base, len) + len;  
286 - // increase the adaption field size.  
287 - packet[4] += stuff_size;  
288 -  
289 - return p;  
290 - }  
291 -  
292 - // create adaption field.  
293 - // adaption_field_control; //2bits  
294 - packet[3] |= 0x20;  
295 - // base: start of PES body  
296 - char* base = &packet[4];  
297 - int len = p - base;  
298 - p = (char*)memmove(base + stuff_size, base, len) + len;  
299 - // adaption_field_length; //8bits  
300 - packet[4] = (stuff_size - 1);  
301 - if (stuff_size >= 2) {  
302 - // adaption field flags.  
303 - packet[5] = 0;  
304 - // adaption data.  
305 - if (stuff_size > 2) {  
306 - memset(&packet[6], 0xff, stuff_size - 2);  
307 - }  
308 - }  
309 -  
310 - return p;  
311 - }  
312 - static char* write_pcr(char* p, int64_t pcr)  
313 - {  
314 - // the pcr=dts-delay  
315 - // and the pcr maybe negative  
316 - // @see https://github.com/winlinvip/simple-rtmp-server/issues/268  
317 - int64_t v = srs_max(0, pcr);  
318 -  
319 - *p++ = (char) (v >> 25);  
320 - *p++ = (char) (v >> 17);  
321 - *p++ = (char) (v >> 9);  
322 - *p++ = (char) (v >> 1);  
323 - *p++ = (char) (v << 7 | 0x7e);  
324 - *p++ = 0;  
325 -  
326 - return p;  
327 - }  
328 - static char* write_pts(char* p, u_int8_t fb, int64_t pts)  
329 - {  
330 - int32_t val;  
331 -  
332 - val = fb << 4 | (((pts >> 30) & 0x07) << 1) | 1;  
333 - *p++ = val;  
334 -  
335 - val = (((pts >> 15) & 0x7fff) << 1) | 1;  
336 - *p++ = (val >> 8);  
337 - *p++ = val;  
338 -  
339 - val = (((pts) & 0x7fff) << 1) | 1;  
340 - *p++ = (val >> 8);  
341 - *p++ = val;  
342 -  
343 - return p;  
344 - }  
345 -};  
346 -  
347 -SrsTSMuxer::SrsTSMuxer()  
348 -{  
349 - writer = new SrsFileWriter();  
350 -}  
351 -  
352 -SrsTSMuxer::~SrsTSMuxer()  
353 -{  
354 - close();  
355 - srs_freep(writer);  
356 -}  
357 -  
358 -int SrsTSMuxer::open(string _path)  
359 -{  
360 - int ret = ERROR_SUCCESS;  
361 -  
362 - path = _path;  
363 -  
364 - close();  
365 -  
366 - if ((ret = writer->open(path)) != ERROR_SUCCESS) {  
367 - return ret;  
368 - }  
369 -  
370 - // write mpegts header  
371 - if ((ret = SrsMpegtsWriter::write_header(writer)) != ERROR_SUCCESS) {  
372 - return ret;  
373 - }  
374 -  
375 - return ret;  
376 -}  
377 -  
378 -int SrsTSMuxer::write_audio(SrsMpegtsFrame* af, SrsSimpleBuffer* ab)  
379 -{  
380 - int ret = ERROR_SUCCESS;  
381 -  
382 - if ((ret = SrsMpegtsWriter::write_frame(writer, af, ab)) != ERROR_SUCCESS) {  
383 - return ret;  
384 - }  
385 -  
386 - return ret;  
387 -}  
388 -  
389 -int SrsTSMuxer::write_video(SrsMpegtsFrame* vf, SrsSimpleBuffer* vb)  
390 -{  
391 - int ret = ERROR_SUCCESS;  
392 -  
393 - if ((ret = SrsMpegtsWriter::write_frame(writer, vf, vb)) != ERROR_SUCCESS) {  
394 - return ret;  
395 - }  
396 -  
397 - return ret;  
398 -}  
399 -  
400 -void SrsTSMuxer::close()  
401 -{  
402 - writer->close();  
403 -}  
404 -  
405 SrsHlsSegment::SrsHlsSegment() 57 SrsHlsSegment::SrsHlsSegment()
406 { 58 {
407 duration = 0; 59 duration = 0;
408 sequence_no = 0; 60 sequence_no = 0;
409 - muxer = new SrsTSMuxer();  
410 segment_start_dts = 0; 61 segment_start_dts = 0;
411 is_sequence_header = false; 62 is_sequence_header = false;
  63 + writer = new SrsFileWriter();
  64 + muxer = new SrsTSMuxer(writer);
412 } 65 }
413 66
414 SrsHlsSegment::~SrsHlsSegment() 67 SrsHlsSegment::~SrsHlsSegment()
415 { 68 {
416 srs_freep(muxer); 69 srs_freep(muxer);
  70 + srs_freep(writer);
417 } 71 }
418 72
419 void SrsHlsSegment::update_duration(int64_t current_frame_dts) 73 void SrsHlsSegment::update_duration(int64_t current_frame_dts)
@@ -926,6 +580,7 @@ int SrsHlsCache::write_audio(SrsAvcAacCodec* codec, SrsHlsMuxer* muxer, int64_t @@ -926,6 +580,7 @@ int SrsHlsCache::write_audio(SrsAvcAacCodec* codec, SrsHlsMuxer* muxer, int64_t
926 return ret; 580 return ret;
927 } 581 }
928 } 582 }
  583 +
929 // TODO: config it. 584 // TODO: config it.
930 // in ms, audio delay to flush the audios. 585 // in ms, audio delay to flush the audios.
931 int64_t audio_delay = SRS_CONF_DEFAULT_AAC_DELAY; 586 int64_t audio_delay = SRS_CONF_DEFAULT_AAC_DELAY;
@@ -53,25 +53,6 @@ class SrsTsAacJitter; @@ -53,25 +53,6 @@ class SrsTsAacJitter;
53 class SrsTsCache; 53 class SrsTsCache;
54 54
55 /** 55 /**
56 -* write data from frame(header info) and buffer(data) to ts file.  
57 -* it's a simple object wrapper for utility from nginx-rtmp: SrsMpegtsWriter  
58 -*/  
59 -class SrsTSMuxer  
60 -{  
61 -private:  
62 - SrsFileWriter* writer;  
63 - std::string path;  
64 -public:  
65 - SrsTSMuxer();  
66 - virtual ~SrsTSMuxer();  
67 -public:  
68 - virtual int open(std::string _path);  
69 - virtual int write_audio(SrsMpegtsFrame* af, SrsSimpleBuffer* ab);  
70 - virtual int write_video(SrsMpegtsFrame* vf, SrsSimpleBuffer* vb);  
71 - virtual void close();  
72 -};  
73 -  
74 -/**  
75 * the wrapper of m3u8 segment from specification: 56 * the wrapper of m3u8 segment from specification:
76 * 57 *
77 * 3.3.2. EXTINF 58 * 3.3.2. EXTINF
@@ -89,6 +70,7 @@ public: @@ -89,6 +70,7 @@ public:
89 // ts full file to write. 70 // ts full file to write.
90 std::string full_path; 71 std::string full_path;
91 // the muxer to write ts. 72 // the muxer to write ts.
  73 + SrsFileWriter* writer;
92 SrsTSMuxer* muxer; 74 SrsTSMuxer* muxer;
93 // current segment start dts for m3u8 75 // current segment start dts for m3u8
94 int64_t segment_start_dts; 76 int64_t segment_start_dts;
@@ -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 101 34 +#define VERSION_REVISION 102
35 35
36 // server info. 36 // server info.
37 #define RTMP_SIG_SRS_KEY "SRS" 37 #define RTMP_SIG_SRS_KEY "SRS"
@@ -28,6 +28,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -28,6 +28,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 #include <srs_kernel_stream.hpp> 28 #include <srs_kernel_stream.hpp>
29 #include <srs_kernel_utility.hpp> 29 #include <srs_kernel_utility.hpp>
30 #include <srs_kernel_buffer.hpp> 30 #include <srs_kernel_buffer.hpp>
  31 +#include <srs_kernel_file.hpp>
  32 +
  33 +using namespace std;
31 34
32 // in ms, for HLS aac sync time. 35 // in ms, for HLS aac sync time.
33 #define SRS_CONF_DEFAULT_AAC_SYNC 100 36 #define SRS_CONF_DEFAULT_AAC_SYNC 100
@@ -65,6 +68,294 @@ int aac_sample_rates[] = @@ -65,6 +68,294 @@ int aac_sample_rates[] =
65 7350, 0, 0, 0 68 7350, 0, 0, 0
66 }; 69 };
67 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 +
68 SrsMpegtsFrame::SrsMpegtsFrame() 359 SrsMpegtsFrame::SrsMpegtsFrame()
69 { 360 {
70 pts = dts = 0; 361 pts = dts = 0;
@@ -72,6 +363,63 @@ SrsMpegtsFrame::SrsMpegtsFrame() @@ -72,6 +363,63 @@ SrsMpegtsFrame::SrsMpegtsFrame()
72 key = false; 363 key = false;
73 } 364 }
74 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 +
75 SrsTsAacJitter::SrsTsAacJitter() 423 SrsTsAacJitter::SrsTsAacJitter()
76 { 424 {
77 base_pts = 0; 425 base_pts = 0;
@@ -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 +#include <string>
  34 +
33 #include <srs_kernel_codec.hpp> 35 #include <srs_kernel_codec.hpp>
34 36
35 class SrsStream; 37 class SrsStream;
@@ -37,6 +39,7 @@ class SrsMpegtsFrame; @@ -37,6 +39,7 @@ class SrsMpegtsFrame;
37 class SrsSimpleBuffer; 39 class SrsSimpleBuffer;
38 class SrsAvcAacCodec; 40 class SrsAvcAacCodec;
39 class SrsCodecSample; 41 class SrsCodecSample;
  42 +class SrsFileWriter;
40 43
41 /** 44 /**
42 * the public data, event HLS disable, others can use it. 45 * the public data, event HLS disable, others can use it.
@@ -57,6 +60,9 @@ extern int aac_sample_rates[]; @@ -57,6 +60,9 @@ extern int aac_sample_rates[];
57 // in ms, for HLS aac flush the audio 60 // in ms, for HLS aac flush the audio
58 #define SRS_CONF_DEFAULT_AAC_DELAY 100 61 #define SRS_CONF_DEFAULT_AAC_DELAY 100
59 62
  63 +// max PES packets size to flush the video.
  64 +#define SRS_AUTO_HLS_AUDIO_CACHE_SIZE 1024 * 1024
  65 +
60 /** 66 /**
61 * the FLV/RTMP supported audio sample size. 67 * the FLV/RTMP supported audio sample size.
62 * Size of each audio sample. This parameter only pertains to 68 * Size of each audio sample. This parameter only pertains to
@@ -104,6 +110,25 @@ public: @@ -104,6 +110,25 @@ public:
104 }; 110 };
105 111
106 /** 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 +/**
107 * jitter correct for audio, 132 * jitter correct for audio,
108 * the sample rate 44100/32000 will lost precise, 133 * the sample rate 44100/32000 will lost precise,
109 * when mp4/ts(tbn=90000) covert to flv/rtmp(1000), 134 * when mp4/ts(tbn=90000) covert to flv/rtmp(1000),
@@ -36,18 +36,23 @@ using namespace std; @@ -36,18 +36,23 @@ using namespace std;
36 #include <srs_kernel_error.hpp> 36 #include <srs_kernel_error.hpp>
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 40
40 SrsTsEncoder::SrsTsEncoder() 41 SrsTsEncoder::SrsTsEncoder()
41 { 42 {
42 _fs = NULL; 43 _fs = NULL;
43 codec = new SrsAvcAacCodec(); 44 codec = new SrsAvcAacCodec();
44 sample = new SrsCodecSample(); 45 sample = new SrsCodecSample();
  46 + cache = new SrsTsCache();
  47 + muxer = NULL;
45 } 48 }
46 49
47 SrsTsEncoder::~SrsTsEncoder() 50 SrsTsEncoder::~SrsTsEncoder()
48 { 51 {
49 srs_freep(codec); 52 srs_freep(codec);
50 srs_freep(sample); 53 srs_freep(sample);
  54 + srs_freep(cache);
  55 + srs_freep(muxer);
51 } 56 }
52 57
53 int SrsTsEncoder::initialize(SrsFileWriter* fs) 58 int SrsTsEncoder::initialize(SrsFileWriter* fs)
@@ -64,6 +69,13 @@ int SrsTsEncoder::initialize(SrsFileWriter* fs) @@ -64,6 +69,13 @@ int SrsTsEncoder::initialize(SrsFileWriter* fs)
64 69
65 _fs = fs; 70 _fs = fs;
66 71
  72 + srs_freep(muxer);
  73 + muxer = new SrsTSMuxer(fs);
  74 +
  75 + if ((ret = muxer->open("")) != ERROR_SUCCESS) {
  76 + return ret;
  77 + }
  78 +
67 return ret; 79 return ret;
68 } 80 }
69 81
@@ -91,10 +103,20 @@ int SrsTsEncoder::write_audio(int64_t timestamp, char* data, int size) @@ -91,10 +103,20 @@ int SrsTsEncoder::write_audio(int64_t timestamp, char* data, int size)
91 // for the packet is filtered by consumer. 103 // for the packet is filtered by consumer.
92 int64_t dts = timestamp * 90; 104 int64_t dts = timestamp * 90;
93 105
94 - /*if ((ret = hls_cache->write_audio(codec, muxer, dts, sample)) != ERROR_SUCCESS) {  
95 - srs_error("http: ts cache write audio failed. ret=%d", ret); 106 + // write audio to cache.
  107 + if ((ret = cache->cache_audio(codec, dts, sample)) != ERROR_SUCCESS) {
96 return ret; 108 return ret;
97 - }*/ 109 + }
  110 +
  111 + // flush if buffer exceed max size.
  112 + if (cache->ab->length() > SRS_AUTO_HLS_AUDIO_CACHE_SIZE) {
  113 + if ((ret = muxer->write_audio(cache->af, cache->ab)) != ERROR_SUCCESS) {
  114 + return ret;
  115 + }
  116 +
  117 + // write success, clear and free the buffer
  118 + cache->ab->erase(cache->ab->length());
  119 + }
98 120
99 return ret; 121 return ret;
100 } 122 }
@@ -126,10 +148,18 @@ int SrsTsEncoder::write_video(int64_t timestamp, char* data, int size) @@ -126,10 +148,18 @@ int SrsTsEncoder::write_video(int64_t timestamp, char* data, int size)
126 } 148 }
127 149
128 int64_t dts = timestamp * 90; 150 int64_t dts = timestamp * 90;
129 - /*if ((ret = hls_cache->write_video(codec, muxer, dts, sample)) != ERROR_SUCCESS) {  
130 - srs_error("http: ts cache write video failed. ret=%d", ret); 151 +
  152 + // write video to cache.
  153 + if ((ret = cache->cache_video(codec, dts, sample)) != ERROR_SUCCESS) {
  154 + return ret;
  155 + }
  156 +
  157 + if ((ret = muxer->write_video(cache->vf, cache->vb)) != ERROR_SUCCESS) {
131 return ret; 158 return ret;
132 - }*/ 159 + }
  160 +
  161 + // write success, clear and free the buffer
  162 + cache->vb->erase(cache->vb->length());
133 163
134 return ret; 164 return ret;
135 } 165 }
@@ -31,6 +31,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -31,6 +31,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 31
32 #include <string> 32 #include <string>
33 33
  34 +class SrsTsCache;
  35 +class SrsTSMuxer;
34 class SrsFileWriter; 36 class SrsFileWriter;
35 class SrsFileReader; 37 class SrsFileReader;
36 class SrsAvcAacCodec; 38 class SrsAvcAacCodec;
@@ -46,6 +48,8 @@ private: @@ -46,6 +48,8 @@ private:
46 private: 48 private:
47 SrsAvcAacCodec* codec; 49 SrsAvcAacCodec* codec;
48 SrsCodecSample* sample; 50 SrsCodecSample* sample;
  51 + SrsTsCache* cache;
  52 + SrsTSMuxer* muxer;
49 public: 53 public:
50 SrsTsEncoder(); 54 SrsTsEncoder();
51 virtual ~SrsTsEncoder(); 55 virtual ~SrsTsEncoder();