請教FFmpeg大神:我用最新版解碼h264檔案,解碼成YUV420檔案后,顏色有錯位,這是為什么???
#pragma once
#include <iostream>
extern "C"
{
#include <libavcodec/avcodec.h>
#include <libavutil/frame.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include <libavutil/imgutils.h>
};
#define INBUF_SIZE 4096
using namespace std;
void pgm_save(unsigned char *buf, int wrap, int xsize, int ysize, char *filename)
{
FILE *f;
int i;
f = fopen(filename, "ab+");
fprintf(f, "P5\n%d %d\n%d\n", xsize, ysize, 255);
for (i = 0; i < ysize; i++)
fwrite(buf + i * wrap, 1, xsize, f);
fclose(f);
}
void decode(AVCodecContext *dec_ctx, AVFrame *frame, AVPacket *pkt, const char *filename)
{
char buf[1024];
int ret;
ret = avcodec_send_packet(dec_ctx, pkt);
if (ret < 0)
{
fprintf(stderr, "Error sending a packet for decoding\n");
exit(1);
}
while (ret >= 0)
{
ret = avcodec_receive_frame(dec_ctx, frame);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
return;
else if (ret < 0)
{
fprintf(stderr, "Error during decoding\n");
exit(1);
}
//sws_scale(imgCtx, frame->data, frame->linesize, 0, dec_ctx->height, yuv->data, yuv->linesize);
printf("saving frame %3d\n", dec_ctx->frame_number);
fflush(stdout);
/* the picture is allocated by the decoder. no need to free it */
snprintf(buf, sizeof(buf), "%s-%d", filename, dec_ctx->frame_number);
pgm_save(frame->data[0], frame->linesize[0], dec_ctx->width, dec_ctx->height, buf);//Y
pgm_save(frame->data[1], frame->linesize[1], dec_ctx->width / 2, dec_ctx->height / 2, buf);//U
pgm_save(frame->data[2], frame->linesize[2], dec_ctx->width / 2, dec_ctx->height / 2, buf);//V
}
}
int main(int argc, char **argv)
{
const char *filename = "test3.h264", *outfilename = "frames\\frame";
const AVCodec *codec;
AVCodecParserContext *parser;
AVCodecContext *c = NULL;
FILE *f;
AVFrame *frame;
uint8_t inbuf[INBUF_SIZE + AV_INPUT_BUFFER_PADDING_SIZE];
uint8_t *data;
size_t data_size;
int ret;
AVPacket *pkt;
pkt = av_packet_alloc();
if (!pkt)
exit(1);
/* set end of buffer to 0 (this ensures that no overreading happens for damaged MPEG streams) */
memset(inbuf + INBUF_SIZE, 0, AV_INPUT_BUFFER_PADDING_SIZE);
/* find the MPEG-1 video decoder */
//codec = avcodec_find_decoder(AV_CODEC_ID_MPEG1VIDEO);
codec = avcodec_find_decoder(AV_CODEC_ID_H264);
if (!codec) {
fprintf(stderr, "Codec not found\n");
exit(1);
}
parser = av_parser_init(codec->id);
if (!parser) {
fprintf(stderr, "parser not found\n");
exit(1);
}
c = avcodec_alloc_context3(codec);
if (!c) {
fprintf(stderr, "Could not allocate video codec context\n");
exit(1);
}
/* open it */
if (avcodec_open2(c, codec, NULL) < 0) {
fprintf(stderr, "Could not open codec\n");
exit(1);
}
f = fopen(filename, "rb");
if (!f) {
fprintf(stderr, "Could not open %s\n", filename);
exit(1);
}
frame = av_frame_alloc();
if (!frame) {
fprintf(stderr, "Could not allocate video frame\n");
exit(1);
}
while (!feof(f)) {
/* read raw data from the input file */
data_size = fread(inbuf, 1, INBUF_SIZE, f);
if (!data_size)
break;
/* use the parser to split the data into frames */
data = inbuf;
while (data_size > 0) {
ret = av_parser_parse2(parser, c, &pkt->data, &pkt->size, data, data_size, AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0);
if (ret < 0) {
fprintf(stderr, "Error while parsing\n");
exit(1);
}
data += ret;
data_size -= ret;
if (pkt->size)
decode(c, frame, pkt, outfilename);
}
}
/* flush the decoder */
decode(c, frame, NULL, outfilename);
fclose(f);
av_parser_close(parser);
avcodec_free_context(&c);
av_frame_free(&frame);
av_packet_free(&pkt);
system("pause");
return 0;
}
FFmpeg4.0.2解碼后的YUV檔案:

低版本解碼正常的YUV檔案:

uj5u.com熱心網友回復:
肯定是格式轉錯了,保存成檔案,用工具看看uj5u.com熱心網友回復:
解碼生成的的YUV應沒問題,Y資料讀出正確,是UV不正確,您發顯示YUV代碼上來才能確定問題出在哪。
直覺判斷是:
一可能是每行后面的Panding補空部分數值不一樣,
二是可能你不小心把Y資料的行寬line[0]用在了UV,所以錯位。
uj5u.com熱心網友回復:
pgm_save 這個函式里面上來把檔案名寫到Y/U/V檔案里面了,確定沒問題?UV讀取時候加偏移了么?uj5u.com熱心網友回復:
U, V資料有問題,位元組對齊有問題,影像邊界出現錯位現象uj5u.com熱心網友回復:
僅僅顏色問題的話,灰度圖沒問題,說明Y分量正確,錯誤處在UV分量上。1. 如樓上說的那樣檢查是否有資料錯位;
2. 檢查編碼前與解碼后的影像格式是否一致
uj5u.com熱心網友回復:
有可能原先的影像格式是YUVJ420P,直接轉成YUV420P會出現顏色的問題。uj5u.com熱心網友回復:
看看YUV資料格式是否匹配,再按照轉化演算法進行對齊一行行處理就行了uj5u.com熱心網友回復:
YUV資料分離問題吧Y資料沒錯,黑白部分正常
上色出錯時UV資料問題,是不是你的UV錯位存放,你分離的時候直接先1/4的U,再1/4V這樣分離的?
uj5u.com熱心網友回復:
問題解決了嗎?我遇到了同樣的問題
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/227736.html
標籤:多媒體/流媒體開發
