当前位置: 代码迷 >> 综合 >> Windows10 + FFmpeg + VS2010 使用FFmpeg解码视频之保存图片
  详细解决方案

Windows10 + FFmpeg + VS2010 使用FFmpeg解码视频之保存图片

热度:104   发布时间:2023-10-15 19:28:34.0

参考链接:http://blog.yundiantech.com/?log=blog&id=8

Windows10 + FFmpeg + VS2010 使用FFmpeg解码视频之保存图片

基于上一篇博文,配置好环境,并且小试牛刀之后,趁热打铁,再进行一个小工程。

打开VS2010,新建一个win32控制台应用程序,在debug64位下,进行编写。各种lib include dll的配置,参看上一篇博文。

功能内容:mp4的视频,截取视频流,保存成图片。代码如下:

#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 filesprintf(szFilename, "frame%d.ppm", index);pFile = fopen(szFilename, "wb");if(pFile == NULL)return ;//write headerfprintf(pFile, "P6 %d %d 255", width, height);// write poxel datafor(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));                // 分配一个packetav_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 语句处,打一个断点进行跟踪。

结果显示,无法找到文件。

Windows10 + FFmpeg + VS2010 使用FFmpeg解码视频之保存图片

使用下面这段代码,如截图中所示,添加,查看输出的错误是啥。

        // 此段主要是检查错误码用。
        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);

 

错误显示,找不到文件。原来是我的文件路径写错了,少了一个转译符\

修改后,即可用。(记录此错误,方便自己回顾。原文中的代码,没有问题。)

  相关解决方案