我想使用FFmpeg4.2.2将输入NV12格式转换为输出NV12格式,具有相同的高度和宽度。我使用了sws_scale转换,但输出帧的颜色都是绿色的。
附言:似乎不需要使用swscale来获得相同的宽度、相同的高度和相同的格式框架,但在我的项目中处理其他框架是必要的。
我已经成功地将输入的NV12格式转换为具有不同高度和宽度的输出NV12格式,输出帧的颜色是右。但我未能将NV12转换为具有相同高度和宽度。这太奇怪了,我不知道为什么:(
我想知道原因是什么,我应该怎么做。以下是我的代码swsCtx4用于将NV12格式转换为输出NV12格式。其他则用于其他格式的转换测试。谢谢你的帮助~
//the main code is
AVFrame* frame_nv12 = av_frame_alloc();
frame_nv12->width = in_width;
frame_nv12->height = in_height;
frame_nv12->format = AV_PIX_FMT_NV12;
uint8_t* frame_buffer_nv12 = (uint8_t*)av_malloc(av_image_get_buffer_size(AV_PIX_FMT_NV12, in_width, in_height , 1));
av_image_fill_arrays(frame_nv12->data, frame_nv12->linesize, frame_buffer_nv12, AV_PIX_FMT_NV12, in_width, in_height, 1);
AVFrame* frame2_nv12 = av_frame_alloc();
frame2_nv12->width = in_width1;
frame2_nv12->height = in_height1;
frame2_nv12->format = AV_PIX_FMT_NV12;
uint8_t* frame2_buffer_nv12 = (uint8_t*)av_malloc(av_image_get_buffer_size(AV_PIX_FMT_NV12, in_width1, in_height1, 1));
av_image_fill_arrays(frame2_nv12->data, frame2_nv12->linesize, frame2_buffer_nv12, AV_PIX_FMT_NV12, in_width1, in_height1, 1);
SwsContext* swsCtx4 = nullptr;
swsCtx4 = sws_getContext(in_width, in_height, AV_PIX_FMT_NV12, in_width1, in_height1, AV_PIX_FMT_NV12,
SWS_BILINEAR | SWS_PRINT_INFO, NULL, NULL, NULL);
printf("swsCtx4n");
ret = sws_scale(swsCtx4, frame_nv12->data, frame_nv12->linesize, 0, frame_nv12->height, frame2_nv12->data, frame2_nv12->linesize);
if (ret < 0) {
printf("sws_4scale failedn");
}
//the complete code
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/imgutils.h>
#include <libswscale/swscale.h>
}
#include <seeker/loggerApi.h>
#include "seeker/common.h"
#include <iostream>
//解决原因:pts设置为0,dts设置为0
#define FILE_SRC "testPicFilter.yuv" //源文件
#define FILE_DES "test11.yuv" //源文件
int count = 0;
int main(int argc, char* argv[])
{
av_register_all();
int ret = 0;
//std::this_thread::sleep_for(std::chrono::milliseconds(5000));
int count1 = 1;
int piccount;
int align = 1;
/*打开输入yuv文件*/
FILE* fp_in = fopen(FILE_SRC, "rb+");
if (fp_in == NULL)
{
printf("文件打开失败n");
return 0;
}
int in_width = 640;
int in_height = 360;
int in_width1 = 640;
int in_height1 = 360;
/*处理后的文件*/
FILE* fp_out = fopen(FILE_DES, "wb+");
if (fp_out == NULL)
{
printf("文件创建失败n");
return 0;
}
char buff[50];
AVFrame* frame_in = av_frame_alloc();
unsigned char* frame_buffer_in;
frame_buffer_in = (unsigned char*)av_malloc(av_image_get_buffer_size(AV_PIX_FMT_YUV420P, in_width, in_height, 1));
/*根据图像设置图像指针和内存对齐方式*/
av_image_fill_arrays(frame_in->data, frame_in->linesize, frame_buffer_in, AV_PIX_FMT_YUV420P, in_width, in_height, 1);
frame_in->width = in_width;
frame_in->height = in_height;
frame_in->format = AV_PIX_FMT_YUV420P;
//输入yuv转成frame_nv12
AVFrame* frame_nv12 = av_frame_alloc();
frame_nv12->width = in_width;
frame_nv12->height = in_height;
frame_nv12->format = AV_PIX_FMT_NV12;
uint8_t* frame_buffer_nv12 = (uint8_t*)av_malloc(av_image_get_buffer_size(AV_PIX_FMT_NV12, in_width, in_height , 1));
av_image_fill_arrays(frame_nv12->data, frame_nv12->linesize, frame_buffer_nv12, AV_PIX_FMT_NV12, in_width, in_height, 1);
AVFrame* frame2_nv12 = av_frame_alloc();
frame2_nv12->width = in_width1;
frame2_nv12->height = in_height1;
frame2_nv12->format = AV_PIX_FMT_NV12;
uint8_t* frame2_buffer_nv12 = (uint8_t*)av_malloc(av_image_get_buffer_size(AV_PIX_FMT_NV12, in_width1, in_height1, 1));
av_image_fill_arrays(frame2_nv12->data, frame2_nv12->linesize, frame2_buffer_nv12, AV_PIX_FMT_NV12, in_width1, in_height1, 1);
//输入rgb转成yuv
AVFrame* frame_yuv = av_frame_alloc();
frame_yuv->width = in_width;
frame_yuv->height = in_height;
frame_yuv->format = AV_PIX_FMT_YUV420P;
uint8_t* frame_buffer_yuv = (uint8_t*)av_malloc(av_image_get_buffer_size(AV_PIX_FMT_YUV420P, in_width, in_height, 1));
av_image_fill_arrays(frame_yuv->data, frame_yuv->linesize, frame_buffer_yuv,
AV_PIX_FMT_YUV420P, in_width, in_height, 1);
SwsContext* swsCtx = nullptr;
swsCtx = sws_getContext(in_width, in_height, AV_PIX_FMT_YUV420P, in_width, in_height, AV_PIX_FMT_NV12,
SWS_BILINEAR | SWS_PRINT_INFO, NULL, NULL, NULL);
printf("swsCtxn");
SwsContext* swsCtx4 = nullptr;
swsCtx4 = sws_getContext(in_width, in_height, AV_PIX_FMT_NV12, in_width1, in_height1, AV_PIX_FMT_NV12,
SWS_BILINEAR | SWS_PRINT_INFO, NULL, NULL, NULL);
printf("swsCtx4n");
SwsContext* swsCtx2 = nullptr;
swsCtx2 = sws_getContext(in_width1, in_height1, AV_PIX_FMT_NV12, in_width, in_height, AV_PIX_FMT_YUV420P,
SWS_BILINEAR | SWS_PRINT_INFO, NULL, NULL, NULL);
printf("swsCtx2n");
while (1)
{
count++;
if (fread(frame_buffer_in, 1, in_width * in_height * 3 / 2, fp_in) != in_width * in_height * 3 / 2)
{
break;
}
frame_in->data[0] = frame_buffer_in;
frame_in->data[1] = frame_buffer_in + in_width * in_height;
frame_in->data[2] = frame_buffer_in + in_width * in_height * 5 / 4;
//转NV12格式
int ret = sws_scale(swsCtx, frame_in->data, frame_in->linesize, 0, frame_in->height, frame_nv12->data, frame_nv12->linesize);
if (ret < 0) {
printf("sws_scale swsCtx failedn");
}
ret = sws_scale(swsCtx4, frame_nv12->data, frame_nv12->linesize, 0, frame_nv12->height, frame2_nv12->data, frame2_nv12->linesize);
if (ret < 0) {
printf("sws_scale swsCtx4 failedn");
}
if (ret > 0) {
int ret2 = sws_scale(swsCtx2, frame2_nv12->data, frame2_nv12->linesize, 0, frame2_nv12->height, frame_yuv->data, frame_yuv->linesize);
if (ret2 < 0) {
printf("sws_scale swsCtx2 failedn");
}
I_LOG("frame_yuv:{},{}", frame_yuv->width, frame_yuv->height);
//I_LOG("frame_yuv:{}", frame_yuv->format);
if (frame_yuv->format == AV_PIX_FMT_YUV420P)
{
for (int i = 0; i < frame_yuv->height; i++)
{
fwrite(frame_yuv->data[0] + frame_yuv->linesize[0] * i, 1, frame_yuv->width, fp_out);
}
for (int i = 0; i < frame_yuv->height / 2; i++)
{
fwrite(frame_yuv->data[1] + frame_yuv->linesize[1] * i, 1, frame_yuv->width / 2, fp_out);
}
for (int i = 0; i < frame_yuv->height / 2; i++)
{
fwrite(frame_yuv->data[2] + frame_yuv->linesize[2] * i, 1, frame_yuv->width / 2, fp_out);
}
printf("yuv to filen");
}
}
}
fclose(fp_in);
fclose(fp_out);
av_frame_free(&frame_in);
av_frame_free(&frame_nv12);
av_frame_free(&frame_yuv);
sws_freeContext(swsCtx);
sws_freeContext(swsCtx2);
sws_freeContext(swsCtx4);
//std::this_thread::sleep_for(std::chrono::milliseconds(8000));
return 0;
}
您在ffmpeg库中发现了一个错误。报告它!(见此。(
作为一种补救措施,如果源帧的格式、宽度和高度与目标帧的相同,我建议您调用av_frame_copy()
。
作为旁注,您可以在#1817行看到有问题的代码。