ffmpeg 解码264 抽帧保存mp4

目录

前7帧编码为新mp4

ffmpeg读取rtsp并保存到mp4文件

ffmpeg4 解码264 输出rgb


前7帧编码为新mp4

ffmpeg -i aaa.mp4 -vframes 7 -c:v libx264 -c:a copy aaa_7.mp4

ffmpeg读取rtsp并保存到mp4文件

ffmpeg读取rtsp并保存到mp4文件_ffmpeg rtsp 流写入mp4-CSDN博客

ffmpeg4 解码264 输出rgb

int play_file(char* file_name, FrameFunc tcallback(char* a, int size, int num, int height, int width))
{

	av_log_set_level(AV_LOG_WARNING);
	unsigned version = avcodec_version();

	printf("FFmpeg version: %d\n", version);

	AVFormatContext *avFormatCtx = NULL;
	int            i, videoindex;
	AVCodecContext  *avCodecCtx=NULL;
	AVCodec        *avCodec;
	avformat_network_init();
	printf("1111\n");
	FILE *fp_open = fopen(file_name, "rb+");
	unsigned char *aviobuffer = (unsigned char *)av_malloc(32768);
	AVIOContext *avio = avio_alloc_context(aviobuffer, 32768, 0, (void*)fp_open, file_buffer, NULL, NULL);
	printf("222\n");
	avFormatCtx = avformat_alloc_context();
	avFormatCtx->pb = avio;
	//if (avformat_open_input(&pFormatCtx, patha.c_str(), NULL, NULL) != 0) {
	if (avformat_open_input(&avFormatCtx, NULL, NULL, NULL) != 0) {
		printf("Couldn't open input stream.\n");
		return -1;
	}
	avCodec = NULL;
	while (avCodec == NULL) {
		printf("start find stream info \n");
		if (avformat_find_stream_info(avFormatCtx, NULL) < 0) {
			printf("Couldn't find stream info\n");
			goto restart_stream;
			continue;
		}
		videoindex = -1;
		for (i = 0; i < avFormatCtx->nb_streams; i++)
			if (avFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
				if (videoindex == -1) {
					videoindex = i;
				}
				//break;
			}
		if (videoindex == -1) {
			printf("Didn't find a video stream.\n");
			goto restart_stream;
		}
		avCodecCtx = avcodec_alloc_context3(NULL);
		avcodec_parameters_to_context(avCodecCtx, avFormatCtx->streams[videoindex]->codecpar);
		avCodec = avcodec_find_decoder(avCodecCtx->codec_id);
		if (avCodec == NULL) {
			printf("Codec not found \n");
			goto restart_stream;
			//return -1;
		}
		if (avcodec_open2(avCodecCtx, avCodec, NULL) < 0) {
			printf("Could not open codec.\n");
			goto restart_stream;
			continue;
			//return -1;
		}
		goto ok;
	restart_stream:
		printf("restart 1  ");
		avformat_free_context(avFormatCtx);
		printf("restart 2  ");
		//avformat_close_input(&pFormatCtx);
		avFormatCtx = NULL;
		avFormatCtx = avformat_alloc_context();
		printf("restart 3  ");
		av_freep(aviobuffer);
		//printf("restart 4");
		aviobuffer = (unsigned char *)av_malloc(32768);
		printf("restart 4  ");
		AVIOContext *avio2 = avio_alloc_context(aviobuffer, 32768, 0, &fp_open, file_buffer, NULL, NULL);
		avFormatCtx->pb = avio2;

		int open_ret = avformat_open_input(&avFormatCtx, NULL, NULL, NULL);
		if (open_ret != 0) {
			printf("2Couldn't open input stream %d\n", open_ret);
			return -1;
		}
		avFormatCtx->probesize = 1000 * 1024;
		avFormatCtx->max_analyze_duration = 10 * AV_TIME_BASE;
		printf("restart 5\n");
		avCodec = NULL;
		continue;
	ok:
		break;
	}

	AVFrame *pFrameYUV;
	AVFrame *pFrameRGB;
	pFrameYUV = av_frame_alloc();
	pFrameRGB = av_frame_alloc();

	
	uint8_t *out_buffer;

	struct SwsContext *img_convert_ctx;
	img_convert_ctx = sws_getContext(avCodecCtx->width, avCodecCtx->height, avCodecCtx->pix_fmt, avCodecCtx->width, avCodecCtx->height, AV_PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL);

	out_buffer = new uint8_t[avpicture_get_size(AV_PIX_FMT_RGB24, avCodecCtx->width, avCodecCtx->height)];
	//avpicture_fill((AVPicture *)pFrameRGB, out_buffer, AV_PIX_FMT_RGB24, avCodecCtx->width, avCodecCtx->height);
	av_image_fill_arrays(pFrameRGB->data, pFrameRGB->linesize, out_buffer, AV_PIX_FMT_RGB24, avCodecCtx->width, avCodecCtx->height, 1);

	int ret, got_picture;

	AVPacket packet;// = (AVPacket *)av_malloc(sizeof(AVPacket));

	int need_decode = 1;
	int is_key_frame = 0;
	
	while (av_read_frame(avFormatCtx, &packet) >= 0) {
		if (packet.stream_index == videoindex) {
			DWORD start_time = GetTickCount();
			if (avcodec_send_packet(avCodecCtx, &packet) != 0) {
				printf("avcodec_send_packet错误\n");
				break;
			}

		/*	if (packet.flags &AV_PKT_FLAG_KEY) {
				is_key_frame = 1;
				need_decode = 1;
				printf("key frame %d\n", need_decode);
			}
			else {
				is_key_frame = 0;
			}
			if (!need_decode) {
				av_packet_unref(&packet);
				printf("not key frame \n");
				continue;
			}*/
			while (avcodec_receive_frame(avCodecCtx, pFrameYUV) == 0) {

					int ret = avcodec_send_frame(avCodecCtx, pFrameYUV);
					pFrameYUV->pts++;
	
					printf("decode ok %d %u\n", avCodecCtx->flags, GetTickCount()-start_time);
				
		
					/*fwrite(pFrameYUV->data[0], (pCodecCtx->width)*(pCodecCtx->height) * 3, 1, output);*/

					sws_scale(img_convert_ctx, pFrameYUV->data, pFrameYUV->linesize, 0, avCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);

					tcallback((char*)pFrameRGB->data[0], avCodecCtx->height * avCodecCtx->width * 3, 1, avCodecCtx->height, avCodecCtx->width);
					avcodec_flush_buffers(avCodecCtx);
					//av_frame_free(&pFrameYUV);
				
			}
		}
		av_packet_unref(&packet);
	}


	avcodec_close(avCodecCtx);
	avformat_close_input(&avFormatCtx);
	return 0;
}

FFmpeg是一套开源软件,可以用来编码、解码、合成和转换音频和视频数据。它提供了丰富的音视频处理功能,并支持对多种音视频格式的读取和处理。如果你的工作涉及到视频相关的内容,那么掌握FFmpeg是必不可少的。 在FFmpeg中,要实现视频抽帧的功能,可以使用一些命令和参数。具体的步骤如下: 1. 首先,确保已经安装了FFmpeg软件,并将其路径添加到系统环境变量中。 2. 打开命令行界面,进入到包含要处理视频的目录。 3. 使用以下命令格式进行视频抽帧操作: ``` ffmpeg -ss [时间点 -i [输入视频文件 -vframes 1 [输出图片文件] ``` 其中,[时间点]表示想要抽取的视频帧的时间点,格式为HH:MM:SS;[输入视频文件]表示要处理的视频文件名;输出图片文件]表示要保存抽帧结果图片文件名。 例如,要在视频的第30秒抽取一帧作为图片,可以使用以下命令: ``` ffmpeg -ss 00:00:30 -i example.mp4 -vframes 1 output.jpg ``` 这将从名为example.mp4的视频中的第30秒抽取一帧,并将结果保存为output.jpg文件。 通过上述步骤,你就可以使用FFmpeg实现视频抽帧的功能了。记得根据实际需求修改命令中的参数,以满足你的具体要求。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [FFmpeg视频抽帧那些事](https://blog.csdn.net/weixin_39593523/article/details/110774418)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AI算法网奇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值