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

Jakub Stachowski qbast at go2.pl
Sat Apr 14 21:30:41 CEST 2012


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
>
>>
>> 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
>

-------------- next part --------------
>From 6157d31c310f938d0c36a14b67a59c5d9b98177d Mon Sep 17 00:00:00 2001
From: Jakub Stachowski <qbast at go2.pl>
Date: Thu, 12 Apr 2012 17:56:42 +0200
Subject: [PATCH] Flush last frame. Unfortunately this creates opposite
 problem - file is now too long<

---
 libavcodec/wmalosslessdec.c |    8 ++++++++
 1 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/libavcodec/wmalosslessdec.c b/libavcodec/wmalosslessdec.c
index e511443..062cfa3 100644
--- a/libavcodec/wmalosslessdec.c
+++ b/libavcodec/wmalosslessdec.c
@@ -1168,6 +1168,13 @@ static int decode_packet(AVCodecContext *avctx, void *data, int *got_frame_ptr,
     int num_bits_prev_frame, packet_sequence_number,
         seekable_frame_in_packet, spliced_packet;
 
+    // flush frames from last packet
+    if ( !buf && s->num_saved_bits > get_bits_count(&s->gb)) {
+        int next=decode_frame(s);
+        if (!next) s->num_saved_bits=0;
+        goto out;
+    }
+
     if (s->packet_done || s->packet_loss) {
         s->packet_done = 0;
 
@@ -1256,6 +1263,7 @@ static int decode_packet(AVCodecContext *avctx, void *data, int *got_frame_ptr,
         save_bits(s, gb, remaining_bits(s, gb), 0);
     }
 
+out:
     *(AVFrame *)data = s->frame;
     *got_frame_ptr   = s->frame.nb_samples > 0;
     s->packet_offset = get_bits_count(gb) & 7;
-- 
1.7.7

-------------- next part --------------
>From 3740bb7f87ca9746602b211281082493b29de9e7 Mon Sep 17 00:00:00 2001
From: Jakub Stachowski <qbast at go2.pl>
Date: Sat, 14 Apr 2012 21:21:04 +0200
Subject: [PATCH] WIP: handle flushing of last packet

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

diff --git a/libavcodec/wmalosslessdec.c b/libavcodec/wmalosslessdec.c
index 6a2268a..ede33cf 100644
--- a/libavcodec/wmalosslessdec.c
+++ b/libavcodec/wmalosslessdec.c
@@ -101,6 +101,7 @@ typedef struct WmallDecodeCtx {
     uint8_t         drc_gain;                       ///< gain for the DRC tool
     int8_t          skip_frame;                     ///< skip output step
     int8_t          parsed_all_subframes;           ///< all subframes decoded?
+    int32_t         samples_written;
 
     /* subframe/block decode state */
     int16_t         subframe_len;                   ///< current subframe length
@@ -839,7 +840,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);
@@ -875,7 +876,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;
 
 
@@ -980,7 +981,8 @@ static int decode_subframe(WmallDecodeCtx *s)
         int c = s->channel_indexes_for_cur_subframe[i];
         int subframe_len = s->channel[c].subframe_len[s->channel[c].cur_subframe];
 
-        for (j = 0; j < subframe_len; j++) {
+        for (j = 0; j < subframe_len && s->samples_written < total_samples; j++) {
+            s->samples_written++;
             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 +1016,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 +1032,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 +1050,21 @@ static int decode_frame(WmallDecodeCtx *s)
 
     }
 
+    s->frame.nb_samples = s->samples_per_frame - skip;
+    av_log(s->avctx,AV_LOG_INFO,"Samples per frame %d, skip %d, real size %d\n",s->samples_per_frame,skip,s->frame.nb_samples);
+    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;
+    }
+    s->samples_written = 0;
+    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

-------------- next part --------------
A non-text attachment was scrubbed...
Name: samples.wav
Type: audio/wav
Size: 60046 bytes
Desc: not available
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20120414/cdfb8124/attachment.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: samples.wma
Type: audio/x-ms-wma
Size: 18574 bytes
Desc: not available
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20120414/cdfb8124/attachment.wma>


More information about the ffmpeg-devel mailing list