使用FFmpeg解码并用swscale将YUV转为RGB
#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的更多相关文章
- 【视频处理】YUV与RGB格式转换
YUV格式具有亮度信息和色彩信息分离的特点,但大多数图像处理操作都是基于RGB格式. 因此当要对图像进行后期处理显示时,需要把YUV格式转换成RGB格式. RGB与YUV的变换公式如下: YUV(25 ...
- YUV与RGB格式转换
YUV格式具有亮度信息和色彩信息分离的特点,但大多数图像处理操作都是基于RGB格式. 因此当要对图像进行后期处理显示时,需要把YUV格式转换成RGB格式. RGB与YUV的变换公式如下: YUV(25 ...
- 【图像处理与医学图像处理】YUV与RGB格式转换速度几种方法对比
[视频处理]YUV与RGB格式转换 YUV格式具有亮度信息和色彩信息分离的特点,但大多数图像处理操作都是基于RGB格式. 因此当要对图像进行后期处理显示时,需要把YUV格式转换成RGB格式. RGB与 ...
- 【DSP开发】【VS开发】YUV与RGB格式转换
[视频处理]YUV与RGB格式转换 YUV格式具有亮度信息和色彩信息分离的特点,但大多数图像处理操作都是基于RGB格式. 因此当要对图像进行后期处理显示时,需要把YUV格式转换成RGB格式. RGB与 ...
- FFmpeg解码H264及swscale缩放详解
本文概要: 本文介绍著名开源音视频编解码库ffmpeg如何解码h264码流,比较详细阐述了其h264码流输入过程,解码原理,解码过程.同时,大部分应用环境下,以原始码流视频大小展示并不是最佳方式,因此 ...
- (转)FFMPEG 实现 YUV,RGB各种图像原始数据之间的转换(swscale)
雷霄骅分类专栏: FFMPEG FFmpeg 本文链接:https://blog.csdn.net/leixiaohua1020/article/details/14215391 FFMPEG中的sw ...
- 【图像处理】FFmpeg解码H264及swscale缩放详解
http://blog.csdn.net/gubenpeiyuan/article/details/19548019 主题 FFmpeg 本文概要: 本文介绍著名开源音视频编解码库ffmpeg如何 ...
- 使用X264编码yuv格式的视频帧使用ffmpeg解码h264视频帧
前面一篇博客介绍在centos上搭建点击打开链接ffmpeg及x264开发环境.以下就来问个样例: 1.利用x264库将YUV格式视频文件编码为h264格式视频文件 2.利用ffmpeh库将h264格 ...
- FFMPEG 实现 YUV,RGB各种图像原始数据之间的转换(swscale)
FFMPEG中的swscale提供了视频原始数据(YUV420,YUV422,YUV444,RGB24...)之间的转换,分辨率变换等操作,使用起来十分方便,在这里记录一下它的用法. swscale主 ...
随机推荐
- Windows平台安装配置mysql数据库
Windows平台安装配置mysql数据库 作者:Eric 微信:loveoracle11g 去下载mysql软件 https://www.mysql.com/downloads/ https://d ...
- BAT开发中,ChromeDriver版本兼容性检查
打开解决方案的Nuget包管理器,选择合适的版本,安装即可.版本的兼容性检查,见上一篇blog(初次使用BAT,请检查Chrome浏览器和ChromeDriver兼容性 https://www.cnb ...
- [纯C#实现]基于BP神经网络的中文手写识别算法
效果展示 这不是OCR,有些人可能会觉得这东西会和OCR一样,直接进行整个字的识别就行,然而并不是. OCR是2维像素矩阵的像素数据.而手写识别不一样,手写可以把用户写字的笔画时间顺序,抽象成一个维度 ...
- 1.Java
面向对象:封装,继承,多态 A组合B:那么B就可以调用A中的方法 A关联B:A中的成员变量是用B声明的 A和B的依赖关系:A中某个方法的参数是B声明的对象或者返回值类型是B的数据类型 Static方法 ...
- TestNG实现日志输出
这里介绍的是TestNG中的Report类来实现简单的log输出这个很简单直接看例子吧 package com.rrx.test; import java.io.IOException; import ...
- LinkedHashMap和TreeMap的有序性
做一个数组的多属性动态排序的功能,使用map时发现有序性问题. LinkedHashMap会存储数据的插入顺序,是进入时有序:TreeMap则是默认key升序,是进入后有序(hashMap .hash ...
- Python爬虫的步骤和工具
#四个步骤 1.查看crawl内容的源码格式 crawl的内容可以是 url(链接),文字,图片,视频 2.请求网页源码 (可能要设置)代理,限速,cookie 3.匹配 用正则表达 ...
- 域名动态解析到动态IP
一般宽带用户的IP都是动态IP,重连之后IP可能会发生变化. 如果想在其他地方连接家里的设备,或者在家中搭建服务器,就会受到影响. 现在提供一种动态解析域名的方式,只要检测到IP的变化,那么就调用阿里 ...
- shell脚本实现telnet测试服务端口
备注,使用方法:当前目录下要存在需要测试的地址端口的文件ip.txt,例子:cat ip.txt141.12.65.17 7500 #!/bin/bashcur_dir=$(pwd)ipfile=$c ...
- idea搭建ssm框架
1.file-->new-->project-->maven.... 2.建立后的目录: 3.pom.xml依赖建立: <?xml version="1.0" ...