[Libav-user] PIX_FMT_NB>64 so avcodec_find_best_pix_fmt(int64_t pix_fmt_mask, ...) wraps back to zero after bit 64.
Stefano Sabatini
stefano.sabatini-lala at poste.it
Sat Aug 13 15:06:46 CEST 2011
On date Saturday 2011-08-13 01:01:45 -0400, Matthew Einhorn encoded:
> Hi,
>
> This is basically a bug which appeared between git 9c2651a (July 23)
> and git faa3381 (July 28). It still worked in the 9c2651a git.
>
> The problem is that in avcodec_find_best_pix_fmt1() the loop looks at
> all bits from 0 - PIX_FMT_NB but since PIX_FMT_NB is larger than 64,
> after the 64th iteration we overflow back to the first bit and the
> first pixel format but the loop thinks that we're at say pix fmt 68.
> The following code demonstrates the problem and workaround.
>
> Code:
> int nLoss;
> PixelFormat pix= avcodec_find_best_pix_fmt(1ULL << PIX_FMT_GRAY8 ,
> PIX_FMT_YUV420P, 0, &nLoss);
> std::cout<<pix<<std::endl;
> pix= pix>64?(PixelFormat)(pix-64):pix;
> std::cout<<pix<<std::endl;
>
> Output:
> 72
> 8
>
> I noticed that the code in imgconvert.c got updated between July 23-28
> and I looked through to see if I can find why it stopped working, but
> couldn't. In fact, I'm not sure why it ever worked once PIX_FMT_NB was
> larger than 64.
I did the changes to imgconvert.c, and I was aware of the issue, and
from my knowledge that code couldn't ever work with more than 64 pixel
formats.
> An additional question, since PIX_FMT_NB is larger than 64 it means we
> cannot use this function on any new pixel formats since they don't fit
> within the 64 bit mask, unless I'm missing something. Would it be
> possible to add/replace these functions with something like the
> following? It basically replaces the mask with an array. I know an
> array wastes bit space, but you won't have to search through all 64
> flags anymore since you know how many elements are in the array so it
> should be a bit faster. I have never used git, otherwise I'd try to
> add it as a patch.
git diff
edit edit edit...
git commit -a
git send-email HASH~1..HASH
>
> static enum PixelFormat avcodec_find_best_pix_fmt_alt1(enum
> PixelFormat *dst_pix_fmts,
> enum PixelFormat src_pix_fmt,
> int has_alpha,
> int loss_mask)
> {
> int dist, i, loss, min_dist;
> enum PixelFormat dst_pix_fmt;
>
> /* find exact color match with smallest size */
> dst_pix_fmt = PIX_FMT_NONE;
> min_dist = 0x7fffffff;
> for(i = 0;dst_pix_fmts[i] != PIX_FMT_NONE; i++) {
> loss = avcodec_get_pix_fmt_loss(dst_pix_fmts[i], src_pix_fmt,
> has_alpha) & loss_mask;
> if (loss == 0) {
> dist = avg_bits_per_pixel(dst_pix_fmts[i]);
> if (dist < min_dist) {
> min_dist = dist;
> dst_pix_fmt = dst_pix_fmts[i];
> }
> }
> }
> return dst_pix_fmt;
> }
>
> enum PixelFormat avcodec_find_best_pix_fmt_alt(enum PixelFormat
> *dst_pix_fmts, enum PixelFormat src_pix_fmt,
> int has_alpha, int *loss_ptr)
avcodec_find_best_pix_fmt() is a public function, so you can't change
it without breaking API/ABI compatibility. You need to add a separate
function - e.g. avcodec_find_best_pix_fmt2().
You're welcome to post a patch to ffmpeg-devel, or file a bug report,
but keep in mind, we tend to be *dreadly* busy, so a patch+review is
possibly a faster way to see it fixed, and you may learn something in
the process.
[...]
More information about the Libav-user
mailing list