mirror of https://git.ffmpeg.org/ffmpeg.git
avcodec/mpegpicture: Always reset mbskip_table
Codecs call ff_find_unused_picture() to get the index of an unused picture; said picture may have buffers left from using it previously (these buffers are intentionally not unreferenced so that it might be possible to reuse them; they are only reused when they are writable, otherwise they are replaced by new, zeroed buffers). They should not make any assumptions about which picture they get. Yet this is not true for mbskip_table and damaged bitstreams. When one returns old unused slots randomly, the output becomes nondeterministic. This can't happen now (see below), but it will be possible once mpegpicture uses proper pools for the picture tables. The following discussion uses the sample created via ffmpeg -bitexact -i fate-suite/svq3/Vertical400kbit.sorenson3.mov -ps 50 -bf 2 -bitexact -an -qscale 5 -ss 40 -error_rate 4 -threads 1 out.avi When decoding this with one thread, the slots are as follows: Cur 0 (type I), last -1, Next -1; cur refcount -1, not reusing buffers Cur 1 (type P), last -1, Next 0; cur refcount -1, not reusing buffers Cur 2 (type B), last 0, Next 1; cur refcount -1, not reusing buffers Cur 2 (type B), last 0, Next 1; cur refcount 2, not reusing buffers Cur 0 (type P), last 0, Next 1; cur refcount 2, not reusing buffers Cur 2 (type B), last 1, Next 0; cur refcount 1, reusing buffers Cur 2 (type B), last 1, Next 0; cur refcount 2, not reusing buffers Cur 1 (type P), last 1, Next 0; cur refcount 2, not reusing buffers Cur 2 (type B), last 0, Next 1; cur refcount 1, reusing buffers Cur 2 (type B), last 0, Next 1; cur refcount 2, not reusing buffers Cur 0 (type I), last 0, Next 1; cur refcount 2, not reusing buffers Cur 2 (type B), last 1, Next 0; cur refcount 1, reusing buffers Cur 2 (type B), last 1, Next 0; cur refcount 2, not reusing buffers Cur 1 (type P), last 1, Next 0; cur refcount 2, not reusing buffers After the slots have been filled initially, the buffers are only reused for the first B-frame in a B-frame chain: a) When the new picture is an I or a P frame, the slot of the backward reference is cleared and reused for the new frame (as has been said, "cleared" does not mean that the auxiliary buffers have been unreferenced). Given that not only the slot in the picture array, but also MpegEncContext.last_picture contain references to these auxiliary buffers, they are not writable and are therefore not reused, but replaced by new, zero-allocated buffers. b) When the new picture is the first B-frame in a B-frame chain, the two reference slots are kept as-is and one gets a slot that does not share its auxiliary buffers with any of MpegEncContext. current_picture, last_picture, next_picture. The buffers are therefore writable and are reused. c) When the new picture is a B-frame that is not the first frame in a B-frame chain, ff_mpv_frame_start() reuses the slot occupied by the preceding B-frame. Said slot shares its auxilary buffers with MpegEncContext.current_picture, so that they are not considered writable and are therefore not reused. When using frame-threading, the slots are made to match the one from the last thread, so that the above analysis is mostly the same with one exception: Other threads may also have references to these buffers, so that initial B-frames of a B-frame chain need no longer have writable/reusable buffers. In particular, all I and P-frames always use new, zeroed buffers. Because only the mbskip_tables of I- and P-frames are ever used, it follows that there is currently no problem with using stale values for them at all. Yet as the analysis shows this is very fragile: 1. MpegEncContext.(current|last|next)_picture need not have references of their own, but they have them and this influences the writability decision. 2. It would not work if the slots were returned in a truely random fashion or if there were a proper pool used. Therefore this commit always resets said buffer. This is in preparation for actually adding such a pool (where the checksums for said sample would otherwise be depending on the number of threads used for decoding). Future commits will restrict this to only the codecs for which it is necessary (namely the MPEG-4 decoder). Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
This commit is contained in:
parent
71ff9217f7
commit
7ad13e173b
|
@ -238,6 +238,7 @@ int ff_alloc_picture(AVCodecContext *avctx, Picture *pic, MotionEstContext *me,
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
pic->mbskip_table = pic->mbskip_table_buf->data;
|
pic->mbskip_table = pic->mbskip_table_buf->data;
|
||||||
|
memset(pic->mbskip_table, 0, pic->mbskip_table_buf->size);
|
||||||
pic->qscale_table = pic->qscale_table_buf->data + 2 * mb_stride + 1;
|
pic->qscale_table = pic->qscale_table_buf->data + 2 * mb_stride + 1;
|
||||||
pic->mb_type = (uint32_t*)pic->mb_type_buf->data + 2 * mb_stride + 1;
|
pic->mb_type = (uint32_t*)pic->mb_type_buf->data + 2 * mb_stride + 1;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue