Reputation:
I had an h264 video stream encoded from yuv444p frames, it was played well using vlc or mpv player.
But when I tried to decode it using libavcodec, it just looked like this.
The source frame is an upsize down vlc-player logo.
Here is the intialization of the decoder:
AVCodec *codec = avcodec_find_decoder(AV_CODEC_ID_H264);
AVCodecContext *codecCtx = avcodec_alloc_context3(codec);
avcodec_open2(codecCtx, codec, NULL);
The decoder worked well when decoding packets encoded from yuv420p. Did I miss anything when decoding those packets encoded from yuv444p frames?
Update:I converted the yuv444p output into BGRA with sws_scale(), then I make a transforment with the follow codes;
int offset_out = 0, offset_tmp = 0;
uint32_t *tmp = (uint32_t *)malloc(width * height * 4);
for (int i = 0; i < width * height; i++) {
if ((i + width + 9) % (width + 9) > width) {
out[offset_out++] = in[i];
} else {
tmp[offset_tmp++] = in[i];
}
}
memcpy(out + offset_out, tmp, offset_tmp);
free(tmp);
Then the picture looked all right.
There is a number 9
in i + width + 9
. I guessed that cause I knew the width and height of the source picture. But what if the width or height was changed to some value else, 9
didn't work.
I want to know what's wrong with the decoder.
Upvotes: 1
Views: 2797
Reputation: 365792
What pixel format does the video have? If you encoded with ffmpeg, it doesn't downscale the chroma to yuv420 unless you tell it to. By default, it would make a yuv444 h.264 stream, which libavcodec would decode to yuv444 frames. If you interpreted those bytes as yuv420, it won't look right. Judging from the image, that's probably what happened.
libavcodec could even give you planar RGB (gbrp
) output if you're decoding an RGB h.264 stream.
So you have to check what pixel format you get from the decoder, and treat it accordingly.
Upvotes: 1