[FFmpeg-devel] [PATCH] WMA Lossless: reset channel residues between subframes

Jakub Stachowski qbast at go2.pl
Sun Apr 15 13:16:48 CEST 2012


W dniu 2012-04-14 21:30, Jakub Stachowski pisze:
> W dniu 2012-04-14 21:04, Mashiat Sarker Shakkhar pisze:
>> On 4/15/2012 12:38 AM, Jakub Stachowski wrote:
>> [...]
>>> For first test I used WMA file from bug #1055:
>>> Decoded with dBpoweramp or Microsoft's wmal2pcm.exe I got 1410612
>>> samples.
>>> Decoded with ffmpeg (without taking skip value): 1413120
>>> During decoding last frame, get_bits1() returned 460 samples to skip.
>>> Difference is 2048+460 samples, so it should skip one full frame (I
>>> wonder which one) and 460 from last one?
>>
>> Are you just assuming that samples_per_frame = 2048 or did you check?
>>
>
> I checked. I don't think I have seen any file with different value.
>
>>>
>>> Next test: hand-crafted file with 15000 samples. All of them zeros apart
>>> from last 14 bytes, then encoded with MS Expression Encoder
>>> wmal2pcm.exe decoded it perfectly
>>> ffmpeg after taking skip value into account also created file with right
>>> length, however all samples were 0 (last 14 non-zero bytes got
>>> destroyed).
>>
>> Why don't you share your WIP patch or git tree with us? If possible do
>> share the samples too.
>
> Sure. Patches and my sample (the one used in second test) attached.
> Sample used in first test you can download from
> https://ffmpeg.org/trac/ffmpeg/attachment/ticket/1055/03_Track_3.wma
>>

Wrong output with my 15000 sample file was bug in a patch (wrong way of 
counting written samples). Attached is better one.
It does not fix problem with 03_Track_3.wma though.

>>>
>>> So it is step in right direction, but not completely correct yet.
>>
>> I'd say you are stepping in the right direction. May be there are quirks
>> that we are not aware of. It's easy enough to compare the bitstream
>> reads with refcode. Share your code so that I can test.
>
>
>
>>
>> Regards
>> Shakkhar
>>
>> [...]
>> _______________________________________________
>> ffmpeg-devel mailing list
>> ffmpeg-devel at ffmpeg.org
>> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>>
>
>
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

-------------- next part --------------
>From a0519477b855a1fa1f753b2753c5f03edf917359 Mon Sep 17 00:00:00 2001
From: Jakub Stachowski <qbast at go2.pl>
Date: Sun, 15 Apr 2012 13:10:00 +0200
Subject: [PATCH] Better version of patch to skip samples in last frame

---
 libavcodec/wmalosslessdec.c |   43 ++++++++++++++++++++++++++-----------------
 1 files changed, 26 insertions(+), 17 deletions(-)

diff --git a/libavcodec/wmalosslessdec.c b/libavcodec/wmalosslessdec.c
index 075c023..c70a895 100644
--- a/libavcodec/wmalosslessdec.c
+++ b/libavcodec/wmalosslessdec.c
@@ -838,7 +838,7 @@ static int decode_subframe(WmallDecodeCtx *s)
 {
     int offset        = s->samples_per_frame;
     int subframe_len  = s->samples_per_frame;
-    int total_samples = s->samples_per_frame * s->num_channels;
+    int total_samples = s->frame.nb_samples * s->num_channels;
     int i, j, rawpcm_tile, padding_zeroes, res;
 
     s->subframe_offset = get_bits_count(&s->gb);
@@ -874,7 +874,7 @@ static int decode_subframe(WmallDecodeCtx *s)
 
     /* check if the frame will be complete after processing the
         estimated block */
-    if (!total_samples)
+    if (total_samples <=0 )
         s->parsed_all_subframes = 1;
 
 
@@ -977,10 +977,18 @@ static int decode_subframe(WmallDecodeCtx *s)
 
     /* Write to proper output buffer depending on bit-depth */
     for (i = 0; i < s->channels_for_cur_subframe; i++) {
+        int already_written;
         int c = s->channel_indexes_for_cur_subframe[i];
+
+        if (s->bits_per_sample == 16) 
+           already_written = (s->samples_16[c] - ((int16_t *)s->frame.data[0] + c)) / s->num_channels;
+        else
+           already_written = (s->samples_32[c] - ((int32_t *)s->frame.data[0] + c)) / s->num_channels;
+
         int subframe_len = s->channel[c].subframe_len[s->channel[c].cur_subframe];
+        int to_write = FFMIN(subframe_len, s->frame.nb_samples - already_written);
 
-        for (j = 0; j < subframe_len; j++) {
+        for (j = 0; j < to_write; j++) {
             if (s->bits_per_sample == 16) {
                 *s->samples_16[c] = (int16_t) s->channel_residues[c][j];
                 s->samples_16[c] += s->num_channels;
@@ -1014,19 +1022,6 @@ static int decode_frame(WmallDecodeCtx *s)
     GetBitContext* gb = &s->gb;
     int more_frames = 0, len = 0, i, ret;
 
-    s->frame.nb_samples = s->samples_per_frame;
-    if ((ret = s->avctx->get_buffer(s->avctx, &s->frame)) < 0) {
-        /* return an error if no frame could be decoded at all */
-        av_log(s->avctx, AV_LOG_ERROR,
-               "not enough space for the output samples\n");
-        s->packet_loss = 1;
-        return ret;
-    }
-    for (i = 0; i < s->num_channels; i++) {
-        s->samples_16[i] = (int16_t *)s->frame.data[0] + i;
-        s->samples_32[i] = (int32_t *)s->frame.data[0] + i;
-    }
-
     /* get frame length */
     if (s->len_prefix)
         len = get_bits(gb, s->log2_frame_size);
@@ -1043,13 +1038,14 @@ static int decode_frame(WmallDecodeCtx *s)
 
     /* no idea what these are for, might be the number of samples
        that need to be skipped at the beginning or end of a stream */
+    int skip=0;
     if (get_bits1(gb)) {
-        int skip;
 
         /* usually true for the first frame */
         if (get_bits1(gb)) {
             skip = get_bits(gb, av_log2(s->samples_per_frame * 2));
             av_dlog(s->avctx, "start skip: %i\n", skip);
+            skip=0; // no idea what to do with this one anyway
         }
 
         /* sometimes true for the last frame */
@@ -1060,6 +1056,19 @@ static int decode_frame(WmallDecodeCtx *s)
 
     }
 
+    s->frame.nb_samples = s->samples_per_frame - skip;
+    if ((ret = s->avctx->get_buffer(s->avctx, &s->frame)) < 0) {
+        /* return an error if no frame could be decoded at all */
+        av_log(s->avctx, AV_LOG_ERROR,
+               "not enough space for the output samples\n");
+        s->packet_loss = 1;
+        return ret;
+    }
+    for (i = 0; i < s->num_channels; i++) {
+        s->samples_16[i] = (int16_t *)s->frame.data[0] + i;
+        s->samples_32[i] = (int32_t *)s->frame.data[0] + i;
+    }
+
     /* reset subframe states */
     s->parsed_all_subframes = 0;
     for (i = 0; i < s->num_channels; i++) {
-- 
1.7.7



More information about the ffmpeg-devel mailing list