[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