[FFmpeg-devel] [PATCH v2] Interpretation of duration field in AVI super index chunk

Tobias Rapp t.rapp at noa-audio.com
Tue Mar 3 14:45:24 CET 2015


On 26.02.2015 15:41, Michael Niedermayer wrote:
> On Thu, Feb 26, 2015 at 02:14:33PM +0100, Tobias Rapp wrote:
>> On 26.02.2015 00:51, Michael Niedermayer wrote:
>>> On Wed, Feb 25, 2015 at 05:35:33PM +0100, Tobias Rapp wrote:
[...]
>>>> @@ -511,7 +514,11 @@ static int avi_write_ix(AVFormatContext *s)
>>>>           avio_skip(pb, 16 * avi->riff_id);
>>>>           avio_wl64(pb, ix);                    /* qwOffset */
>>>>           avio_wl32(pb, pos - ix);              /* dwSize */
>>>> -        avio_wl32(pb, avist->indexes.entry);  /* dwDuration */
>>>> +        ff_parse_specific_params(s->streams[i], &au_byterate, &au_ssize, &au_scale);
>>>> +        if (au_ssize == 0)
>>>> +            avio_wl32(pb, avist->indexes.entry);  /* dwDuration (packet count) */
>>>> +        else
>>>
>>>> +            avio_wl32(pb, (avist->audio_strm_length - avist->indexes.audio_strm_offset) / au_ssize);  /* dwDuration (sample count) */
>>>
>>> the rounding here is wrong
>>> the index to be useable needs to have segments duration summable
>>> as is this would lead to significangt errors if many of these
>>> durations would be summed up
>>> something like
>>> avist->audio_strm_length / au_ssize - avist->indexes.audio_strm_offset / au_ssize
>>> might avoid that but ive not tested it
>>
>> My assumption was that a stream packet contains only whole samples
>> for linear/uncompressed audio (PCM) and that only for linear audio
>> the expression "au_ssize > 0" evaluates to TRUE.
>
> We try to use au_ssize = 0 for compressed audio but i think it can be
> non zero in some stream copy cases, iam not 100% sure though
>
>
>>
>> If that is not the case I can do the rounding as suggested or maybe
>> introduce some separate stream duration counter based on
>> AVPacket.duration?
>
> i think best to keep it simple and maybe print a request for a sample/
> testcase if some combination of parameters is found which we are
> unsure about if it works correctly
>

Attached a new patch that calls avpriv_request_sample if the audio 
segment size is no multiple of au_ssize. Tested different audio encoder 
types (pcm_s16le, pcm_s24le, adpcm_ms, mp2, libmp3lame) with success.

Regards,
Tobias
-------------- next part --------------
>From 89d3f13169e2ff183a1e60c9939263035ad83a0f Mon Sep 17 00:00:00 2001
From: Tobias Rapp <t.rapp at noa-audio.com>
Date: Tue, 3 Mar 2015 13:29:05 +0100
Subject: [PATCH] libavformat/avienc: Fix duration of audio segment in OpenDML
 master index

Fixes the duration field of the OpenDML master index "indx" chunk to
contain the number of samples instead of the number of packets for
(linear/PCM) audio streams.

This matches the OpenDML V1.02 standard text which states that the
duration field shall contain "time span in stream ticks".
---
 libavformat/avienc.c | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/libavformat/avienc.c b/libavformat/avienc.c
index 53c2fe7..3b5e5c4 100644
--- a/libavformat/avienc.c
+++ b/libavformat/avienc.c
@@ -49,6 +49,7 @@ typedef struct AVIIentry {
 
 typedef struct AVIIndex {
     int64_t     indx_start;
+    int64_t     audio_strm_offset;
     int         entry;
     int         ents_allocated;
     AVIIentry** cluster;
@@ -66,6 +67,7 @@ typedef struct AVIStream {
     int packet_count;
     int entry;
     int max_size;
+    int sample_requested;
 
     int64_t last_dts;
 
@@ -91,6 +93,7 @@ static int64_t avi_start_new_riff(AVFormatContext *s, AVIOContext *pb,
     avi->riff_id++;
     for (i = 0; i < s->nb_streams; i++) {
         AVIStream *avist = s->streams[i]->priv_data;
+        avist->indexes.audio_strm_offset = avist->audio_strm_length;
         avist->indexes.entry = 0;
     }
 
@@ -476,6 +479,7 @@ static int avi_write_ix(AVFormatContext *s)
     for (i = 0; i < s->nb_streams; i++) {
         AVIStream *avist = s->streams[i]->priv_data;
         int64_t ix, pos;
+        int au_byterate, au_ssize, au_scale;
 
         avi_stream2fourcc(tag, i, s->streams[i]->codec->codec_type);
         ix_tag[3] = '0' + i;
@@ -511,7 +515,16 @@ static int avi_write_ix(AVFormatContext *s)
         avio_skip(pb, 16 * avi->riff_id);
         avio_wl64(pb, ix);                    /* qwOffset */
         avio_wl32(pb, pos - ix);              /* dwSize */
-        avio_wl32(pb, avist->indexes.entry);  /* dwDuration */
+        ff_parse_specific_params(s->streams[i], &au_byterate, &au_ssize, &au_scale);
+        if (s->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO && au_ssize > 0) {
+            uint32_t audio_segm_size = (avist->audio_strm_length - avist->indexes.audio_strm_offset);
+            if ((audio_segm_size % au_ssize > 0) && !avist->sample_requested) {
+                avpriv_request_sample(s, "OpenDML index duration for audio packets with partial frames");
+                avist->sample_requested = 1;
+            }
+            avio_wl32(pb, audio_segm_size / au_ssize);  /* dwDuration (sample count) */
+        } else
+            avio_wl32(pb, avist->indexes.entry);  /* dwDuration (packet count) */
 
         avio_seek(pb, pos, SEEK_SET);
     }
-- 
1.9.1



More information about the ffmpeg-devel mailing list