用ffmpeg转换图片、视频格式yuv, C语言读取YUV图像

1.用ffmpeg将视频转换为yuv格式

ffmpeg.exe -i src.avi -c:v rawvideo -pix_fmt yuv420p 1280x720.yuv

输出视频可以用yuvPlayer打开

2.用ffmpeg将jpg,png图像转换为yuv格式

建议图像命名为宽乘高 width*height,乘号用字母”x”。
使用ffmpeg的命令为:

ffmpeg.exe -i 1024x680.jpg -pix_fmt gray8 1024x680_gray8.yuv

ffmpeg.exe -i 1024x680.jpg -pix_fmt yuv420p 1024x680_420p.yuv

转换后的图像可以用软件pYUV查看,格式注意和转换的要一致,比如gray8的color space为黑白BW,subsampling选4:0:0; 而420p的颜色空间选yuv, subsampling选4:2:0

3.用C语言读取yuv图像

首先定义一个yuv图像的结构体

typedef struct yuvImage
    {
        int width;           /* Image width  */
        int height;          /* Image height */
        unsigned char *y;    /* y: data pointer */
        unsigned char *u;    /* u: data pointer */
        unsigned char *v;    /* v: data pointer */
    } YUV_IMAGE;

// read image
FILE*fp = NULL;
fp = fopen("E:/mycode/Datasets/1024x680_gray8.yuv", "rb");

yuv的格式为: y的大小为size, u,v各为size/4;
这里写图片描述

设置yuv的起始位置
y:0
u:size
v: size+size/4

YUV_IMAGE* yuvImage= (YUV_IMAGE*)malloc(sizeof(YUV_IMAGE));
yuvImage->height= 240;
yuvImage->width= 320;
yuvImage->y= (unsigned char*)malloc((size * 3 / 2)*sizeof(unsigned char));
memset(yuvImage->y, 0, size * sizeof(unsigned char));
yuvImage->u= yuvImage->y+ size;
yuvImage->v = yuvImage->u+ size / 4;

读取

buffer = (char *)malloc(size*sizeof(char));
fread(buffer, size, 1, fp);
memcpy(yuvImage->y, buffer, size);
fread(buffer, size/4, 1, fp);
memcpy(yuvImage->u, buffer, size);
fread(buffer, size/4, 1, fp);
memcpy(yuvImage->v, buffer, size);```

另一种格式

// 420p
    unsigned char*y = (unsigned char*)malloc(sizeof(unsigned char) * size);
    memset(y, 0, size);
    unsigned char*u = (unsigned char*)malloc(sizeof(unsigned char) * size/4);
    memset(u, 0, size/4);
    unsigned char*v = (unsigned char*)malloc(sizeof(unsigned char) * 1size/4);
    memset(v, 0, size/4);

    FILE*fp = NULL;
    fp = fopen("E:/mycode/Datasets/1024x680.yuv", "rb");
    fread(y, 1, size, fp);
    fread(u, 1, size/4, fp);
    fread(v, 1, size/4, fp);
    fclose(fp);
  • 0
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是使用c语言FFmpeg解码视频为yuv420p格式并保存文件的代码示例: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <libavutil/imgutils.h> #include <libavutil/parseutils.h> #include <libavutil/opt.h> #include <libavcodec/avcodec.h> #include <libavformat/avformat.h> int main(int argc, char *argv[]) { AVFormatContext *fmt_ctx = NULL; int ret; if (argc < 2) { fprintf(stderr, "Usage: %s <input file>\n", argv[0]); exit(1); } ret = avformat_open_input(&fmt_ctx, argv[1], NULL, NULL); if (ret < 0) { fprintf(stderr, "Could not open input file '%s'\n", argv[1]); exit(1); } ret = avformat_find_stream_info(fmt_ctx, NULL); if (ret < 0) { fprintf(stderr, "Could not find stream information\n"); exit(1); } int video_stream_index = -1; for (int i = 0; i < fmt_ctx->nb_streams; i++) { if (fmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { video_stream_index = i; break; } } if (video_stream_index == -1) { fprintf(stderr, "Could not find video stream\n"); exit(1); } AVCodecParameters *codecpar = fmt_ctx->streams[video_stream_index]->codecpar; AVCodec *codec = avcodec_find_decoder(codecpar->codec_id); if (!codec) { fprintf(stderr, "Codec not found\n"); exit(1); } AVCodecContext *codec_ctx = avcodec_alloc_context3(codec); if (!codec_ctx) { fprintf(stderr, "Could not allocate codec context\n"); exit(1); } ret = avcodec_parameters_to_context(codec_ctx, codecpar); if (ret < 0) { fprintf(stderr, "Could not copy codec parameters to codec context\n"); exit(1); } ret = avcodec_open2(codec_ctx, codec, NULL); if (ret < 0) { fprintf(stderr, "Could not open codec\n"); exit(1); } AVPacket pkt; av_init_packet(&pkt); pkt.data = NULL; pkt.size = 0; AVFrame *frame = av_frame_alloc(); if (!frame) { fprintf(stderr, "Could not allocate frame\n"); exit(1); } int frame_count = 0; while (av_read_frame(fmt_ctx, &pkt) >= 0) { if (pkt.stream_index == video_stream_index) { ret = avcodec_send_packet(codec_ctx, &pkt); if (ret < 0) { fprintf(stderr, "Error sending packet to decoder\n"); exit(1); } while (ret >= 0) { ret = avcodec_receive_frame(codec_ctx, frame); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { break; } else if (ret < 0) { fprintf(stderr, "Error during decoding\n"); exit(1); } char filename[256]; snprintf(filename, sizeof(filename), "frame-%d.yuv", frame_count); FILE *fp = fopen(filename, "wb"); if (!fp) { fprintf(stderr, "Could not open output file '%s'\n", filename); exit(1); } for (int i = 0; i < codec_ctx->height; i++) { fwrite(frame->data[0] + i * frame->linesize[0], 1, codec_ctx->width, fp); } for (int i = 0; i < codec_ctx->height / 2; i++) { fwrite(frame->data[1] + i * frame->linesize[1], 1, codec_ctx->width / 2, fp); } for (int i = 0; i < codec_ctx->height / 2; i++) { fwrite(frame->data[2] + i * frame->linesize[2], 1, codec_ctx->width / 2, fp); } fclose(fp); frame_count++; } } av_packet_unref(&pkt); } avcodec_free_context(&codec_ctx); avformat_close_input(&fmt_ctx); avformat_free_context(fmt_ctx); av_frame_free(&frame); return 0; } ``` 该示例代码从命令行读取一个输入文件名,并使用FFmpeg打开该文件。然后它搜索视频流并使用视频解码器解码视频帧。对于每个解码帧,它将像素数据写入一个yuv文件。每个yuv文件的名称都是“frame-N.yuv”,其中N是帧计数器。最后,它释放所有使用的资源并退出。 请注意,此示例代码假定输入文件是可解码的视频文件。如果您想处理其他类型的输入文件,请根据需要进行修改。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值