Michael <[EMAIL PROTECTED]> added the comment:
> Well, The report, contains
> no gdb output (mandatory for crashes)
> no valgrind output (mandatory for memory issues)
> no patch (mandatory for any "fix")
> no sample file to reproduce
> it does contain some vague description of a crash and a bug that is not
> reproduceable.
> and a claim of an out of array access, which isnt out of the array as
> far as i can tell for ffmpeg and ffplay. It may be that the quoted
> code is wrong and that it is out of the allocated space for some
> applications. But honestly this is becoming quite a bit too
> speculative, especially considering that we have many well written
> bug reports which need to be dealt with.
I appreciate it would be more useful to have all those things, but
there's a limit to the amount of time I can spend on this. I'm a long
way from a usable development machine, and I simply don't have that
data any more. The best I can do for you is try and explain as best as
I can what the bug is.
Using line numbers from h264.c in the trunk (rev 14283).
The function xchg_mb_border() contains the following code:
2304 : if(h->deblocking_filter == 2) {
2305 : mb_xy = h->mb_xy;
2306 : deblock_left = h->slice_table[mb_xy] == h->slice_table[mb_xy -
1];
2307 : deblock_top = h->slice_table[mb_xy] ==
h->slice_table[h->top_mb_xy];
2308 : } else {
2309 : deblock_left = (s->mb_x > 0);
2310 : deblock_top = (s->mb_y > 0);
2311 : }
Assume h->deblocking_filter != 2 (Which is true for my videos).
The first time this routine is called for a given field, it has src_y
== &buffer[0] (the start of the image buffer).
Normally (progressive video), when routine is called on at the top of
the image, then 'deblock_top' is set false (because s->mb_y == 0)
Unfortunately, when the video is interlaced, and this is called on an
odd field, then s->mb_y == 1, and thus deblock_top is set to true.
(even though this is the first line in the field).
If this is 1080I video, then xchg_mb_border() is called with linesize
== 1080 * 2. (if it's 1080P, then linesize == 1080). This is so that
stepping forward by a linesize stays in the same field.
The code then does:
2313 : src_y -= linesize + 1;
2314 : src_cb -= uvlinesize + 1;
2315 : src_cr -= uvlinesize + 1;
Now, if this is an interlaced odd field, and we're at the top of the
field, then this routine was called with src_y = &buffer[1080];
(address of the start of line 1 in the frame, being the 1st line in
the field, and the 2nd line in the frame).
When the 'src_y -= linesize + 1' is run, then it backs up _two_ lines
in interlaced video (because linesize is doubled)
So src_y is now &buffer[-1079]; I.e. it now points before the start of
the buffer. (note that it also does this when the video is
progressive, so it's not bad in itself).
But then the code does:
2323 : if(deblock_left){
2324 : for(i = !deblock_top; i<17; i++){
2325 : XCHG(h->left_border[i ], src_y [i* linesize], temp8,
xchg);
2326 : }
2327 : }
Normally, when the video is progressive and this is the first line,
then deblock_top == 0, so the loop runs 1 .. 17, so the accesses start
from 'src_y + linesize' and the fact that src_y currently points
before the buffer is avoided.
But when the video is interlaced, the first line is numbered 1
(s->mb-y == 1), so deblock_top == 1, so the loop runs 0 .. 17, which
causes an access to src_y[0], which currently points to &buffer[-1079]
which randomly segfaults. (The segfault happens in the XCHG macro when
it accesses that memory).
In summary:
If the video is progressive, then the order is:
xchg_mb_border() is called with src_y == &buffer[0], linesize =
actual linesize.
deblock_top is set to false.
src_y is moved to &buffer[0] - linesize + 1.
now accesses memory starting from src_y[linesize] == &buffer[0].
If the video is interlaced, and this is odd field, then the order is.
xchg_mb_border() is called with src_y == &buffer[linesize],
linesize = 2 * actual linesize.
deblock_top is set to _TRUE_
src_y is moved to &buffer[0] - linesize + 1.
now accesses memory starting from src_y[0] == &buffer[-linesize+1]
== illegal memory access.
My fix for this, was to change the line:
2310 : deblock_top = (s->mb_y > 0);
to instead read
2310 : deblock_top = (s->mb_y > !!MB_FIELD);
This sets deblock_top to false when the video is interlaced, the field
is odd, and s->mb_y == 1 (which is the first line in an odd field).
With this change, the loop at line 2324 now goes from 1 .. 17 (instead
of 0 .. 17) and it no longer accesses memory before the start of the
buffer.
Hope this helps somewhat.
______________________________________________________
FFmpeg issue tracker <[EMAIL PROTECTED]>
<https://roundup.mplayerhq.hu/roundup/ffmpeg/issue427>
______________________________________________________