首页 > 其他分享 >使用ffmpeg将MP4文件的每一帧保存为jpg图片

使用ffmpeg将MP4文件的每一帧保存为jpg图片

时间:2023-08-22 16:15:24浏览次数:42  
标签:include ffmpeg decoder ctx jpg MP4 ret av NULL

#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 <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avio.h>
#include <libavutil/file.h>
#include <libavutil/pixdesc.h>
#include <libavutil/imgutils.h>
#include <libswscale/swscale.h>

int file;

int saveAsJPEG(AVFrame *pFrame, int index) {
	fprintf(stdout, "ok   0  \n");
	int width = pFrame->width;
	int height = pFrame->height;
	AVCodecContext *pCodeCtx = NULL;
	char out_name[32];
	sprintf(out_name, "frame%d.png", index);
	fprintf(stdout, "out_name: %d \n", index);

	AVFormatContext *output_format_context = NULL;
	avformat_alloc_output_context2(&output_format_context, NULL, NULL,
			out_name);

	fprintf(stdout, "mime_type  %s \n",
			output_format_context->oformat->mime_type);
	// 构建一个新stream
	AVStream *pAVStream = avformat_new_stream(output_format_context, 0);
	if (pAVStream == NULL) {
		return -1;
	}

	AVCodecParameters *parameters = pAVStream->codecpar;
	parameters->codec_id = output_format_context->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);
	pCodeCtx = avcodec_alloc_context3(NULL);
	avcodec_parameters_to_context(pCodeCtx, pAVStream->codecpar);
	pCodeCtx->time_base = (AVRational ) { 1, 25 };
	avcodec_open2(pCodeCtx, pCodec, NULL);
	avformat_write_header(output_format_context, NULL);

	int y_size = width * height;

	AVPacket pkt;
	av_new_packet(&pkt, y_size * 10);

	printf("av_new_packet %d \n", index);
	int ret = avcodec_send_frame(pCodeCtx, pFrame);
	if (ret < 0) {
		perror("avcodec_send_frame");
		return -1;
	}

	ret = avcodec_receive_packet(pCodeCtx, &pkt);
	if (ret < 0) {
		perror("avcodec_receive_packet");
		return -1;
	}
	printf("start write packet to file\n");

	printf("pkt.size = %d\n", pkt.size);  //  62448

	if (write(file, pkt.data, pkt.size) < 0)
		perror("write");
	else
		printf("write success \n");

	ret = av_write_frame(output_format_context, &pkt);
	if (ret < 0) {
		printf("Could not av_write_frame");
		return -1;
	}

	av_packet_unref(&pkt);
	//Write Trailer
	av_write_trailer(output_format_context);
	avcodec_close(pCodeCtx);
	avio_close(output_format_context->pb);
	avformat_free_context(output_format_context);
//	av_packet_free(&pkt);
	return 0;
}

/**
 *   1280*720*12/8 =  1382400  bytes.
 *   img file size is  also  62448 bytes.
 *
 */
int main(int argc, char **argv) {
	int ret;
	file = open("output.yuv", O_WRONLY | O_CREAT | O_TRUNC);
	const char *inFileName = "../missu.mp4";
	AVFormatContext *ifmt_ctx = NULL;
	AVPacket *packet = NULL;
	packet = av_packet_alloc();
	AVFrame *pFrame = NULL;
	AVCodecContext *decode_ctx;

	pFrame = av_frame_alloc();

	if (avformat_open_input(&ifmt_ctx, inFileName, NULL, NULL) != 0) {
		perror("avformat_open_input");
		return -1;
	}

	if (avformat_find_stream_info(ifmt_ctx, NULL) < 0) {
		perror("avformat_find_stream_info");
		fprintf(stdout, "Couldn't find stream information \n");
		return -1;
	}

//	av_dump_format(ifmt_ctx, 0, NULL, 0);

	printf("streams number : %d \n", ifmt_ctx->nb_streams);

	if (ifmt_ctx->nb_streams == 0) {
		printf("nb_streams is 0,exit \n");
		return -1;
	}

	// Find the first video stream
	int videoStream = av_find_best_stream(ifmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1,
	NULL, 0);

	if (videoStream == -1) {
		printf("Didn't find a video stream  \n");
		return -1;
	}

	AVStream *stream = ifmt_ctx->streams[videoStream];
	// Copy contexts
	const AVCodec *decoder = avcodec_find_decoder(stream->codecpar->codec_id);

	printf("decoder->name =  %s  \n", decoder->name);  // h264
	printf("decoder->long_name =  %s  \n", decoder->long_name);
	printf("decoder->type =  %s  \n", decoder->type);
//	printf("decoder->type =  %d  \n",decoder->pix_fmts[0]);
	printf("decoder->AVCodecID =  %d  \n", decoder->id);  //AV_CODEC_ID_H264

	decode_ctx = avcodec_alloc_context3(decoder);

	if (!decode_ctx) {
		fprintf(stderr, "Could not allocate video codec context\n");
		exit(1);
	}

	ret = avcodec_parameters_to_context(decode_ctx, stream->codecpar);

	if (ret < 0) {
		av_log(NULL, AV_LOG_ERROR,
				"Failed to copy decoder parameters to input decoder context "
						"for stream\n");
		return ret;
	}

	ret = avcodec_open2(decode_ctx, decoder, NULL);
	if (ret < 0) {
		av_log(NULL, AV_LOG_ERROR, "Failed to open decoder for stream \n");
		return ret;
	}

	int i = 0;
	while (av_read_frame(ifmt_ctx, packet) >= 0) {
		if (packet->stream_index == videoStream) {
			i++;
			dd: ret = avcodec_send_packet(decode_ctx, packet);
			if (ret < 0) {
				if (ret == AVERROR(EAGAIN)) {
					av_log(NULL, AV_LOG_ERROR, "AVERROR(EAGAIN) \n");
				}

				av_log(NULL, AV_LOG_ERROR, "Decoding failed: %d \n", ret);
				break;
			}

			ret = avcodec_receive_frame(decode_ctx, pFrame);
			if (ret == AVERROR(EAGAIN)) {
				goto dd;

			}
			if (ret != 0) {
				av_log(NULL, AV_LOG_ERROR,
						"avcodec_receive_frame: failed %d \n", ret);
				break;
			}
			if (ret == 0) {
				fprintf(stdout, "we get a video frame  \n");
				saveAsJPEG(pFrame, i);
			}
		}
	}

	end: av_frame_free(&pFrame);
	av_packet_free(&packet);
	avformat_close_input(&ifmt_ctx);
	return 0;
}
 

标签:include,ffmpeg,decoder,ctx,jpg,MP4,ret,av,NULL
From: https://www.cnblogs.com/lidabo/p/17648766.html

相关文章

  • windows 32位系统和64位系统ffmpeg下载
    64位下载Releases·BtbN/FFmpeg-Builds(github.com)  32位下载https://github.com/sudo-nautilus/FFmpeg-Builds-Win32/releases/tag/latest  ......
  • COMP4650 文档分析
    COMP4650COMP4650/6490DocumentAnalysis–Semester2/2023Assignment1Due17:00onWednesday16August2023AEST(UTC+10)LastupdatedJuly28,2023OverviewInthisassignment,yourtaskistoimplementabasicbooleanandrankedinformationretrieval(IR......
  • Python实现pdf转jpg
    自己电脑没找到软件用,想到python参考:https://zyicu.cn/?p=7656代码:(还可以调整分辨率)#-*-coding:utf-8-*-"""1、安装库pipinstallpymupdf2、直接运行"""importosimportfitzpdf_dir=[]defget_file():docunames=os.listdir()for......
  • OpenCV3.2图像分割 实例1:读取单张JPG图像(测试环境)
    1#include<opencv2/opencv.hpp>2#include<iostream>34usingnamespacecv;56intmain(intargc,char**argv)7{8Matsrc=imread("toux.jpg");//读取图像9if(src.empty())10{11printf("cou......
  • 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......
  • 将memo转化为JPG输出
    units1;interfaceuses Windows,Messages,SysUtils,Graphics,Controls,Forms,StdCtrls, Classes;type TForm1=class(TForm) Button1:TButton; Memo1:TMemo; procedureButton1Click(Sender:TObject); private {Privatedeclarations} public {Publicdecla......
  • 显示 jpg、png、gif 图片及 gif 动画
    unitUnit1;interfaceusesWindows,Messages,SysUtils,Variants,Classes,Graphics,Controls,Forms,Dialogs,StdCtrls,ExtCtrls;typeTForm1=class(TForm) Button1:TButton; Button2:TButton; Button3:TButton; Button4:TButton; procedureButton1Click(Sender:......
  • [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流协议格式进行......