[MPlayer-advusers] [BUG] mencoder floating point exception with -of lavf

Corey Hickey bugfood-ml at fatooh.org
Sun Nov 13 23:51:33 CET 2005


Here is the third version of my buffering muxer wrapping patch. I doubt
it is acceptable in its current form, but it is mostly working for me
and I should be able to finish it based on your feedback. I've come up
with about 45 regression tests, the results of which I'll list in detail
at the end of this email.

This is going to be long, but I'd appreciate any help you can give me.


----------------------------------------------------------------------
First, here's a summary of the current status of each muxer:

muxer_avi.c:
I worked on this muxer first, and it was easy to modify -- all I had to
do was move the counter code out into the wrapper. When comparing my
patched mencoder to an unpatched version, all the regression tests I've
done turn out identical (to the byte).

muxer_mpeg.c:
The counter code was distributed among different functions, and I hacked
it out with a dull knife. As a result, not all the regression tests are
the same. This part is definitely not finished, but if anyone reading
this knows the mpeg muxer well I'd be interested in hearing how
atrocious my changes are and what could be done better.

muxer_lavf.c:
The counter removal here was simple and the diff is small. Since this
muxer was broken before, I can't compare my regression tests to
anything. Many tests encode and play fine. I suspect that the failures
are due to problems elsewhere (for example, last night I tracked down a
DTS problem and it is now fixed in ffmpeg/libavformat cvs). Also, some
of the ones that fail are because I couldn't figure out how to make
mencoder feed a particular muxer data from an allowed codec.

muxer_rawaudio.c:
Counter removal was very simple. I ran a couple regression tests and
they were both identical to files from an unpatched mencoder.

muxer_rawvideo.c:
Same as muxer_rawaudio.c


----------------------------------------------------------------------
The muxer buffer in this patch has quite a few differences to the one in
my previous patches. I ran into a few problems with that design. The new
design is much more complicated, for these reasons. Perhaps there's a
better way.

1. I can't just save the pointer to the stream buffer (and give it a new
pointer) because the pointers change in other parts of mencoder. So, I
have to use memcpy().

2. s->buffer often holds data past s->buffer+len. So, I can't memcpy
only len bytes.

...and...

3. I can't depend on s->buffer pointing to memory as big as
s->buffer_size because functions like ds_get_packet() change the pointer
to point to a smaller memory allocation.

...and...

4. s->buffer_len isn't always set. So, I have to take and store the
maximum of len and s->buffer_len, and use that value for memcpy()ing the
necessary number of bytes.

5. The data in the audio buffer can change between the time the muxer
receives an audio frame and the time the muxer receives a video frame.
So, I have to make sure I don't overwrite the current audio buffer with
data from the most recently buffered frame.

6. The lavf muxer uses s->timer to set pts, so I have to store that too.
Otherwise, the pts for all buffered packets would end up being the same.


----------------------------------------------------------------------
I have several questions by now:

1. My patch makes muxer_write_chunk() buffer up to 100 frames of audio.
I picked that number arbitrarily, and I'd like to choose one that is
large enough to be safe for all circumstances. So far 27 is the largest
number of initial audio frames I've seen, but I can't really conjecture
what would be best. My code allocates memory for storing s->buffer as
required, so very little extra memory would be used if we pick a very
large number. If nobody gives me any input here I'm going to choose 500
as a "reasonable amount of overkill."

2. muxer_mpeg.c doesn't set the counters in as straightforward a manner
as all the other muxers; the counters in muxer_mpeg.c weren't updated
for all frames. Putting the counter code in the wrapper implies that
mencoder's timing is now based on what is sent to the muxer, and the
muxer must keep up. I don't know if this is the correct way to go about
it. In fact, I'm not comfortable with any of the changes I've made to
muxer_mpeg.c.

3. In muxer_mpeg.c, s->gop_start is set but apparently never used. My
patch removes it, but I'm not entirely comfortable about doing so. I
don't know if gop_start is orphaned from previously removed code or if
it's there for the convenience of a future feature.

4. Will there ever be a situation wherein s->buffer is NULL and len is
!= 0? My code will segfault if that ever happens. If there's any sane
reason that could happen I can check for it and set len=0.


----------------------------------------------------------------------
There are a couple small cleanup things to do later that shouldn't
change functionality. Probably they should be separate patches.

1. Either change messages like "Writing AVI header..." to non-AVI
specific counterparts like "Writing container header...", or put the
messages inside each individual muxer.

2. muxer_avi.c writes the header three times. I think I can eliminate
the second time.



======================================================================

And finally, the regression test results. These are all on my main
amd64, but I doubt there's anything architecture-specific.

The source files:

1. small.vob: a partial dumpstream of a DVD. Video is MPEG2 and the
default audio stream is DTS.

2. test.avi: an encoded clip from a DVD. Video is FMP4 and audio is AC3 5.1.

3. img/*.jpg a bunch of jpeg files.


----------------------------------------------------------------------
-of avi (default)

---identical---
small.vob -ovc lavc -oac copy -ofps 24000/1001
small.vob -ovc lavc -oac mp3lame -ofps 24000/1001
small.vob -ovc lavc -nosound -ofps 24000/1001
small.vob -ovc copy -oac copy -ofps 24000/1001
small.vob -ovc copy -oac mp3lame -ofps 24000/1001
small.vob -ovc copy -nosound -ofps 24000/1001

test.avi -ovc lavc -oac copy
test.avi -ovc lavc -oac mp3lame
test.avi -ovc lavc -nosound
test.avi -ovc copy -oac copy
test.avi -ovc copy -oac mp3lame
test.avi -ovc copy -nosound


mf://img/*.jpg -mf type=jpeg:fps=10 -ovc lavc -lavcopts vcodec=mjpeg


----------------------------------------------------------------------
-of mpeg

---identical---
test.avi -ovc lavc -lavcopts vcodec=mpeg2video -oac copy -of mpeg
test.avi -ovc lavc -lavcopts vcodec=mpeg2video -oac mp3lame -of mpeg
test.avi -ovc lavc -lavcopts vcodec=mpeg2video -nosound -of mpeg

small.vob -ovc copy -oac mp3lame -of mpeg -ofps 24000/1001
small.vob -ovc copy -nosound -of mpeg -ofps 24000/1001
small.vob -ovc lavc -lavcopts vcodec=mpeg2video -oac mp3lame -of mpeg
-ofps 24000/1001
small.vob -ovc lavc -lavcopts vcodec=mpeg2video -nosound -of mpeg -ofps
24000/1001

mf://img/*.jpg -mf type=jpeg:fps=10 -ovc lavc -lavcopts
vcodec=mpeg2video -of mpeg

---different, but still play ok---
test.avi -ovc copy -oac copy -of mpeg

This example tries copying FMP4 video and mp3 using -of mpeg. This isn't
supposed to work right, is it? Both patched and unpatched mplayer
produce files with very bad a-v desync. The files seem identical when
played, but the files are different. I think this is a result of
duplicate frames -- mpegfile_write_chunk() immediately returns when
s->buffer is null and never updates the timer. Is that the correct
behavior? avifile_write_chunk() updates the timer regardless. My
muxer_write_chunk() function updates the timer always.


small.vob -ovc lavc -lavcopts vcodec=mpeg2video -oac copy -of mpeg -ofps
24000/1001

The audio in the resulting files are both completely broken. For some
reason, out of 1378308 bytes, the two differ by only two bytes:

bugfood at bugfood:/tmp$ cmp -l old.mpeg new.mpeg
     29 102 106
   2077 102 106

I suppose I should track this down; I have a feeling it's due to the
timer differences again. I'll have a look later.


----------------------------------------------------------------------
-of lavf

---can't compare to anything, but look ok---
small.vob -ovc lavc -nosound -of lavf -lavfopts format=avi -ofps 24000/1001
small.vob -ovc lavc -oac mp3lame -of lavf -lavfopts format=avi -ofps
24000/1001
small.vob -ovc lavc -oac copy -of lavf -lavfopts format=avi -ofps 24000/1001
small.vob -ovc lavc -oac copy -of lavf -lavfopts format=mov -ofps 24000/1001
small.vob -ovc lavc -oac copy -of lavf -lavfopts format=mp4 -ofps 24000/1001
small.vob -ovc lavc -oac copy -of lavf -lavfopts format=asf -ofps 24000/1001
small.vob -ovc lavc -oac copy -of lavf -lavfopts format=nut -ofps 24000/1001

test.avi -ovc copy -oac copy -of lavf -lavfopts format=avi
test.avi -ovc copy -oac copy -of lavf -lavfopts format=mov
test.avi -ovc copy -oac copy -of lavf -lavfopts format=mp4


---doesn't work yet, but might be bugs elsewhere---
small.vob -ovc lavc -lavcopts vcodec=mpeg2video -oac copy -of lavf
-lavfopts format=mpg -ofps 24000/1001

Oddly, this muxes an avi file. I'll investigate that some other time.


/mnt/tmp/small.vob -ovc lavc -lavcopts vcodec=mpeg2video -oac copy -of
lavf -lavfopts format=mpg -ofps 24000/1001 -o test.mpg

Adding "-o test.mpg" seems to make lavf write an mpeg file; however, I
get lots of messages like the following:
[mpeg @ 0x906440]packet too large, ignoring buffer limits to mux it
[mpeg @ 0x906440]buffer underflow


small.vob -ovc lavc -lavcopts vcodec=flv -nosound -of lavf -lavfopts
format=swf -ofps 24000/1001

mencoder reports:
[NULL @ 0xb72b00]SWF only supports FLV1 and MJPEG
...and then gets a floating point exception.


small.vob -ovc lavc -lavcopts vcodec=mjpeg -nosound -of lavf -lavfopts
format=swf -ofps 24000/1001

mencoder encodes ok, but mplayer reports:
[swf @ 0x9725a0]No media found in SWF
LAVF_header: av_open_input_stream() failed
...and quits.


small.vob -ovc lavc -lavcopts vcodec=rv10 -nosound -of lavf -lavfopts
format=rm -ofps 24000/1001

This encodes happily, but mplayer crashes because the fourcc is set to
RV20. 'mplayer -vc +ffrv10' works ok.


small.vob -ovc copy -oac pcm -of lavf -lavfopts format=dv -ofps 25

I don't have any idea what kind of video I can put in a dv...


test.avi -ovc copy -oac copy -of lavf -lavfopts format=asf

This seems mostly ok, but lots of slight errors creep into the video stream,
like:
[mpeg4 @ 0xbfb210]Error at MB: 808
[mpeg4 @ 0xbfb210]concealing 57 DC, 57 AC, 57 MV errors
[mpeg4 @ 0xbfb210]cbpc damaged at 37
[mpeg4 @ 0xbfb210]Error at MB: 802


test.avi -ovc copy -oac copy -of lavf -lavfopts format=nut

There's no audio when I play this, but the video looks ok for several
seconds until:
VDec: vo config request - 5498 x 5075 (preferred colorspace: Planar YV12)
VDec: using Planar YV12 as output csp (no 0)
Movie-Aspect is 2.44:1 - prescaling to correct movie aspect.
VO: [xv] 5498x5075 => 12406x5075 Planar YV12

It was very disconcerting seeing my monitor go completely black. :) This
works if I choose -oac mp3lame instead.


----------------------------------------------------------------------
-of rawaudio

---identical---
small.vob -ovc lavc -oac copy -ofps 24000/1001 -of rawaudio
test.avi -ovc copy -oac copy -ofps 24000/1001 -of rawaudio

----------------------------------------------------------------------
-of rawvideo

---identical---
small.vob -ovc lavc -nosound -ofps 24000/1001 -of rawvideo
test.avi -ovc copy -nosound -of rawvideo



======================================================================

That's all for now, except for a quote from Rich:
"Try it -- it really won't be difficult!"

Yes it was. :)) The code was easy, but I've ended up spending hours with
two parallel gdb sessions trying to figure out where and why my patched
mencoder differed from the unpatched version. I learned a lot about gdb
and mencoder.

-Corey
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: muxer-buffer-try3.diff
URL: <http://lists.mplayerhq.hu/pipermail/mplayer-advusers/attachments/20051113/e2a0e377/attachment.asc>


More information about the MPlayer-advusers mailing list