[FFmpeg-devel] Handling of mono data in WMA lossless

Jakub Stachowski qbast at go2.pl
Sun Apr 29 23:36:15 CEST 2012


While testing WMA lossless decoder on various files I found another case 
when it outputs different data from Microsoft's implementation.  I have 
not been able to fully fix this, so I am sharing what I found so far in 
hope that someone else will be able to provide additional information.

WMAL apparently has special way of dealing with mono (where all samples 
in both channels are identical) data: only first channel is coded and 
decoder is expected to copy samples to second channel.

Attached testsamples.c creates two files designed to cause encoder to 
use this mode: samples-equal.pcm have first frame with mono data, in 
second frame it is different. Decoder should copy data from first 
channel to second.
sample-zero.pcm has data in first channel and zeros in second. In this 
case decoder should not copy data. I have no found any specific flag 
which decides that, but it is possible that do_interch_decorr is used.
Attached patch makes ffmpeg decode both files ok. It also fixes 
Mashiat's sample.

However it does not work with real world sample ( 
http://stream1.criteriamx.com:8080/part.wma ) . Unfortunately I cannot 
share whole file.

Differences are following:
- in my previous samples, copying of data from first to second channel 
has to be done before all filtering. Otherwise second frame will be broken
- however in this sample it is the other way around - samples has to be 
copied as last step or decoder starts generating wrong data
- there are frames which have both channel coded and yet encoder should 
overwrite data. Which really makes no sense to me.
- I decoded the sample into wav and compressed it again with Expression 
encoder. This time ffmpeg could decode it ok. Maybe behaviour was 
different in older version of SDK ( ?
-------------- next part --------------
#include <stdio.h>

void main() {
    unsigned short int i;
    unsigned short int j=0;
    FILE *f=fopen("samples-equal.pcm","wb");
    FILE *f2=fopen("samples-zero.pcm","wb");
    int zero=0;
    for (i=0;i<2048;i++) {
    for (i=0;i<2048;i++) {
-------------- next part --------------
diff --git a/libavcodec/wmalosslessdec.c b/libavcodec/wmalosslessdec.c
index b77d576..e8168a9 100644
--- a/libavcodec/wmalosslessdec.c
+++ b/libavcodec/wmalosslessdec.c
@@ -959,8 +959,12 @@ static int decode_subframe(WmallDecodeCtx *s)
                     use_normal_update_speed(s, i);
                 revert_cdlms(s, i, 0, subframe_len);
-            } else
-                memset(s->channel_residues[i], 0, sizeof(s->channel_residues[i]));
+            } else {
+                if (i>0 && !s->is_channel_coded[i] && s->do_inter_ch_decorr) 
+                    memcpy(s->channel_residues[i],s->channel_residues[i-1],sizeof(s->channel_residues[i]));
+                else 
+                    memset(s->channel_residues[i], 0, sizeof(s->channel_residues[i]));
+            }
     if (s->do_mclms)
         revert_mclms(s, subframe_len);

More information about the ffmpeg-devel mailing list