首页 > 其他分享 >FFmpeg将视频转换成一帧一帧的jpeg图片(代码实现)

FFmpeg将视频转换成一帧一帧的jpeg图片(代码实现)

时间:2023-08-22 16:37:44浏览次数:133  
标签:一帧 stream frame jpeg codec av NULL avcodec FFmpeg

 
  #include <iostream>   using namespace std;   extern "C"   {   #include "libavcodec/avcodec.h"   #include "libavformat/avformat.h"   #include "libswscale/swscale.h"   #include "libavutil/imgutils.h"   }   int savePicture(AVFrame *pFrame, char *out_name) ;   int main(int argc, char *argv[]) {//解码视频   int ret;   const char *in_filename, *out_filename;   AVFormatContext *fmt_ctx = NULL;       const AVCodec *codec;   AVCodecContext *codeCtx = NULL;       AVStream *stream = NULL;   int stream_index;       AVPacket avpkt;       int frame_count;   AVFrame *frame;           if (argc <= 2) {   printf("Usage: %s <input file> <output file>\n", argv[0]);   exit(0);   }   in_filename = argv[1];   out_filename = argv[2];       // 1   if (avformat_open_input(&fmt_ctx, in_filename, NULL, NULL) < 0) {   printf("Could not open source file %s\n", in_filename);   exit(1);   }       if (avformat_find_stream_info(fmt_ctx, NULL) < 0) {   printf("Could not find stream information\n");   exit(1);   }       av_dump_format(fmt_ctx, 0, in_filename, 0);       av_init_packet(&avpkt); //初始化AVPacket,只是单纯初始化avpkt字段   avpkt.data = NULL;   avpkt.size = 0;       // 2   stream_index = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);   if (ret < 0) {   fprintf(stderr, "Could not find %s stream in input file '%s'\n",   av_get_media_type_string(AVMEDIA_TYPE_VIDEO), in_filename);   return ret;   }       stream = fmt_ctx->streams[stream_index];       // 3   codec = avcodec_find_decoder(stream->codecpar->codec_id); //查找指定的解码器   if (codec == NULL) {   return -1;   }       // 4   codeCtx = avcodec_alloc_context3(NULL); //分配解码器上下文   if (!codeCtx) {   fprintf(stderr, "Could not allocate video codec context\n");   exit(1);   }           // 5   if ((ret = avcodec_parameters_to_context(codeCtx, stream->codecpar)) < 0) { //将AVCodecParameters对象转为AVCodecContext对象   fprintf(stderr, "Failed to copy %s codec parameters to decoder context\n",   av_get_media_type_string(AVMEDIA_TYPE_VIDEO));   return ret;   }       // 6   avcodec_open2(codeCtx, codec, NULL); //打开解码器和关联解码器上下文           //初始化frame,解码后数据   frame = av_frame_alloc();   if (!frame) {   fprintf(stderr, "Could not allocate video frame\n");   exit(1);   }       frame_count = 0;   char buf[1024];   // 7   while (av_read_frame(fmt_ctx, &avpkt) >= 0) {   if (avpkt.stream_index == stream_index) {   // 8   int re = avcodec_send_packet(codeCtx, &avpkt); //发送给解码器   if (re < 0) {   continue;   }       // 9 这里必须用while(),因为一次avcodec_receive_frame可能无法接收到所有数据   while (avcodec_receive_frame(codeCtx, frame) == 0) { //接收解码后的帧   // 拼接图片路径、名称   snprintf(buf, sizeof(buf), "%s/picture-%d.jpg", out_filename, frame_count); //将 out_filename/picture-frame_count.jpg 复制到buf   savePicture(frame, buf); //保存为jpg图片   }       frame_count++;   }   av_packet_unref(&avpkt);   }       }   int savePicture(AVFrame *pFrame, char *out_name) {//编码保存图片       int width = pFrame->width;   int height = pFrame->height;   AVCodecContext *pCodeCtx = NULL;           AVFormatContext *pFormatCtx = avformat_alloc_context();   // 设置输出文件格式   pFormatCtx->oformat = av_guess_format("mjpeg", NULL, NULL);       // 创建并初始化输出AVIOContext   if (avio_open(&pFormatCtx->pb, out_name, AVIO_FLAG_READ_WRITE) < 0) {   printf("Couldn't open output file.");   return -1;   }       // 构建一个新stream   AVStream *pAVStream = avformat_new_stream(pFormatCtx, 0);   if (pAVStream == NULL) {   return -1;   }       AVCodecParameters *parameters = pAVStream->codecpar;   parameters->codec_id = pFormatCtx->oformat->video_codec;   parameters->codec_type = AVMEDIA_TYPE_VIDEO;   parameters->format = AV_PIX_FMT_YUVJ420P;   parameters->width = pFrame->width;   parameters->height = pFrame->height;       AVCodec *pCodec = avcodec_find_encoder(pAVStream->codecpar->codec_id); //查找编码器       if (!pCodec) {   printf("Could not find encoder\n");   return -1;   }       pCodeCtx = avcodec_alloc_context3(pCodec); //为AVCodecContext分配内存   if (!pCodeCtx) {   fprintf(stderr, "Could not allocate video codec context\n");   exit(1);   }       if ((avcodec_parameters_to_context(pCodeCtx, pAVStream->codecpar)) < 0) {   fprintf(stderr, "Failed to copy %s codec parameters to decoder context\n",   av_get_media_type_string(AVMEDIA_TYPE_VIDEO));   return -1;   }       pCodeCtx->time_base = (AVRational) {1, 25};       if (avcodec_open2(pCodeCtx, pCodec, NULL) < 0) { //打开编码器   printf("Could not open codec.");   return -1;   }       int ret = avformat_write_header(pFormatCtx, NULL);   if (ret < 0) {   printf("write_header fail\n");   return -1;   }       int y_size = width * height;       //Encode   // 给AVPacket分配足够大的空间   AVPacket pkt;   av_new_packet(&pkt, y_size * 3);       // 编码数据   ret = avcodec_send_frame(pCodeCtx, pFrame);   if (ret < 0) {   printf("Could not avcodec_send_frame.");   return -1;   }       // 得到编码后数据   ret = avcodec_receive_packet(pCodeCtx, &pkt);   if (ret < 0) {   printf("Could not avcodec_receive_packet");   return -1;   }       ret = av_write_frame(pFormatCtx, &pkt);       if (ret < 0) {   printf("Could not av_write_frame");   return -1;   }       av_packet_unref(&pkt);       //Write Trailer   av_write_trailer(pFormatCtx);           avcodec_close(pCodeCtx);   avio_close(pFormatCtx->pb);   avformat_free_context(pFormatCtx);       return 0;   }
 
 

 

 

标签:一帧,stream,frame,jpeg,codec,av,NULL,avcodec,FFmpeg
From: https://www.cnblogs.com/lidabo/p/17648868.html

相关文章

  • ffmpeg把读取的视频流保存为jpeg文件
    intimg_savejpeg(AVFrame*pFrame,char*out_filename){//视频流保存为jpegintwidth=pFrame->width;intheight=pFrame->height;AVCodecContext*pCodeCtx=NULL;AVFormatContext*pFormatCtx=avformat_alloc_context();//设置输出文件格式pFormatCtx->oformat=av......
  • 使用ffmpeg将MP4文件的每一帧保存为jpg图片
    #include<stdio.h>#include<stdlib.h>#include<string.h>#include<unistd.h>#include<fcntl.h>#include<sys/ioctl.h>#include<string.h>#include<sys/mman.h>#include<assert.h>#include<liba......
  • windows 32位系统和64位系统ffmpeg下载
    64位下载Releases·BtbN/FFmpeg-Builds(github.com)  32位下载https://github.com/sudo-nautilus/FFmpeg-Builds-Win32/releases/tag/latest  ......
  • Win11+ VS2022编译 FFmpeg6.0 静态库
    目录编译前言为什么项目编译?前期准备环境配置ffmpeg外部库额外的编译选项-for渲染opengl(需要glext)ffnvcodec(需要nv-codec-headers)AMFsdk头文件编译工具链开始编译step1.选择编译类型Debug/ReleaseDll/libstep2.打包SDK验证结尾参考链接编译前言编译作为自己持有......
  • Qt+rtsp+ffmpeg 播放声音
    #include<QtCore/QCoreApplication>#include<QtMultimedia/QAudioFormat>#include<QtMultimedia/QAudioOutput>#include<QtCore/QFile>#include<iostream>#ifdef__cplusplusextern"C"{#endif//__cplusplus#include"li......
  • [Multimedia][ffmpeg] 音频音量获取
    ffmpeg-i~/media/test.mp4-filter_complexvolumedetect-c:vcopy-fnull/dev/null...[Parsed_volumedetect_0@0x7f83a481c000]n_samples:23887872[Parsed_volumedetect_0@0x7f83a481c000]mean_volume:-16.7dB[Parsed_volumedetect_0@0x7f83a481c000]......
  • Windows上使用FFmpeg实现本地视频推送模拟海康协议rtsp视频流
    场景Nginx搭建RTMP服务器+FFmpeg实现海康威视摄像头预览:https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/121202130上面记录的是使用FFmpeg拉取海康协议摄像头的rtsp流并推流到流媒体服务器。如果在其它业务场景下需要本地的视频文件模拟海康的rtsp流协议格式进行......
  • ffmpeg 之 sdl
    使用ffmpeg解码视频渲染到sdl窗口前言使用ffmpeg解码视频并渲染视频到窗口,网上是有不少例子的,但是大部分例子的细节都不是很完善,比如资源释放、flush解码缓存、多线程优化等都没有。特别是想要快速搭建一个demo时,总是要重新编写不少代码,比较不方便,所以在这里提供一个完善的例子,......
  • 记录 FFmpeg开发常用功能封装
    说明记录下个人在开发中使用到的FFmpeg常用功能,避免相同功能代码的重复编写,使用时直接复制提升效率。由于音视频处理的场景众多,无法编写完全通用的方法接口,可能需根据实际场景进行一定的修改,本文章中的代码也将持续更新优化。代码这里提供ffmpegheader.h,ffmpegheader.cpp。配......
  • 使用FFmpeg进行yuv420转rgba
    讲解一下将获取到视频数据,进行rgb转码,并且进行相应的缩放操作//存放解码过后的数据unsignedchar*decode_data;intdecode_size=0;/***解码AVFrame中的yuv420数据并且转换为rgba数据**@paramframe需要解码的帧结构*@paramsrc_width需要转换的帧宽度*......