Browse code

buggy PCR output (just to keep HW decoders happy) - audio and subtitle language support - 'title' stream field sets the service name - fixed TS packet stuffing code - support for subtitle PES packets

Originally committed as revision 4349 to svn://svn.ffmpeg.org/ffmpeg/trunk

Fabrice Bellard authored on 2005/06/03 23:05:41
Showing 1 changed files
... ...
@@ -190,8 +190,10 @@ int mpegts_write_section1(MpegTSSection *s, int tid, int id,
190 190
 /* we retransmit the SI info at this rate */
191 191
 #define SDT_RETRANS_TIME 500
192 192
 #define PAT_RETRANS_TIME 100
193
+#define PCR_RETRANS_TIME 20
193 194
 
194 195
 typedef struct MpegTSWriteStream {
196
+    struct MpegTSService *service;
195 197
     int pid; /* stream associated pid */
196 198
     int cc;
197 199
     int payload_index;
... ...
@@ -201,10 +203,12 @@ typedef struct MpegTSWriteStream {
201 201
 
202 202
 typedef struct MpegTSService {
203 203
     MpegTSSection pmt; /* MPEG2 pmt table context */
204
-    int pcr_pid;
205 204
     int sid;           /* service ID */
206 205
     char *name;
207 206
     char *provider_name;
207
+    int pcr_pid;
208
+    int pcr_packet_count;
209
+    int pcr_packet_freq;
208 210
 } MpegTSService;
209 211
 
210 212
 typedef struct MpegTSWrite {
... ...
@@ -289,6 +293,34 @@ static void mpegts_write_pmt(AVFormatContext *s, MpegTSService *service)
289 289
         q += 2; /* patched after */
290 290
 
291 291
         /* write optional descriptors here */
292
+        switch(st->codec.codec_type) {
293
+        case CODEC_TYPE_AUDIO:
294
+            if (strlen(st->language) == 3) {
295
+                *q++ = 0x0a; /* ISO 639 language descriptor */
296
+                *q++ = 4;
297
+                *q++ = st->language[0];
298
+                *q++ = st->language[1];
299
+                *q++ = st->language[2];
300
+                *q++ = 0; /* undefined type */
301
+            }
302
+            break;
303
+        case CODEC_TYPE_SUBTITLE:
304
+            {
305
+                const char *language;
306
+                language = st->language;
307
+                if (strlen(language) != 3)
308
+                    language = "eng";
309
+                *q++ = 0x59;
310
+                *q++ = 8;
311
+                *q++ = language[0];
312
+                *q++ = language[1];
313
+                *q++ = language[2];
314
+                *q++ = 0x10; /* normal subtitles (0x20 = if hearing pb) */
315
+                put16(&q, 1); /* page id */
316
+                put16(&q, 1); /* ancillary page id */
317
+            }
318
+            break;
319
+        }
292 320
 
293 321
         val = 0xf000 | (q - desc_length_ptr - 2);
294 322
         desc_length_ptr[0] = val >> 8;
... ...
@@ -385,12 +417,16 @@ static int mpegts_write_header(AVFormatContext *s)
385 385
     MpegTSService *service;
386 386
     AVStream *st;
387 387
     int i, total_bit_rate;
388
-
388
+    const char *service_name;
389
+    
389 390
     ts->tsid = DEFAULT_TSID;
390 391
     ts->onid = DEFAULT_ONID;
391 392
     /* allocate a single DVB service */
393
+    service_name = s->title;
394
+    if (service_name[0] == '\0')
395
+        service_name = DEFAULT_SERVICE_NAME;
392 396
     service = mpegts_add_service(ts, DEFAULT_SID, 
393
-                                 DEFAULT_PROVIDER_NAME, DEFAULT_SERVICE_NAME);
397
+                                 DEFAULT_PROVIDER_NAME, service_name);
394 398
     service->pmt.write_packet = section_write_packet;
395 399
     service->pmt.opaque = s;
396 400
 
... ...
@@ -412,16 +448,26 @@ static int mpegts_write_header(AVFormatContext *s)
412 412
         if (!ts_st)
413 413
             goto fail;
414 414
         st->priv_data = ts_st;
415
+        ts_st->service = service;
415 416
         ts_st->pid = DEFAULT_START_PID + i;
416 417
         ts_st->payload_pts = AV_NOPTS_VALUE;
417
-        /* update PCR pid if needed */
418
+        /* update PCR pid by using the first video stream */
418 419
         if (st->codec.codec_type == CODEC_TYPE_VIDEO && 
419 420
             service->pcr_pid == 0x1fff)
420 421
             service->pcr_pid = ts_st->pid;
421 422
         total_bit_rate += st->codec.bit_rate;
422 423
     }
424
+    
425
+    /* if no video stream, use the first stream as PCR */
426
+    if (service->pcr_pid == 0x1fff && s->nb_streams > 0) {
427
+        ts_st = s->streams[0]->priv_data;
428
+        service->pcr_pid = ts_st->pid;
429
+    }
430
+
423 431
     if (total_bit_rate <= 8 * 1024)
424 432
         total_bit_rate = 8 * 1024;
433
+    service->pcr_packet_freq = (total_bit_rate * PCR_RETRANS_TIME) / 
434
+        (TS_PACKET_SIZE * 8 * 1000);
425 435
     ts->sdt_packet_freq = (total_bit_rate * SDT_RETRANS_TIME) / 
426 436
         (TS_PACKET_SIZE * 8 * 1000);
427 437
     ts->pat_packet_freq = (total_bit_rate * PAT_RETRANS_TIME) / 
... ...
@@ -477,12 +523,27 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st,
477 477
     MpegTSWriteStream *ts_st = st->priv_data;
478 478
     uint8_t buf[TS_PACKET_SIZE];
479 479
     uint8_t *q;
480
-    int val, is_start, len, ts_len, header_len;
480
+    int val, is_start, len, header_len, write_pcr, private_code;
481
+    int afc_len, stuffing_len;
482
+    int64_t pcr = -1; /* avoid warning */
481 483
 
482 484
     is_start = 1;
483 485
     while (payload_size > 0) {
484 486
         retransmit_si_info(s);
485 487
 
488
+        write_pcr = 0;
489
+        if (ts_st->pid == ts_st->service->pcr_pid) {
490
+            ts_st->service->pcr_packet_count++;
491
+            if (ts_st->service->pcr_packet_count >= 
492
+                ts_st->service->pcr_packet_freq) {
493
+                ts_st->service->pcr_packet_count = 0;
494
+                write_pcr = 1;
495
+                /* XXX: this is incorrect, but at least we have a PCR
496
+                   value */
497
+                pcr = pts;
498
+            }
499
+        }
500
+
486 501
         /* prepare packet header */
487 502
         q = buf;
488 503
         *q++ = 0x47;
... ...
@@ -491,25 +552,50 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st,
491 491
             val |= 0x40;
492 492
         *q++ = val;
493 493
         *q++ = ts_st->pid;
494
-        *q++ = 0x10 | ts_st->cc;
494
+        *q++ = 0x10 | ts_st->cc | (write_pcr ? 0x20 : 0);
495 495
         ts_st->cc = (ts_st->cc + 1) & 0xf;
496
+        if (write_pcr) {
497
+            *q++ = 7; /* AFC length */
498
+            *q++ = 0x10; /* flags: PCR present */
499
+            *q++ = pcr >> 25;
500
+            *q++ = pcr >> 17;
501
+            *q++ = pcr >> 9;
502
+            *q++ = pcr >> 1;
503
+            *q++ = (pcr & 1) << 7;
504
+            *q++ = 0;
505
+        }
496 506
         if (is_start) {
497 507
             /* write PES header */
498 508
             *q++ = 0x00;
499 509
             *q++ = 0x00;
500 510
             *q++ = 0x01;
501
-            if (st->codec.codec_type == CODEC_TYPE_VIDEO)
511
+            private_code = 0;
512
+            if (st->codec.codec_type == CODEC_TYPE_VIDEO) {
502 513
                 *q++ = 0xe0;
503
-            else
504
-                *q++ = 0xc0;
514
+            } else if (st->codec.codec_type == CODEC_TYPE_AUDIO &&
515
+                       (st->codec.codec_id == CODEC_ID_MP2 ||
516
+                        st->codec.codec_id == CODEC_ID_MP3)) {
517
+                *q++ = 0xc0; 
518
+            } else {
519
+                *q++ = 0xbd;
520
+                if (st->codec.codec_type == CODEC_TYPE_SUBTITLE) {
521
+                    private_code = 0x20;
522
+                }
523
+            }
505 524
             if (pts != AV_NOPTS_VALUE)
506 525
                 header_len = 8;
507 526
             else
508 527
                 header_len = 3;
528
+            if (private_code != 0)
529
+                header_len++;
509 530
             len = payload_size + header_len;
510 531
             *q++ = len >> 8;
511 532
             *q++ = len;
512
-            *q++ = 0x80;
533
+            val = 0x80;
534
+            /* data alignment indicator is required for subtitle data */
535
+            if (st->codec.codec_type == CODEC_TYPE_SUBTITLE)
536
+                val |= 0x04;
537
+            *q++ = val;
513 538
             if (pts != AV_NOPTS_VALUE) {
514 539
                 *q++ = 0x80; /* PTS only */
515 540
                 *q++ = 0x05; /* header len */
... ...
@@ -526,25 +612,42 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st,
526 526
                 *q++ = 0x00;
527 527
                 *q++ = 0x00;
528 528
             }
529
+            if (private_code != 0)
530
+                *q++ = private_code;
529 531
             is_start = 0;
530 532
         }
531
-        /* write header */
532
-        ts_len = q - buf;
533
-        put_buffer(&s->pb, buf, ts_len);
534
-        /* write data */
535
-        len = TS_PACKET_SIZE - ts_len;
533
+        /* header size */
534
+        header_len = q - buf;
535
+        /* data len */
536
+        len = TS_PACKET_SIZE - header_len;
536 537
         if (len > payload_size)
537 538
             len = payload_size;
538
-        put_buffer(&s->pb, payload, len);
539
+        stuffing_len = TS_PACKET_SIZE - header_len - len;
540
+        if (stuffing_len > 0) {
541
+            /* add stuffing with AFC */
542
+            if (buf[3] & 0x20) {
543
+                /* stuffing already present: increase its size */
544
+                afc_len = buf[4] + 1;
545
+                memmove(buf + 4 + afc_len + stuffing_len,
546
+                        buf + 4 + afc_len, 
547
+                        header_len - (4 + afc_len));
548
+                buf[4] += stuffing_len;
549
+                memset(buf + 4 + afc_len, 0xff, stuffing_len);
550
+            } else {
551
+                /* add stuffing */
552
+                memmove(buf + 4 + stuffing_len, buf + 4, header_len - 4);
553
+                buf[3] |= 0x20;
554
+                buf[4] = stuffing_len - 1;
555
+                if (stuffing_len >= 2) {
556
+                    buf[5] = 0x00;
557
+                    memset(buf + 6, 0xff, stuffing_len - 2);
558
+                }
559
+            }
560
+        }
561
+        memcpy(buf + TS_PACKET_SIZE - len, payload, len);
539 562
         payload += len;
540 563
         payload_size -= len;
541
-        ts_len += len;
542
-        /* stuffing */
543
-        len = TS_PACKET_SIZE - ts_len;
544
-        if (len > 0) {
545
-            memset(buf, 0xff, len);
546
-            put_buffer(&s->pb, buf, len);
547
-        }
564
+        put_buffer(&s->pb, buf, TS_PACKET_SIZE);
548 565
     }
549 566
     put_flush_packet(&s->pb);
550 567
 }
... ...
@@ -555,10 +658,17 @@ static int mpegts_write_packet(AVFormatContext *s, AVPacket *pkt)
555 555
     int size= pkt->size;
556 556
     uint8_t *buf= pkt->data;
557 557
     MpegTSWriteStream *ts_st = st->priv_data;
558
-    int len;
558
+    int len, max_payload_size;
559 559
 
560
+    if (st->codec.codec_type == CODEC_TYPE_SUBTITLE) {
561
+        /* for subtitle, a single PES packet must be generated */
562
+        mpegts_write_pes(s, st, buf, size, pkt->pts);
563
+        return 0;
564
+    }
565
+    
566
+    max_payload_size = DEFAULT_PES_PAYLOAD_SIZE;
560 567
     while (size > 0) {
561
-        len = DEFAULT_PES_PAYLOAD_SIZE - ts_st->payload_index;
568
+        len = max_payload_size - ts_st->payload_index;
562 569
         if (len > size)
563 570
             len = size;
564 571
         memcpy(ts_st->payload + ts_st->payload_index, buf, len);
... ...
@@ -567,7 +677,7 @@ static int mpegts_write_packet(AVFormatContext *s, AVPacket *pkt)
567 567
         ts_st->payload_index += len;
568 568
         if (ts_st->payload_pts == AV_NOPTS_VALUE)
569 569
             ts_st->payload_pts = pkt->pts;
570
-        if (ts_st->payload_index >= DEFAULT_PES_PAYLOAD_SIZE) {
570
+        if (ts_st->payload_index >= max_payload_size) {
571 571
             mpegts_write_pes(s, st, ts_st->payload, ts_st->payload_index,
572 572
                              ts_st->payload_pts);
573 573
             ts_st->payload_pts = AV_NOPTS_VALUE;