[FFmpeg-devel] [PATCH 1/2] opus/matroska: Adding support for DiscardPadding in muxer

Vignesh Venkatasubramanian vigneshv at google.com
Wed Aug 21 00:13:36 CEST 2013


Support for end trimming Opus in Matroska is implemented by using
the DiscardPadding container element in the Block data. The last
chunk is stored as a Block instead of SimpleBlock and the
trimming information is stored and used to discard samples that
were padded by the Opus codec. This patch adds support for muxing
DiscardPadding element into the container with appropriate value.
Matroska spec for the DiscardPadding element can be found here:
http://matroska.org/technical/specs/index.html#DiscardPadding

Signed-off-by: Vignesh Venkatasubramanian <vigneshv at google.com>
---
 libavcodec/avpacket.c     |  2 --
 libavcodec/libopusenc.c   | 12 ++++++++++++
 libavformat/matroska.h    |  1 +
 libavformat/matroskaenc.c | 24 ++++++++++++++++++++++--
 4 files changed, 35 insertions(+), 4 deletions(-)

diff --git a/libavcodec/avpacket.c b/libavcodec/avpacket.c
index 7196c31..ac761f1 100644
--- a/libavcodec/avpacket.c
+++ b/libavcodec/avpacket.c
@@ -225,8 +225,6 @@ int av_copy_packet_side_data(AVPacket *pkt, AVPacket *src)
         int i;
         DUP_DATA(pkt->side_data, src->side_data,
                 src->side_data_elems * sizeof(*src->side_data), 0, ALLOC_MALLOC);
-        memset(pkt->side_data, 0,
-                src->side_data_elems * sizeof(*src->side_data));
         for (i = 0; i < src->side_data_elems; i++) {
             DUP_DATA(pkt->side_data[i].data, src->side_data[i].data,
                     src->side_data[i].size, 1, ALLOC_MALLOC);
diff --git a/libavcodec/libopusenc.c b/libavcodec/libopusenc.c
index 59caac7..775b2ef 100644
--- a/libavcodec/libopusenc.c
+++ b/libavcodec/libopusenc.c
@@ -354,6 +354,18 @@ static int libopus_encode(AVCodecContext *avctx, AVPacket *avpkt,
     ff_af_queue_remove(&opus->afq, opus->opts.packet_size,
                        &avpkt->pts, &avpkt->duration);
 
+    if (opus->opts.packet_size - avpkt->duration > 0) {
+        uint8_t* side_data = av_packet_new_side_data(avpkt,
+                                                     AV_PKT_DATA_SKIP_SAMPLES,
+                                                     10);
+        if(side_data == NULL) {
+            av_free_packet(avpkt);
+            av_free(avpkt);
+            return AVERROR(ENOMEM);
+        }
+        AV_WL32(side_data + 4, opus->opts.packet_size - avpkt->duration);
+    }
+
     *got_packet_ptr = 1;
 
     return 0;
diff --git a/libavformat/matroska.h b/libavformat/matroska.h
index 7cf423c..002fc4c 100644
--- a/libavformat/matroska.h
+++ b/libavformat/matroska.h
@@ -198,6 +198,7 @@
 #define MATROSKA_ID_BLOCKDURATION 0x9B
 #define MATROSKA_ID_BLOCKREFERENCE 0xFB
 #define MATROSKA_ID_CODECSTATE 0xA4
+#define MATROSKA_ID_DISCARDPADDING 0x75A2
 
 /* IDs in the attachments master */
 #define MATROSKA_ID_ATTACHEDFILE        0x61A7
diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c
index 92df6cb..7ad35b5 100644
--- a/libavformat/matroskaenc.c
+++ b/libavformat/matroskaenc.c
@@ -43,6 +43,7 @@
 
 #include "libavcodec/xiph.h"
 #include "libavcodec/mpeg4audio.h"
+#include "libavcodec/internal.h"
 
 typedef struct ebml_master {
     int64_t         pos;                ///< absolute offset in the file where the master's elements start
@@ -1283,7 +1284,7 @@ static void mkv_write_block(AVFormatContext *s, AVIOContext *pb,
     uint8_t *data = NULL, *side_data = NULL;
     int offset = 0, size = pkt->size, side_data_size = 0;
     int64_t ts = mkv->tracks[pkt->stream_index].write_dts ? pkt->dts : pkt->pts;
-    uint64_t additional_id = 0;
+    uint64_t additional_id = 0, discard_padding = 0;
     ebml_master block_group, block_additions, block_more;
 
     av_log(s, AV_LOG_DEBUG, "Writing block at offset %" PRIu64 ", size %d, "
@@ -1309,6 +1310,16 @@ static void mkv_write_block(AVFormatContext *s, AVIOContext *pb,
     }
 
     side_data = av_packet_get_side_data(pkt,
+                                        AV_PKT_DATA_SKIP_SAMPLES,
+                                        &side_data_size);
+
+    if (side_data && side_data_size >= 10) {
+        discard_padding = av_rescale_q(AV_RL32(side_data + 4),
+                                       (AVRational){1, codec->sample_rate},
+                                       (AVRational){1, 1000000000});
+    }
+
+    side_data = av_packet_get_side_data(pkt,
                                         AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL,
                                         &side_data_size);
     if (side_data) {
@@ -1317,7 +1328,7 @@ static void mkv_write_block(AVFormatContext *s, AVIOContext *pb,
         side_data_size -= 8;
     }
 
-    if (side_data_size && additional_id == 1) {
+    if ((side_data_size && additional_id == 1) || discard_padding) {
         block_group = start_ebml_master(pb, MATROSKA_ID_BLOCKGROUP, 0);
         blockid = MATROSKA_ID_BLOCK;
     }
@@ -1331,6 +1342,10 @@ static void mkv_write_block(AVFormatContext *s, AVIOContext *pb,
     if (data != pkt->data)
         av_free(data);
 
+    if (discard_padding) {
+        put_ebml_uint(pb, MATROSKA_ID_DISCARDPADDING, discard_padding);
+    }
+
     if (side_data_size && additional_id == 1) {
         block_additions = start_ebml_master(pb, MATROSKA_ID_BLOCKADDITIONS, 0);
         block_more = start_ebml_master(pb, MATROSKA_ID_BLOCKMORE, 0);
@@ -1340,6 +1355,8 @@ static void mkv_write_block(AVFormatContext *s, AVIOContext *pb,
         avio_write(pb, side_data, side_data_size);
         end_ebml_master(pb, block_more);
         end_ebml_master(pb, block_additions);
+    }
+    if ((side_data_size && additional_id == 1) || discard_padding) {
         end_ebml_master(pb, block_group);
     }
 }
@@ -1556,6 +1573,9 @@ static int mkv_write_packet(AVFormatContext *s, AVPacket *pkt)
             ret = mkv->cur_audio_pkt.buf ? 0 : AVERROR(ENOMEM);
         } else
             ret = av_dup_packet(&mkv->cur_audio_pkt);
+            if (mkv->cur_audio_pkt.side_data_elems > 0) {
+                ret = av_copy_packet_side_data(&mkv->cur_audio_pkt, &mkv->cur_audio_pkt);
+            }
     } else
         ret = mkv_write_packet_internal(s, pkt);
     return ret;
-- 
1.8.3



More information about the ffmpeg-devel mailing list