yuv编码为jpeg linux c,最简单的基于FFMPEG的图像编码器(YUV编码为JPEG)(转)

伴随着毕业论文的完成,这两天终于腾出了空闲,又有时间搞搞FFMPEG的研究了。想着以前一直搞的都是FFMPEG解码方面的工做,不多涉及到FFMPEG编码方面的东西,因而打算研究一下FFMPEG的编码。在网上看了一些例子,发现要否则是难度略微有些大,要否则就是类库比较陈旧,因而就决定本身作一个编码方面的例子,方便之后学习。git

简介

本文的编码器实现了YUV420P的数据编码为JPEG图片。本着简单的原则,代码基本上精简到了极限。使用了2014年5月6号编译的最新的FFMPEG类库。github

程序很简单,打开工程后直接运行便可将YUV数据编码为JPEG。本程序十分灵活,能够根据须要修改为编码各类图像格式的编码器,好比PNG,GIF等等。平台使用VC2010。ide

源代码

/**

* 最简单的基于FFmpeg的图像编码器

* Simplest FFmpeg Picture Encoder

*

* 雷霄骅 Lei Xiaohua

* leixiaohua1020@126.com

* 中国传媒大学/数字电视技术

* Communication University of China / Digital TV Technology

*http://blog.csdn.net/leixiaohua1020*

* 本程序实现了YUV420P像素数据编码为JPEG图片。是最简单的FFmpeg编码方面的教程。

* 经过学习本例子能够了解FFmpeg的编码流程。*/#include

#define __STDC_CONSTANT_MACROS#ifdef _WIN32//Windows

extern "C"{

#include"libavcodec/avcodec.h"#include"libavformat/avformat.h"};#else

//Linux...

#ifdef __cplusplusextern "C"{#endif#include#include#ifdef __cplusplus

};#endif

#endif

int main(int argc, char*argv[])

{

AVFormatContext*pFormatCtx;

AVOutputFormat*fmt;

AVStream*video_st;

AVCodecContext*pCodecCtx;

AVCodec*pCodec;

uint8_t*picture_buf;

AVFrame*picture;

AVPacket pkt;inty_size;int got_picture=0;intsize;int ret=0;

FILE*in_file = NULL; //YUV source

int in_w=480,in_h=272; //YUV's width and height

const char* out_file = "cuc_view_encode.jpg"; //Output file

in_file= fopen("cuc_view_480x272.yuv", "rb");

av_register_all();//Method 1

pFormatCtx =avformat_alloc_context();//Guess format

fmt = av_guess_format("mjpeg", NULL, NULL);

pFormatCtx->oformat =fmt;//Output URL

if (avio_open(&pFormatCtx->pb,out_file, AVIO_FLAG_READ_WRITE) < 0){

printf("Couldn't open output file.");return -1;

}//Method 2. More simple//avformat_alloc_output_context2(&pFormatCtx, NULL, NULL, out_file);//fmt = pFormatCtx->oformat;

video_st= avformat_new_stream(pFormatCtx, 0);if (video_st==NULL){return -1;

}

pCodecCtx= video_st->codec;

pCodecCtx->codec_id = fmt->video_codec;

pCodecCtx->codec_type =AVMEDIA_TYPE_VIDEO;

pCodecCtx->pix_fmt =AV_PIX_FMT_YUVJ420P;

pCodecCtx->width =in_w;

pCodecCtx->height =in_h;

pCodecCtx->time_base.num = 1;

pCodecCtx->time_base.den = 25;//Output some information

av_dump_format(pFormatCtx, 0, out_file, 1);

pCodec= avcodec_find_encoder(pCodecCtx->codec_id);if (!pCodec){

printf("Codec not found.");return -1;

}if (avcodec_open2(pCodecCtx, pCodec,NULL) < 0){

printf("Could not open codec.");return -1;

}

picture=av_frame_alloc();

size= avpicture_get_size(pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height);

picture_buf= (uint8_t *)av_malloc(size);if (!picture_buf)

{return -1;

}

avpicture_fill((AVPicture*)picture, picture_buf, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height);//Write Header

avformat_write_header(pFormatCtx,NULL);

y_size= pCodecCtx->width * pCodecCtx->height;

av_new_packet(&pkt,y_size*3);//Read YUV

if (fread(picture_buf, 1, y_size*3/2, in_file) <=0)

{

printf("Could not read input file.");return -1;

}

picture->data[0] = picture_buf; //Y

picture->data[1] = picture_buf+ y_size; //U

picture->data[2] = picture_buf+ y_size*5/4; //V//Encode

ret = avcodec_encode_video2(pCodecCtx, &pkt,picture, &got_picture);if(ret < 0){

printf("Encode Error.\n");return -1;

}if (got_picture==1){

pkt.stream_index= video_st->index;

ret= av_write_frame(pFormatCtx, &pkt);

}

av_free_packet(&pkt);//Write Trailer

av_write_trailer(pFormatCtx);

printf("Encode Successful.\n");if(video_st){

avcodec_close(video_st->codec);

av_free(picture);

av_free(picture_buf);

}

avio_close(pFormatCtx->pb);

avformat_free_context(pFormatCtx);

fclose(in_file);return 0;

}

结果

编码前的YUV420P数据:post

edd0e4f284033ae6e289fb568b84da95.png

编码后的JPEG:学习

dc39e39a1b781c4e94d4ce887217127e.png

下载

simplest ffmpeg picture encoderui

项目主页编码

CSDN工程下载地址:

PUDN工程下载地址:

本程序实现了YUV420P像素数据编码为JPEG图片。是最简单的FFmpeg编码方面的教程。经过学习本例子能够了解FFmpeg的编码流程。

更新-1.1(2015.2.13)=========================================

此次考虑到了跨平台的要求,调整了源代码。通过此次调整以后,源代码能够在如下平台编译经过:

VC++:打开sln文件便可编译,无需配置。

cl.exe:打开compile_cl.bat便可命令行下使用cl.exe进行编译,注意可能须要按照VC的安装路径调整脚本里面的参数。编译命令以下。

::VS2010 Environment

call "D:\Program Files\Microsoft Visual Studio 10.0\VC\vcvarsall.bat"

::include

@set INCLUDE=include;%INCLUDE%

::lib

@set LIB=lib;%LIB%

::compile and link

cl simplest_ffmpeg_picture_encoder.cpp /link avcodec.lib avformat.lib avutil.lib ^

avdevice.lib avfilter.lib postproc.lib swresample.lib swscale.lib /OPT:NOREF

MinGW:MinGW命令行下运行compile_mingw.sh便可使用MinGW的g++进行编译。编译命令以下。

g++ simplest_ffmpeg_picture_encoder.cpp -g -o simplest_ffmpeg_picture_encoder.exe \

-I /usr/local/include -L /usr/local/lib \

-lavformat -lavcodec -lavutil

GCC:Linux或者MacOS命令行下运行compile_gcc.sh便可使用GCC进行编译。编译命令以下。

gcc simplest_ffmpeg_picture_encoder.cpp -g -o simplest_ffmpeg_picture_encoder.out \

-I /usr/local/include -L /usr/local/lib -lavformat -lavcodec -lavutil

PS:相关的编译命令已经保存到了工程文件夹中

SourceForge上已经更新。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要将一个yuv图像编码jpeg文件,可以使用libjpeg-turbo库提供的API。以下是一个基本的示例: ```c #include <stdio.h> #include <jpeglib.h> #define WIDTH 640 #define HEIGHT 480 void encode_jpeg(unsigned char* yuv_data, const char* filename) { struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; JSAMPROW row_pointer[1]; int row_stride; FILE* outfile = fopen(filename, "wb"); if (outfile == NULL) { fprintf(stderr, "Error opening output jpeg file %s\n", filename); return; } cinfo.err = jpeg_std_error(&jerr); jpeg_create_compress(&cinfo); jpeg_stdio_dest(&cinfo, outfile); cinfo.image_width = WIDTH; cinfo.image_height = HEIGHT; cinfo.input_components = 3; cinfo.in_color_space = JCS_YCbCr; jpeg_set_defaults(&cinfo); jpeg_start_compress(&cinfo, TRUE); row_stride = WIDTH * 3; while (cinfo.next_scanline < cinfo.image_height) { row_pointer[0] = &yuv_data[cinfo.next_scanline * row_stride]; jpeg_write_scanlines(&cinfo, row_pointer, 1); } jpeg_finish_compress(&cinfo); fclose(outfile); jpeg_destroy_compress(&cinfo); } ``` 在这个示例中,我们创建了一个`encode_jpeg()`函数,它接收一个指向yuv数据的指针和一个输出文件名。函数中使用了libjpeg-turbo库提供的API来将yuv数据编码jpeg文件。 首先,我们创建了`jpeg_compress_struct`结构体和`jpeg_error_mgr`结构体,用于存储压缩参数和错误信息。然后,我们打开输出文件并将输出流绑定到`jpeg_compress_struct`结构体中。接下来,我们设置了图像宽度、高度、输入组件数量和颜色空间等参数,并使用`jpeg_set_defaults()`函数设置了默认的压缩参数。然后,我们开始压缩过程,并在while循环中逐行写入扫描线数据。最后,我们完成了压缩过程,关闭输出文件并销毁`jpeg_compress_struct`结构体。 要使用这个函数,我们只需要将yuv数据和输出文件名作为参数传递给它即可。例如: ```c int main() { unsigned char yuv_data[WIDTH * HEIGHT * 3]; // fill yuv_data with actual data encode_jpeg(yuv_data, "output.jpg"); return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值