[MPlayer-dev-eng] [BUG][PATCH] Decoding of WMV3 files fail, shows only black screen
Shachar Raindel
shacharr at gmail.com
Sat Jul 2 22:18:28 CEST 2005
On 7/2/05, Ivan Kalvachev <ikalvachev at gmail.com> wrote:
> On 7/2/05, Shachar Raindel <shacharr at gmail.com> wrote:
> > Hi,
> > I have been having a problem with decoding WMV3 files, getting the
> > following (interesting) messages (sorry, long post to show what is
> > going on):
> > <snip loads of not so interesting startup messages>
> > Playing ******.wmv.
> > ASF file format detected.
> > VIDEO: [WMV3] 320x240 24bpp 1000.000 fps 0.0 kbps ( 0.0 kbyte/s)
> > Clip info:
> > name:
> > author:
> > copyright:
> > comments:
> > ==========================================================================
> > Opening audio decoder: [ffmpeg] FFmpeg/libavcodec audio decoders
> > AUDIO: 44100 Hz, 2 ch, s16le, 48.0 kbit/3.40% (ratio: 6003->176400)
> > Selected audio codec: [ffwmav2] afm:ffmpeg (DivX audio v2 (FFmpeg))
> > ==========================================================================
> > vo: X11 running at 1024x768 with depth 24 and 32 bpp (":0.0" => local display)
> > ==========================================================================
> > Opening video decoder: [dmo] DMO video codecs
> > DMO dll supports VO Optimizations 0 1
> > DMO dll might use previous sample when requested
> > GetOutput r=0x0 size:230400 align:1
> > StreamCount r=0x0 1 1
> > Decoder supports the following formats: YV12 YUY2 UYVY YVYU RGB8
> > RGB555 RGB565 RGB24 RGB32
> > Decoder is capable of YUV output (flags 0x1b)
> > VDec: vo config request - 320 x 240 (preferred csp: Packed YUY2)
> > VDec: using Planar YV12 as output csp (no 0)
> > Movie-Aspect is undefined - no prescaling applied.
> > VO: [xv] 320x240 => 320x240 Planar YV12
> > Selected video codec: [wmv9dmo] vfm:dmo (Windows Media Video 9 DMO)
> > ==========================================================================
> > Building audio filter chain for 44100Hz/2ch/s16le -> 0Hz/0ch/??...
> > [libaf] setting tempo 1.000000
> > alsa-init: 1 soundcard found, using: default
> > alsa: 44100 Hz/2 channels/4 bpf/32768 bytes buffer/Signed 16 bit Little Endian
> > AO: [alsa] 44100Hz 2ch s16le (2 bps)
> > Building audio filter chain for 44100Hz/2ch/s16le -> 44100Hz/2ch/s16le...
> > [libaf] setting tempo 1.000000
> > Starting playback...
> > ProcessInputError FALSE ?? (keyframe: 0)
> > ProcessInputError FALSE ?? (keyframe: 0) 1/ 1 ??% ??% ??,?% 1 0 98%
> > ProcessInputError r:0x80004005=-2147467259 (keyframe: 1)??,?% 2 0 98%
> > ProcessInputError r:0x80004005=-2147467259 (keyframe: 0)??,?% 2 0 98%
> > ProcessInputError r:0x80004005=-2147467259 (keyframe: 1)??,?% 3 0 98%
> > ProcessInputError r:0x80004005=-2147467259 (keyframe: 1)??,?% 3 0 98%
> > ProcessInputError r:0x80004005=-2147467259 (keyframe: 1)??,?% 3 0 98%
> > ProcessInputError r:0x80004005=-2147467259 (keyframe: 1)??,?% 3 0 98%
> > ProcessInputError r:0x80004005=-2147467259 (keyframe: 1)??,?% 3 0 98%
> > <snip tons and tons of these messages>
> >
> > Audio was playing-back great, video remained a black screen.
> > What is more interesting was that seeking to the beginning of the file
> > after few seconds of playback revived the video stream. After some
> > messing around with DMO_VideoDecoder.c, I found out the reason: The
> > first 2 calls to DMO_VideoDecoder_DecodeInternal (and therefore to the
> > ProcessInput method of the DMO itself) are done with is_keyframe = 0
> > (which should actually be called should_drop, and is actually rather
> > redundant), since mplayer wants to drop the first frame as it is
> > lagging behind the audio (it gets more audio in the beginning), and
> > confuses the codec internal state, as it misses the first sync
> > signals.
> >
> > Removing the dependency in the phony flag of is_keyframe solved the
> > problem, and now my WMV files play great.
> >
> > Note that this is just a work-around, not a correct fix as the DMO now
> > thinks that any bit we feed it with is a sync point (which is of
> > course wrong and buggy). Someone who knows what is going on in the
> > rest of this mess should fix it to provide useful information to the
> > codec (probably extracted from the carrying ASF container).
> >
> > Shachar
>
> Hi,
>
> (the usual declaimer, i'm not win32 loader & dmo expert).
>
> It looks like DMO interface have 2 phases.
> Phase1 - feed data into the decoder.
> Phase2 - get ready data from the decoder.
>
Yep, that is right. First you feed samples to ProcessInput, possibly
marking key-frames with DMO_INPUT_DATA_BUFFERF_SYNCPOINT in the flags,
than you pull them out of the codec using ProcessOutput. DMO doesn't
support hard frame dropping naturally (you should simply skip feeding
the codec with data in order to do this, and I am not sure what the
result will be). For "soft" frame dropping, one should use the
DMO_PROCESS_OUTPUT_DISCARD_WHEN_NO_BUFFER flag with an output pointer
of null when calling ProcessOutput. What happening today is that any
frame dropping is handled as a soft frame dropping, and as a bonus
frame dropping is used to decided which frame should be marked as a
keyframe and which shouldn't.
> To be more confusing we do hardframedrop for all small framedrops on phase1.
>
No, what we do at phase 1 is flag frames that we wish to drop as
non-key-frames, and do soft frame dropping for them as well. If I
understood correctly, "hard-dropping" = not even decoding the data
(never happens with DMO), "soft-dropping" = decoding, not running
video filters on it and not blitting to screen. Please correct me if I
am wrong.
> Probably the right way to make an soft drop is to use
> DMO_PROCESS_OUTPUT_DISCARD_WHEN_NO_BUFFER flag on
> ProcessOutput() and not supply the output buffer, as described here:
> http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/htm/imediaobjectprocessoutput.asp
>
More up2date link:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directshow/htm/imediaobjectprocessoutput.asp
The mechanism for doing this is already implemented correctly in the
code, and it is when we get a NULL as the target buffer.
The problem is that the code in vd_dmo has somehow coupled the frame
dropping logic with the keyframe logic, here is the relevant code from
libmpcodecs/vd_dmo.c:
// decode a frame
static mp_image_t* decode(sh_video_t *sh,void* data,int len,int flags){
mp_image_t* mpi;
if(len<=0) return NULL; // skipped frame
if(flags&3){
// framedrop:
DMO_VideoDecoder_DecodeInternal(sh->context, data, len, 0, 0);
return NULL;
}
mpi=mpcodecs_get_image(sh, MP_IMGTYPE_TEMP, 0 /*MP_IMGFLAG_ACCEPT_STRIDE*/,
sh->disp_w, sh->disp_h);
if(!mpi){ // temporary!
printf("couldn't allocate image for cinepak codec\n");
return NULL;
}
DMO_VideoDecoder_DecodeInternal(sh->context, data, len, 1, mpi->planes[0]);
return mpi;
}
Now, the prototype of DMO_VideoDecoder_DecodeInternal is:
int DMO_VideoDecoder_DecodeInternal(DMO_VideoDecoder *this, const
void* src, int size, int is_keyframe, char* imdata)
Pay attention, the value of is_keyframe, is determine according to the
flags, set by the call in decode_video, which looks like this:
mpi=mpvdec->decode(sh_video, start, in_size, drop_frame);
^^^^^^^^ This variable is called "flags" in vd_dmo.c, and than
translated into "is_keyframe" in DMO_VideoDecoder_DecodeInternal.
drop_frame => flags => is_keyframe, nice, isn't it?
As we can see, each frame we don't drop is considered as a keyframe by
DMO_VideoDecoder_DecodeInternal, while every frame we do drop is fed
to the decoder, as a normal frame. Do you think that this is logical?
Now, Ivan, the patch you sent in your second e-mail is nice, but sadly
doesn't solve the bug (since, as I shown to you it is caused by the
fact that we use frame dropping to decide which frames are keyframes
and which aren't (which is absolutely crazy).
The correct fix is to pass the information about which frames are
key-frames and which aren't from the ASF demuxer to the DMO decoder,
but this is rather complex, and setting all of the frames to be
treated as key-frames seems to work fine most of the time.
Shachar
More information about the MPlayer-dev-eng
mailing list