diracdec: Move strides to bytes, and pointer types to uint8_t.
[ffmpeg.git] / libavformat / mpegtsenc.c
index 96d277e..055e441 100644 (file)
@@ -230,6 +230,7 @@ typedef struct MpegTSWriteStream {
 
     /* For Opus */
     int opus_queued_samples;
+    int opus_pending_trim_start;
 } MpegTSWriteStream;
 
 static void mpegts_write_pat(AVFormatContext *s)
@@ -296,6 +297,9 @@ static int mpegts_write_pmt(AVFormatContext *s, MpegTSService *service)
         case AV_CODEC_ID_DIRAC:
             stream_type = STREAM_TYPE_VIDEO_DIRAC;
             break;
+        case AV_CODEC_ID_VC1:
+            stream_type = STREAM_TYPE_VIDEO_VC1;
+            break;
         case AV_CODEC_ID_MP2:
         case AV_CODEC_ID_MP3:
             stream_type = STREAM_TYPE_AUDIO_MPEG1;
@@ -397,11 +401,11 @@ static int mpegts_write_pmt(AVFormatContext *s, MpegTSService *service)
 
                         if (st->codec->extradata[19] == st->codec->channels - coupled_stream_counts[st->codec->channels] &&
                             st->codec->extradata[20] == coupled_stream_counts[st->codec->channels] &&
-                            memcmp(&st->codec->extradata[21], channel_map_a[st->codec->channels], st->codec->channels) == 0) {
+                            memcmp(&st->codec->extradata[21], channel_map_a[st->codec->channels-1], st->codec->channels) == 0) {
                             *q++ = st->codec->channels;
                         } else if (st->codec->channels >= 2 && st->codec->extradata[19] == st->codec->channels &&
                                    st->codec->extradata[20] == 0 &&
-                                   memcmp(&st->codec->extradata[21], channel_map_b[st->codec->channels], st->codec->channels) == 0) {
+                                   memcmp(&st->codec->extradata[21], channel_map_b[st->codec->channels-1], st->codec->channels) == 0) {
                             *q++ = st->codec->channels | 0x80;
                         } else {
                             /* Unsupported, could write an extended descriptor here */
@@ -550,6 +554,13 @@ static int mpegts_write_pmt(AVFormatContext *s, MpegTSService *service)
                 *q++ = 'r';
                 *q++ = 'a';
                 *q++ = 'c';
+            } else if (stream_type == STREAM_TYPE_VIDEO_VC1) {
+                *q++ = 0x05; /*MPEG-2 registration descriptor*/
+                *q++ = 4;
+                *q++ = 'V';
+                *q++ = 'C';
+                *q++ = '-';
+                *q++ = '1';
             }
             break;
         case AVMEDIA_TYPE_DATA:
@@ -825,6 +836,9 @@ static int mpegts_write_header(AVFormatContext *s)
             if (ret < 0)
                 goto fail;
         }
+        if (st->codec->codec_id == AV_CODEC_ID_OPUS) {
+            ts_st->opus_pending_trim_start = st->codec->initial_padding * 48000 / st->codec->sample_rate;
+        }
     }
 
     av_freep(&pids);
@@ -838,11 +852,11 @@ static int mpegts_write_header(AVFormatContext *s)
         ts_st = pcr_st->priv_data;
 
     if (ts->mux_rate > 1) {
-        service->pcr_packet_period = (ts->mux_rate * ts->pcr_period) /
+        service->pcr_packet_period = (int64_t)ts->mux_rate * ts->pcr_period /
                                      (TS_PACKET_SIZE * 8 * 1000);
-        ts->sdt_packet_period      = (ts->mux_rate * SDT_RETRANS_TIME) /
+        ts->sdt_packet_period      = (int64_t)ts->mux_rate * SDT_RETRANS_TIME /
                                      (TS_PACKET_SIZE * 8 * 1000);
-        ts->pat_packet_period      = (ts->mux_rate * PAT_RETRANS_TIME) /
+        ts->pat_packet_period      = (int64_t)ts->mux_rate * PAT_RETRANS_TIME /
                                      (TS_PACKET_SIZE * 8 * 1000);
 
         if (ts->copyts < 1)
@@ -1513,17 +1527,38 @@ static int mpegts_write_packet_internal(AVFormatContext *s, AVPacket *pkt)
 
         /* Add Opus control header */
         if ((AV_RB16(pkt->data) >> 5) != 0x3ff) {
+            uint8_t *side_data;
+            int side_data_size;
             int i, n;
+            int ctrl_header_size;
+            int trim_start = 0, trim_end = 0;
 
             opus_samples = opus_get_packet_samples(s, pkt);
 
-            data = av_malloc(pkt->size + 2 + pkt->size / 255 + 1);
+            side_data = av_packet_get_side_data(pkt,
+                                                AV_PKT_DATA_SKIP_SAMPLES,
+                                                &side_data_size);
+
+            if (side_data && side_data_size >= 10) {
+                trim_end = AV_RL32(side_data + 4) * 48000 / st->codec->sample_rate;
+            }
+
+            ctrl_header_size = pkt->size + 2 + pkt->size / 255 + 1;
+            if (ts_st->opus_pending_trim_start)
+              ctrl_header_size += 2;
+            if (trim_end)
+              ctrl_header_size += 2;
+
+            data = av_malloc(ctrl_header_size);
             if (!data)
                 return AVERROR(ENOMEM);
 
-            /* TODO: Write trim if needed */
             data[0] = 0x7f;
             data[1] = 0xe0;
+            if (ts_st->opus_pending_trim_start)
+                data[1] |= 0x10;
+            if (trim_end)
+                data[1] |= 0x08;
 
             n = pkt->size;
             i = 2;
@@ -1535,9 +1570,21 @@ static int mpegts_write_packet_internal(AVFormatContext *s, AVPacket *pkt)
 
             av_assert0(2 + pkt->size / 255 + 1 == i);
 
+            if (ts_st->opus_pending_trim_start) {
+                trim_start = FFMIN(ts_st->opus_pending_trim_start, opus_samples);
+                AV_WB16(data + i, trim_start);
+                i += 2;
+                ts_st->opus_pending_trim_start -= trim_start;
+            }
+            if (trim_end) {
+                trim_end = FFMIN(trim_end, opus_samples - trim_start);
+                AV_WB16(data + i, trim_end);
+                i += 2;
+            }
+
             memcpy(data + i, pkt->data, pkt->size);
             buf     = data;
-            size    = pkt->size + 2 + pkt->size / 255 + 1;
+            size    = ctrl_header_size;
         } else {
             /* TODO: Can we get TS formatted data here? If so we will
              * need to count the samples of that too! */
@@ -1696,7 +1743,7 @@ static const AVOption options[] = {
       offsetof(MpegTSWrite, start_pid), AV_OPT_TYPE_INT,
       { .i64 = 0x0100 }, 0x0020, 0x0f00, AV_OPT_FLAG_ENCODING_PARAM },
     { "mpegts_m2ts_mode", "Enable m2ts mode.",
-      offsetof(MpegTSWrite, m2ts_mode), AV_OPT_TYPE_INT,
+      offsetof(MpegTSWrite, m2ts_mode), AV_OPT_TYPE_BOOL,
       { .i64 = -1 }, -1, 1, AV_OPT_FLAG_ENCODING_PARAM },
     { "muxrate", NULL,
       offsetof(MpegTSWrite, mux_rate), AV_OPT_TYPE_INT,
@@ -1721,13 +1768,13 @@ static const AVOption options[] = {
       offsetof(MpegTSWrite, reemit_pat_pmt), AV_OPT_TYPE_INT,
       { .i64 = 0 }, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM },
     { "mpegts_copyts", "don't offset dts/pts",
-      offsetof(MpegTSWrite, copyts), AV_OPT_TYPE_INT,
+      offsetof(MpegTSWrite, copyts), AV_OPT_TYPE_BOOL,
       { .i64 = -1 }, -1, 1, AV_OPT_FLAG_ENCODING_PARAM },
     { "tables_version", "set PAT, PMT and SDT version",
       offsetof(MpegTSWrite, tables_version), AV_OPT_TYPE_INT,
       { .i64 = 0 }, 0, 31, AV_OPT_FLAG_ENCODING_PARAM },
     { "omit_video_pes_length", "Omit the PES packet length for video packets",
-      offsetof(MpegTSWrite, omit_video_pes_length), AV_OPT_TYPE_INT,
+      offsetof(MpegTSWrite, omit_video_pes_length), AV_OPT_TYPE_BOOL,
       { .i64 = 1 }, 0, 1, AV_OPT_FLAG_ENCODING_PARAM },
     { "pcr_period", "PCR retransmission time",
       offsetof(MpegTSWrite, pcr_period), AV_OPT_TYPE_INT,