Merge commit 'e8049af1325dd59a51546c15b2e71a0f578e9d27'
authorMichael Niedermayer <michaelni@gmx.at>
Thu, 14 Aug 2014 00:11:02 +0000 (02:11 +0200)
committerMichael Niedermayer <michaelni@gmx.at>
Thu, 14 Aug 2014 00:13:46 +0000 (02:13 +0200)
* commit 'e8049af1325dd59a51546c15b2e71a0f578e9d27':
  mpegts: Do not try to write a PMT larger than SECTION_SIZE

Conflicts:
libavformat/mpegtsenc.c

See: 842b6c14bcfc1c5da1a2d288fd65386eb8c158ad
Merged-by: Michael Niedermayer <michaelni@gmx.at>
1  2 
libavformat/mpegtsenc.c

@@@ -251,6 -244,11 +251,11 @@@ static int mpegts_write_pmt(AVFormatCon
          AVStream *st = s->streams[i];
          MpegTSWriteStream *ts_st = st->priv_data;
          AVDictionaryEntry *lang = av_dict_get(st->metadata, "language", NULL, 0);
 -        if (q - data > SECTION_LENGTH - 3 - 2 - 6) {
++        if (q - data > SECTION_LENGTH - 32) {
+             err = 1;
+             break;
+         }
          switch (st->codec->codec_id) {
          case AV_CODEC_ID_MPEG1VIDEO:
          case AV_CODEC_ID_MPEG2VIDEO:
              stream_type = STREAM_TYPE_PRIVATE_DATA;
              break;
          }
-         if (q - data > sizeof(data) - 32)
-             return AVERROR(EINVAL);
 +
          *q++ = stream_type;
          put16(&q, 0xe000 | ts_st->pid);
          desc_length_ptr = q;
              break;
          case AVMEDIA_TYPE_SUBTITLE:
          {
 -            const char *language;
 -            language = lang && strlen(lang->value) == 3 ? lang->value : "eng";
 -            *q++ = 0x59;
 -            *q++ = 8;
 -            *q++ = language[0];
 -            *q++ = language[1];
 -            *q++ = language[2];
 -            *q++ = 0x10; /* normal subtitles (0x20 = if hearing pb) */
 -
 -            if (q - data > SECTION_LENGTH - 4) {
 -                err = 1;
 -                break;
 -            }
 -
 -            if (st->codec->extradata_size == 4) {
 -                memcpy(q, st->codec->extradata, 4);
 -                q += 4;
 -            } else {
 -                put16(&q, 1);     /* page id */
 -                put16(&q, 1);     /* ancillary page id */
 +           const char default_language[] = "und";
 +           const char *language = lang && strlen(lang->value) >= 3 ? lang->value : default_language;
 +
 +           if (st->codec->codec_id == AV_CODEC_ID_DVB_SUBTITLE) {
 +               uint8_t *len_ptr;
 +               int extradata_copied = 0;
 +
 +               *q++ = 0x59; /* subtitling_descriptor */
 +               len_ptr = q++;
 +
-                while (strlen(language) >= 3 && (sizeof(data) - (q - data)) >= 8) { /* 8 bytes per DVB subtitle substream data */
++               while (strlen(language) >= 3) {
++                   if (sizeof(data) - (q - data) < 8) { /* 8 bytes per DVB subtitle substream data */
++                       err = 1;
++                       break;
++                   }
 +                   *q++ = *language++;
 +                   *q++ = *language++;
 +                   *q++ = *language++;
 +                   /* Skip comma */
 +                   if (*language != '\0')
 +                       language++;
 +
 +                   if (st->codec->extradata_size - extradata_copied >= 5) {
 +                       *q++ = st->codec->extradata[extradata_copied + 4]; /* subtitling_type */
 +                       memcpy(q, st->codec->extradata + extradata_copied, 4); /* composition_page_id and ancillary_page_id */
 +                       extradata_copied += 5;
 +                       q += 4;
 +                   } else {
 +                       /* subtitling_type:
 +                        * 0x10 - normal with no monitor aspect ratio criticality
 +                        * 0x20 - for the hard of hearing with no monitor aspect ratio criticality */
 +                       *q++ = (st->disposition & AV_DISPOSITION_HEARING_IMPAIRED) ? 0x20 : 0x10;
 +                       if ((st->codec->extradata_size == 4) && (extradata_copied == 0)) {
 +                           /* support of old 4-byte extradata format */
 +                           memcpy(q, st->codec->extradata, 4); /* composition_page_id and ancillary_page_id */
 +                           extradata_copied += 4;
 +                           q += 4;
 +                       } else {
 +                           put16(&q, 1); /* composition_page_id */
 +                           put16(&q, 1); /* ancillary_page_id */
 +                       }
 +                   }
 +               }
 +
 +               *len_ptr = q - len_ptr - 1;
 +           } else if (st->codec->codec_id == AV_CODEC_ID_DVB_TELETEXT) {
 +               uint8_t *len_ptr = NULL;
 +               int extradata_copied = 0;
 +
 +               /* The descriptor tag. teletext_descriptor */
 +               *q++ = 0x56;
 +               len_ptr = q++;
 +
 +               while (strlen(language) >= 3 && q - data < sizeof(data) - 6) {
 +                   *q++ = *language++;
 +                   *q++ = *language++;
 +                   *q++ = *language++;
 +                   /* Skip comma */
 +                   if (*language != '\0')
 +                       language++;
 +
 +                   if (st->codec->extradata_size - 1 > extradata_copied) {
 +                       memcpy(q, st->codec->extradata + extradata_copied, 2);
 +                       extradata_copied += 2;
 +                       q += 2;
 +                   } else {
 +                       /* The Teletext descriptor:
 +                        * teletext_type: This 5-bit field indicates the type of Teletext page indicated. (0x01 Initial Teletext page)
 +                        * teletext_magazine_number: This is a 3-bit field which identifies the magazine number.
 +                        * teletext_page_number: This is an 8-bit field giving two 4-bit hex digits identifying the page number. */
 +                       *q++ = 0x08;
 +                       *q++ = 0x00;
 +                   }
 +               }
 +
 +               *len_ptr = q - len_ptr - 1;
              }
          }
          break;
          desc_length_ptr[0] = val >> 8;
          desc_length_ptr[1] = val;
      }
 -    mpegts_write_section1(&service->pmt, PMT_TID, service->sid, 0, 0, 0,
+     if (err)
+         av_log(s, AV_LOG_ERROR,
+                "The PMT section cannot fit stream %d and all following streams.\n"
+                "Try reducing the number of languages in the audio streams "
+                "or the total number of streams.\n", i);
 +    mpegts_write_section1(&service->pmt, PMT_TID, service->sid, ts->tables_version, 0, 0,
                            data, q - data);
 +    return 0;
  }
  
  /* NOTE: str == NULL is accepted for an empty string */