[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