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

Vignesh Venkatasubramanian vigneshv at google.com
Thu Aug 29 21:28:49 CEST 2013


On Tue, Aug 20, 2013 at 3:13 PM, Vignesh Venkatasubramanian
<vigneshv at google.com> wrote:
> 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
>

Could someone please look into this? Thanks!


More information about the ffmpeg-devel mailing list