Windows10 + FFmpeg + VS2010 使用FFmpeg解码视频之保存图片
2019-02-13 15:38
381 查看
参考链接:http://blog.yundiantech.com/?log=blog&id=8
Windows10 + FFmpeg + VS2010 使用FFmpeg解码视频之保存图片
基于上一篇博文,配置好环境,并且小试牛刀之后,趁热打铁,再进行一个小工程。
打开VS2010,新建一个win32控制台应用程序,在debug64位下,进行编写。各种lib include dll的配置,参看上一篇博文。
功能内容:mp4的视频,截取视频流,保存成图片。代码如下:
[code]#include "stdafx.h" #include<iostream> #include<stdio.h> using namespace std; extern "C" { #include "libavcodec/avcodec.h" #include "libavformat/avformat.h" #include "libavutil/pixfmt.h" #include "libswscale/swscale.h" } // 定义SaveFrame函数,把RGB信息搞到一个PPM格式的文件中 // 生成一个简单的PPM格式的文件 void SaveFrame(AVFrame *pFrame, int width, int height, int index) { FILE *pFile; char szFilename[32]; // open file sprintf(szFilename, "frame%d.ppm", index); pFile = fopen(szFilename, "wb"); if(pFile == NULL) return ; //write header fprintf(pFile, "P6 %d %d 255", width, height); // write poxel data for(int y = 0; y < height; ++y) { fwrite(pFrame->data[0] + y * pFrame->linesize[0], 1, width * 3, pFile); } fclose(pFile); } int _tmain(int argc, _TCHAR* argv[]) { char *file_path = "D:\\Tkinter14.mp4"; // 据说:打开的视频文件,不要有中文,否则会失败 // 定义一些变量。 AVFormatContext *pFormatCtx; AVCodecContext *pCodecCtx; AVCodec *pCodec; AVFrame *pFrame, *pFrameRGB; AVPacket *packet; uint8_t *out_buffer; static struct SwsContext *img_convert_ctx; av_register_all(); // 初始化FFMPEG, 调用了这个函数才能正常使用编码器和解码器 pFormatCtx = avformat_alloc_context(); // 分配一个AVFormatContext,FFMPEG所有的操作都要通过这个AVFormatContext来进行 if (avformat_open_input(&pFormatCtx, file_path, NULL, NULL) != 0) { printf("Can not open the file."); return -1; } if (avformat_find_stream_info(pFormatCtx, NULL) < 0) { printf("Can not find stream information."); return -1; } int videoStream; videoStream = -1; // 循环查找视频中包含的流信息,知道找到视频类型的流 // 便将其记录下来,保存到videoStream变量中, // 这里我们现在只处理视频流,音频流先不管 for(int i = 0; i < pFormatCtx->nb_streams; ++i) { if(pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { videoStream = i; } } // 如果videoStream为-1,说明没有找到视频流 if(videoStream == -1) { printf("Can not find a video stream."); return -1; } // *** 根据视频流,打开一个解码器来解码 // 查找解码器 pCodecCtx = pFormatCtx->streams[videoStream]->codec; pCodec = avcodec_find_decoder(pCodecCtx->codec_id); if(pCodec == NULL) { printf("Codec not found!"); return -1; } // 打开解码器 if(avcodec_open2(pCodecCtx, pCodec, NULL) < 0) { printf("Can not open codec."); return -1; } pFrame = av_frame_alloc(); // 为其开辟空间 pFrameRGB = av_frame_alloc(); 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); // 原文件中,PIX_FMT_BGR24改为AV_PIX_FMT_BGR24,即可 int numBytes; numBytes = avpicture_get_size(AV_PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height); out_buffer = (uint8_t *)av_malloc(numBytes * sizeof(uint8_t)); avpicture_fill((AVPicture *)pFrameRGB, out_buffer, AV_PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height); // *** 开始读取视频 int y_size = pCodecCtx->width * pCodecCtx->height; packet = (AVPacket*)malloc(sizeof(AVPacket)); // 分配一个packet av_new_packet(packet, y_size); // 分配packet的数据 av_dump_format(pFormatCtx, 0, file_path, 0); // 输出视频信息 int index = 0; int ret, got_picture; while(1) { if(av_read_frame(pFormatCtx, packet) < 0) { //return -1; break; // 读取完视频,退出. } // *** 对视频进行解码 if(packet->stream_index == videoStream) { ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet); if(ret < 0) { printf("decode error."); return -1; } // *** 解码之后的图像数据都是YUV420格式,将其保存为图片文件,则需要将YUV420转换为RGB格式 if(got_picture) { sws_scale(img_convert_ctx, (uint8_t const * const *)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize); // *** 将得到的RGB数据 直接写入文件。 SaveFrame(pFrameRGB, pCodecCtx->width, pCodecCtx->height, ++index); // 保存图片 if (index > 20) { return 0; // 先保存20张图片 } } } av_free_packet(packet); } // 释放空间 av_free(out_buffer); av_free(pFrameRGB); avcodec_close(pCodecCtx); avformat_close_input(&pFormatCtx); return 0; }
进行测试代码时,每个return 语句处,打一个断点进行跟踪。
结果显示,无法找到文件。
使用下面这段代码,如截图中所示,添加,查看输出的错误是啥。
// 此段主要是检查错误码用。
char buf[] = "";
int err_code = avformat_open_input(&pFormatCtx, file_path, NULL, NULL);
av_strerror(err_code, buf, 1024);
printf("Can not open the file.%s: %d(%s)\n", file_path, err_code, buf);
错误显示,找不到文件。原来是我的文件路径写错了,少了一个转译符\
修改后,即可用。(记录此错误,方便自己回顾。原文中的代码,没有问题。)
相关文章推荐
- 从零开始学习音视频编程技术(五) 使用FFMPEG解码视频之保存成图片
- 0基础学习音视频编程技术(四) 使用FFMPEG解码视频之保存成图片
- 从零开始学习音视频编程技术(五) 使用FFMPEG解码视频之保存成图片
- FFMPEG教程1_解码后保存图片(使用2014年新SDK重新整理编译通过)
- ffmpeg解码mp4视频数据保存成图片
- 使用ffmpeg将BMP图片编码为x264视频文件,将H264视频保存为BMP图片,yuv视频文件保存为图片的代码
- 使用ffmpeg将BMP图片编码为x264视频文件,将H264视频保存为BMP图片,yuv视频文件保存为图片的代码
- 使用ffmpeg将BMP图片编码为x264视频文件,将H264视频保存为BMP图片,yuv视频文件保存为图片的代码
- ffmpeg将视频每帧画面保存为PPM格式图片,使用最新的ffmpeg官网15-7-2日更新的版本
- 通过C++/CLI使用FFMPEG库进行视频解码[初步]
- Qt5.3里使用OpenCV库采集摄像头图像保存为图片和视频
- 使用FFMPEG3.4.2版本进行视频的解码为YUV格式
- 【视频编解码】Linux下FFmpeg编译安装及其ffplay的安装使用
- Glide的使用(加载图片,动态图,缩略图,视频解码等)
- Linux下使用convert对图片缩放和使用ffmpeg对视频进行转换
- 使用ffmpeg-1.0内置RTMP协议实时解码H264视频流
- 在iOS平台使用ffmpeg解码h264视频流
- 使用 ffmpeg 截取视频文件图片
- 使用 ffmpeg 进行网络推流:拉流->解封装->解码->处理原始数据(音频、视频)->编码->编码->推流
- VS2013中使用ffmpeg解码视频