ffmpeg swcale实现rgb24转yuv420p

我测试的rgb素材是BGR24的,如果你的 rgb数据是AV_PIX_FMT_RGB24格式,请自行替换

#include <stdio.h>
#include <stdint.h>
#include <cstring>
#include <malloc.h>
extern "C"
{
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#include "libavutil/imgutils.h"
};

int main(int argc, char **argv){
    av_register_all();
    const int width = 400, height = 400;
    enum AVPixelFormat src_pix_fmt = AV_PIX_FMT_BGR24, dst_pix_fmt = AV_PIX_FMT_YUV420P;
    FILE* fp = NULL;
    fopen_s(&fp, "sucai_rgb.rgb", "rb");
    uint8_t* rgbbuf = (uint8_t*)malloc(width * height * 3);
    fread(rgbbuf, width * height * 3, 1, fp);
    fclose(fp);


    AVFrame *pFrameYUV = av_frame_alloc();
    uint8_t *out_buffer = new uint8_t[avpicture_get_size(dst_pix_fmt, width, height)];
    //avpicture_fill是给pFrameYUV初始化一些字段,并且给填充data和linesize
    avpicture_fill((AVPicture *)pFrameYUV, out_buffer, dst_pix_fmt, width, height);

    AVFrame *rgbFrame = av_frame_alloc();

    avpicture_fill((AVPicture *)rgbFrame, rgbbuf, src_pix_fmt, width, height);

    SwsContext *sws_ctx = sws_getContext(
        width, height, src_pix_fmt,
        width, height, dst_pix_fmt,
        SWS_BILINEAR, NULL, NULL, NULL);
    /*
    int sws_scale(struct SwsContext *c, const uint8_t *const srcSlice[],
              const int srcStride[], int srcSliceY, int srcSliceH,
              uint8_t *const dst[], const int dstStride[]);
    srcSlice[],dst[]是输入输出图像数据各颜色通道的buffer指针数组
    srcStride[],dstStride[] 为输入输出图像数据各颜色通道每行存储的字节数数组
    srcSliceY 为从输入图像数据的第多少列开始逐行扫描,通常设为0
    srcSliceH 为需要扫描多少行,通常为输入图像数据的高度
    */
    // *(rgbFrame->linesize)--->3*width
    // *(pFrameYUV->linesize)-->width
    sws_scale(sws_ctx, rgbFrame->data, rgbFrame->linesize, 0, height, pFrameYUV->data, pFrameYUV->linesize);
    sws_freeContext(sws_ctx);

    FILE* fpout = NULL;
    fopen_s(&fpout, "yuv_out.yuv", "wb");
    fwrite(pFrameYUV->data[0], width * height, 1, fpout);
    fwrite(pFrameYUV->data[1], width * height / 4, 1, fpout);
    fwrite(pFrameYUV->data[2], width * height / 4, 1, fpout);

    fclose(fpout);
    return 0;
}
  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在代码中实现 YUV444 换为 YUV420P 格式,可以使用 FFmpeg 的相关 API 来实现。下面是一个简单的示例代码: ```c #include <libavcodec/avcodec.h> #include <libavutil/imgutils.h> #include <libswscale/swscale.h> int main(int argc, char **argv) { AVCodecContext *codec_ctx = NULL; AVFrame *frame = NULL; AVPacket packet = {0}; struct SwsContext *sws_ctx = NULL; int ret; // 1. 打开输入文件并读取输入视频信息 AVFormatContext *fmt_ctx = NULL; ret = avformat_open_input(&fmt_ctx, "input.yuv", NULL, NULL); // ...省略错误处理代码 ret = avformat_find_stream_info(fmt_ctx, NULL); // ...省略错误处理代码 // 2. 初始化编解码器上下文及帧对象 AVStream *stream = fmt_ctx->streams[0]; codec_ctx = avcodec_alloc_context3(NULL); // ...省略错误处理代码 avcodec_parameters_to_context(codec_ctx, stream->codecpar); AVCodec *decoder = avcodec_find_decoder(codec_ctx->codec_id); // ...省略错误处理代码 ret = avcodec_open2(codec_ctx, decoder, NULL); // ...省略错误处理代码 frame = av_frame_alloc(); // ...省略错误处理代码 // 3. 初始化缩放上下文 sws_ctx = sws_getContext(codec_ctx->width, codec_ctx->height, codec_ctx->pix_fmt, codec_ctx->width / 2, codec_ctx->height / 2, AV_PIX_FMT_YUV420P, SWS_BILINEAR, NULL, NULL, NULL); // ...省略错误处理代码 // 4. 读取每一帧并进行 YUV444 YUV420P 的处理 while (1) { ret = av_read_frame(fmt_ctx, &packet); if (ret < 0) { break; } if (packet.stream_index != 0) { av_packet_unref(&packet); continue; } ret = avcodec_send_packet(codec_ctx, &packet); if (ret < 0) { av_packet_unref(&packet); break; } while (ret >= 0) { ret = avcodec_receive_frame(codec_ctx, frame); if (ret < 0) { break; } // 进行 YUV444 YUV420P 的处理 AVFrame *out_frame = av_frame_alloc(); out_frame->width = frame->width / 2; out_frame->height = frame->height / 2; out_frame->format = AV_PIX_FMT_YUV420P; av_frame_get_buffer(out_frame, 32); sws_scale(sws_ctx, frame->data, frame->linesize, 0, frame->height, out_frame->data, out_frame->linesize); // ... // 输出 out_frame 到文件或其他处理 // ... av_frame_unref(out_frame); } av_packet_unref(&packet); } // 5. 释放资源 avformat_close_input(&fmt_ctx); avcodec_free_context(&codec_ctx); av_frame_free(&frame); sws_freeContext(sws_ctx); return 0; } ``` 这个示例代码中,首先打开输入文件并读取输入视频信息,然后初始化编解码器上下文及帧对象,接着初始化缩放上下文,最后读取每一帧并进行 YUV444 YUV420P 的处理,并将处理结果输出到文件或其他处理。其中,`av_read_frame` 函数用于读取每一帧,`avcodec_send_packet` 函数用于将输入数据包发送给解码器,`avcodec_receive_frame` 函数用于从解码器接收解码后的帧数据,`sws_scale` 函数用于进行缩放处理,`av_frame_get_buffer` 函数用于为输出帧分配内存空间,`av_frame_unref` 函数用于释放帧对象。 希望这个示例代码对您有所帮助。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值