#include <stdio.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include <libavutil/imgutils.h> void SaveFrame(AVFrame *pFrame, int width, int height, int iFrame); int main(int argc, char *argv[])
{
// 获取AVFormatContext句柄
AVFormatContext *pFormatCtx = avformat_alloc_context(); // 打开一个流媒体文件 open video file
if (avformat_open_input(&pFormatCtx, argv[1], NULL, NULL)) {
fprintf(stderr, "open input failed\n");
return -1;
} // 获取多媒体信息,存至句柄 retrieve stream information
if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {
fprintf(stderr, "find stream info failed\n");
return -1;
} // 打印多媒体信息 dump information about file onto standard error
av_dump_format(pFormatCtx, 0, argv[1], 0); // 通过句柄,找出视频流 find the video stream
int videoStream = -1;
videoStream = av_find_best_stream(pFormatCtx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);
if (-1 == videoStream) {
fprintf(stderr, "Can not find video stream!\n");
return -1;
} AVCodecParameters *pCodecPar = NULL;
pCodecPar = pFormatCtx->streams[videoStream]->codecpar; // 搜索合适的视频解码器 find the decoder for the video stream
AVCodec *pCodec = NULL;
pCodec = avcodec_find_decoder(pCodecPar->codec_id);
if (NULL == pCodec) {
fprintf(stderr, "Unsupported codec!\n");
return -1;
} AVCodecContext *pCodecCtx = NULL;
pCodecCtx = avcodec_alloc_context3(pCodec);
// 因为 AVStream::codec 被弃用,AVCodecContext 需要通过 AVCodecParameters 转换得到
avcodec_parameters_to_context(pCodecCtx, pCodecPar); // 打开视频解码器 open Codec
if (avcodec_open2(pCodecCtx, pCodec, NULL)) {
fprintf(stderr, "Codec open failed!\n");
return -1;
} AVFrame *pFrame = NULL;
AVFrame *pFrameRGB = NULL;
// 分配两个视频帧,pFrame保存原始帧,pFrameRGB存放转换后的RGB帧 Allocate video frame
pFrame = av_frame_alloc();
pFrameRGB = av_frame_alloc();
if (NULL == pFrameRGB || NULL == pFrame) {
fprintf(stderr, "Alloc frame failed!\n");
return -1;
}
uint8_t *buffer = NULL;
int numBytes = 0;
// 计算解码后原始数据所需缓冲区大小,并分配内存空间 Determine required buffer size and allocate buffer
numBytes = av_image_get_buffer_size(AV_PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height, 1);
buffer = (uint8_t *)av_malloc(numBytes * sizeof(uint8_t)); av_image_fill_arrays(pFrameRGB->data, pFrameRGB->linesize, buffer, AV_PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height, 1); int frameFinished = 0;
AVPacket packet = {0};
int i = 0;
struct SwsContext *img_convert_ctx = NULL;
// 获取swscale句柄
img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt,
pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL);
while (av_read_frame(pFormatCtx, &packet) >= 0) {
// Is this a packet from the video stream?
if (packet.stream_index == videoStream) {
// Decode video frame
int ret = avcodec_send_packet(pCodecCtx, &packet);
if (0 != ret)
continue;
while (avcodec_receive_frame(pCodecCtx, pFrame) == 0) {
// Convert the image from its native format to RGB
//img_convert((AVPicture *)pFrameRGB, AV_PIX_FMT_RGB24, (AVPicture *)pFrame,
// pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height);
sws_scale(img_convert_ctx, (const unsigned char* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);
// Save the frame to disk
if (++i <= 5)
SaveFrame(pFrameRGB, pCodecCtx->width, pCodecCtx->height, i);
else
break;
}
#if 0
avcodec_decode_video(pCodecCtx, pFrame, &frameFinished, packet.data, packet.size);
// Did we get a video frame?
if (frameFinished) {
// Convert the image from its native format to RGB
img_convert((AVPicture *)pFrameRGB, AV_PIX_FMT_RGB24, (AVPicture *)pFrame,
pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height); // Save the frame to disk
if (++i <= 5)
SaveFrame(pFrameRGB, pCodecCtx->width, pCodecCtx->height, i);
}
#endif
}
}
// Free the packet that was allocate by av_read_frame
av_packet_unref(&packet); // Free the RGB image
av_free(buffer);
av_free(pFrameRGB); // Free the YUV frame
av_free(pFrame); // Close the codec
avcodec_close(pCodecCtx); // Close the video file
avformat_close_input(&pFormatCtx); return 0;
} void SaveFrame(AVFrame *pFrame, int width, int height, int iFrame)
{
FILE *pFile = NULL;
char szFilename[32] = {0};
int y = 0; // Open file
sprintf(szFilename, "./raw/frame%d.ppm", iFrame);
pFile = fopen(szFilename, "wb");
if (NULL == pFile)
return; // Write header
fprintf(pFile, "P6\n%d %d\n255\n", width, height); // Write pixel data
for (y = 0; y < height; y++)
fwrite(pFrame->data[0] + y * pFrame->linesize[0], 1, width * 3, pFile); // Close file
fclose(pFile); }

Makefile:

all:yuv2rgb
CC=gcc
CLIBSFLAGS=-lavformat -lavcodec -lavutil -lswresample -lswscale -lz -lpthread -lm
FFMPEG=/usr/local
CFLAGS=-I$(FFMPEG)/include/
LDFLAGS = -L$(FFMPEG)/lib/
yuv2rgb:yuv2rgb.o
$(CC) -o yuv2rgb yuv2rgb.o $(CLIBSFLAGS) $(CFLAGS) $(LDFLAGS)
yuv2rgb.o:yuv2rgb.c
$(CC) -o yuv2rgb.o -c yuv2rgb.c $(CLIBSFLAGS) $(CFLAGS) $(LDFLAGS)
clean:
rm yuv2rgb yuv2rgb.o

使用FFmpeg解码并用swscale将YUV转为RGB的更多相关文章

  1. 【视频处理】YUV与RGB格式转换

    YUV格式具有亮度信息和色彩信息分离的特点,但大多数图像处理操作都是基于RGB格式. 因此当要对图像进行后期处理显示时,需要把YUV格式转换成RGB格式. RGB与YUV的变换公式如下: YUV(25 ...

  2. YUV与RGB格式转换

    YUV格式具有亮度信息和色彩信息分离的特点,但大多数图像处理操作都是基于RGB格式. 因此当要对图像进行后期处理显示时,需要把YUV格式转换成RGB格式. RGB与YUV的变换公式如下: YUV(25 ...

  3. 【图像处理与医学图像处理】YUV与RGB格式转换速度几种方法对比

    [视频处理]YUV与RGB格式转换 YUV格式具有亮度信息和色彩信息分离的特点,但大多数图像处理操作都是基于RGB格式. 因此当要对图像进行后期处理显示时,需要把YUV格式转换成RGB格式. RGB与 ...

  4. 【DSP开发】【VS开发】YUV与RGB格式转换

    [视频处理]YUV与RGB格式转换 YUV格式具有亮度信息和色彩信息分离的特点,但大多数图像处理操作都是基于RGB格式. 因此当要对图像进行后期处理显示时,需要把YUV格式转换成RGB格式. RGB与 ...

  5. FFmpeg解码H264及swscale缩放详解

    本文概要: 本文介绍著名开源音视频编解码库ffmpeg如何解码h264码流,比较详细阐述了其h264码流输入过程,解码原理,解码过程.同时,大部分应用环境下,以原始码流视频大小展示并不是最佳方式,因此 ...

  6. (转)FFMPEG 实现 YUV,RGB各种图像原始数据之间的转换(swscale)

    雷霄骅分类专栏: FFMPEG FFmpeg 本文链接:https://blog.csdn.net/leixiaohua1020/article/details/14215391 FFMPEG中的sw ...

  7. 【图像处理】FFmpeg解码H264及swscale缩放详解

      http://blog.csdn.net/gubenpeiyuan/article/details/19548019 主题 FFmpeg 本文概要: 本文介绍著名开源音视频编解码库ffmpeg如何 ...

  8. 使用X264编码yuv格式的视频帧使用ffmpeg解码h264视频帧

    前面一篇博客介绍在centos上搭建点击打开链接ffmpeg及x264开发环境.以下就来问个样例: 1.利用x264库将YUV格式视频文件编码为h264格式视频文件 2.利用ffmpeh库将h264格 ...

  9. FFMPEG 实现 YUV,RGB各种图像原始数据之间的转换(swscale)

    FFMPEG中的swscale提供了视频原始数据(YUV420,YUV422,YUV444,RGB24...)之间的转换,分辨率变换等操作,使用起来十分方便,在这里记录一下它的用法. swscale主 ...

随机推荐

  1. cefsharp插入自定义JS

       string script_1 = "document.getElementsByTagName('head')[0].appendChild(document.createEleme ...

  2. php对函数的引用

    function &example($tmp=0){                  //定义一个函数,别忘了加“&”符     return $tmp;              ...

  3. Excel 2016 密码保护破解

    Excel 2016的密码保护可以区分为几个: 文件密码保护(Excel中叫做工作簿保护) 文件打开权限密码 文件修改权限密码 工作表保护 关于各个保护密码的设置方式请查阅其他资料,我的情况是之前自己 ...

  4. 集成学习(ensemble learning)

    集成学习,又称为“多分类器系统”(multi-classifier system).“基于委员会的学习”(committee-based learning)等.基本的想法是结合多个学习器,获得比单一学 ...

  5. tigervnc-server 无法启动问题

    [root@moodle-bak .X11-unix]# vncserver WARNING: The first attempt to start Xvnc failed, possibly bec ...

  6. mysql 5.7 enable binlog

    0. precondition a) install mysql 5.7, for  detail please refer my blog post. 1. login mysql and chec ...

  7. Chapter07 链表(下):如何轻松学出正确的链表代码?

    技巧一:理解指针或引用的含义 技巧二:指针丢失和内存泄漏 技巧三:利用哨兵简化实现难度 技巧四:重点留意边界条件处理 如果链表未空时,代码是否能够正常运行 如果链表只包含一个节点时,代码能否正常运行 ...

  8. Android 开发 将window变暗

    前言 在创建弹窗功能时,一般有需求将背景的window界面变暗.下面两组代码就实现了变暗与恢复的功能. 变暗 public void startDark(){ WindowManager.Layout ...

  9. IIS日志分析工具-Log Parser

    下载地址:https://www.microsoft.com/en-us/download/details.aspx?id=24659 参考链接: https://www.cnblogs.com/fu ...

  10. Git的操作理解

    1.本地和远程的关系相当于两个分支,是相互独立的. 2.本地分支属于本地仓库,一个仓库可以包含多个分支. 3.commit是为了告诉Git这次提交我改了哪些东西:       pull是将远程comm ...