• ffmpeg视频编解码 demo初探(一)(包含下载指定windows版本ffmpeg)分离视频文件中的视频流每一帧YUV图片


    参考文章1:YUV数据流编码成H264

    参考文章2:【FFmpeg编码实战】(1)将YUV420P图片集编码成H264视频文件

    第一个项目:分离视频文件中的视频流每一张图片

    先参考这个文章:【FFmpeg解码实战】(2)分离视频文件中的视频流每一张图片(进阶)(C)

    这篇文章的上一篇文章:【FFmpeg解码实战】(1)解码并分离视频文件中的音频流和视频流(C),也是第一篇demp,我们跳过

    博主提供了工程下载方式:VS2019-解码视频-工程所有文件.zip

    这个下载的项目其实是把解码并分离视频文件中的音频流和视频流分离视频文件中的视频流每一张图片合在一起了,通过宏开关去控制
    在这里插入图片描述

    弯路

    里面没有ffmpeg,我们下载博主编译好的或者直接到官网下载

    博主给的:

    你要ARM 的话,可以使用这个: https://download.csdn.net/download/Ciellee/13027058
    windows 的话,可以用这个 : https://download.csdn.net/download/Ciellee/12915075
    都是我之前用最新的 4.3 源码自已编译的

    我没有用博主的,直接找方法自己编译了一个,不过是4.4版本的,不知道兼容不兼容
    Visual Studio 2019 VS编译ffmpeg4.4为静态库或动态库

    然后我们在博主的工程里面,添加include和lib两个目录,并且把需要的头文件和库文件拷贝进去

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在vs项目种配置附加包含目录和附加库目录

    看vs项目的这个地方发现博主是这样包含ffmpeg的头文件和库目录的,我们把它改了
    在这里插入图片描述
    在这里插入图片描述

    改成这样
    在这里插入图片描述
    在这里插入图片描述
    然后运行项目,发现报错了,错误 C4996 'av_init_packet': 被声明为已否决,应该这个函数不推荐使用了,我们看下4.4有没替代接口
    在这里插入图片描述

    在ffmpeg编译工程里查找,发现这个文档,参考文章:ffmpeg的API函数变化记录

    在这里插入图片描述

    看了下,貌似没替代接口,那么我们只能“沉默”它了
    在这里插入图片描述
    在代码开头添加#pragma warning(disable : 4996)
    在这里插入图片描述
    运行报错:
    在这里插入图片描述
    按博主提供的ffmpeg4.3配置了,也还是同样问题

    严重性 代码 说明 项目 文件 行 禁止显示状态
    警告 MSB8028 中间目录(x64\Debug)包含从另一个项目(1-解码视频.vcxproj)共享的文件。
    这会导致错误的清除和重新生成行为。 demux_video C:\Program Files (x86)\Microsoft Visual
    Studio\2019\Community\MSBuild\Microsoft\VC\v160\Microsoft.CppBuild.targets 513

    严重性 代码 说明 项目 文件 行 禁止显示状态
    警告 LNK4078 找到多个“.rdata”节,它们具有不同的特性(C0400040) demux_video F:\ArnoldCppTest\20221113_ffmpeg_test\prj\libavformatd.lib(invert_limb_table.obj) 1

    步入正轨

    下载官方编译的ffmpeg4.3(win64-gpl-shared-4.3.zip)

    遇到很多困难啊,后来发现是博主给的ffmpeg有问题,后来我到ffmpeg官网,图中箭头所指的地方下到了4.3老版本

    在这里插入图片描述

    我一直往后面翻,终于找到了4.3老版本,

    https://github.com/BtbN/FFmpeg-Builds/releases

    然后下载了

    https://github.com/BtbN/FFmpeg-Builds/releases/download/autobuild-2021-03-31-12-39/ffmpeg-n4.3.2-162-g4bbcaf7559-win64-gpl-shared-4.3.zip

    在这里插入图片描述
    然后下下来解压,把里面的一些东西拷贝到我们项目目录中,主要就是头文件,静态库文件,动态库文件,其中动态库文件注意要放在项目根目录

    拷贝ffmpeg文件到项目

    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述

    配置vs

    因为下下来的没见带d,所以估计是release版本的,我们在Release x64下配置

    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述

    因为我们是在代码中引用附加依赖项的,所以不用在vs里填了

    在这里插入图片描述

    运行项目

    把博主那个视频文件拷贝到项目根目录下

    在这里插入图片描述
    发现有的代码不大对,我们改一下,
    main.cpp

    /*
    
    ffmpeg lib 测试程序
    
    */
    
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    extern "C"
    {
    	#include 
    	#include 
    	#include 
    	#include 		//av_ts2timestr
    	#include 
    }
    
    #define YUV420P_FILE	1	// 视频流保存成 yuv420p 图片
    //#define H264_FILE	    1	// 视频流保存成 H264 文件
    
    #ifdef _DEBUG
    	#pragma comment(lib, "libavformatd.lib")
    	#pragma comment(lib, "libavutild.lib")
    #else
    	//#pragma comment(lib, "libavformat.lib")
    	#pragma comment(lib, "avformat.lib")
    	//#pragma comment(lib, "libavutil.lib")
    	#pragma comment(lib, "avutil.lib")
    	#pragma comment(lib, "avcodec.lib")
    	#pragma comment(lib, "avfilter.lib")
    	#pragma comment(lib, "swscale.lib")
    	#pragma comment(lib, "swresample.lib")
    	#pragma comment(lib, "postproc.lib")
    	#pragma comment(lib, "avdevice.lib")
    #endif
    
    using namespace std;
    
    static int get_format_from_sample_fmt(const char** fmt, enum AVSampleFormat sample_fmt)
    {
    	int i;
    	struct sample_fmt_entry 
    	{
    		enum AVSampleFormat sample_fmt; 
    		const char* fmt_be, * fmt_le;
    	} 
    	sample_fmt_entries[] = 
    	{
    		{ AV_SAMPLE_FMT_U8,  "u8",    "u8"    },
    		{ AV_SAMPLE_FMT_S16, "s16be", "s16le" },
    		{ AV_SAMPLE_FMT_S32, "s32be", "s32le" },
    		{ AV_SAMPLE_FMT_FLT, "f32be", "f32le" },
    		{ AV_SAMPLE_FMT_DBL, "f64be", "f64le" },
    	};
    	*fmt = NULL;
    
    	for (i = 0; i < FF_ARRAY_ELEMS(sample_fmt_entries); i++) 
    	{
    		struct sample_fmt_entry* entry = &sample_fmt_entries[i];
    		if (sample_fmt == entry->sample_fmt) 
    		{
    			*fmt = AV_NE(entry->fmt_be, entry->fmt_le);
    			return 0;
    		}
    	}
    
    	fprintf(stderr,
    		"sample format %s is not supported as output format\n",
    		av_get_sample_fmt_name(sample_fmt));
    	return -1;
    }
    
    // 参考:ffplay.c、demuxing_decoding.c
    int main(int argc, char* argv[])
    {
    	int ret = 0;
    	//printf("%s \n",avcodec_configuration());
    
    	// 定义文件名
    	const char input_filename[] = "video.mp4";
    	const char out_filename[] = "video_out";
    	char video_dst_filename[50]; // = "Video_Test_out.h264";
    	char audio_dst_filename[50]; // = "Video_Test_out.aac";
    	memset(video_dst_filename, '\0', 50);
    	memset(audio_dst_filename, '\0', 50);
    
    	// 1. 打开文件,分配AVFormatContext 结构体上下文
    	AVFormatContext* fmt_ctx = NULL;	// 定义音视频格式上下文结构体
    	if (avformat_open_input(&fmt_ctx, input_filename, NULL, NULL) < 0) 
    	{
    		printf("Could not open source file %s\n", input_filename);
    		return 0;
    	}
    	// 2. 查找文件对应的流信息
    	if (avformat_find_stream_info(fmt_ctx, NULL) < 0) {
    		printf("Could not find stream information\n");
    		return 0;
    	}
    
    	// 3. 打印流信息
    	av_dump_format(fmt_ctx, 0, input_filename, 0);
    
    	// 4. 视频解码器初始化
    	// 4.1 获取视频对应的stream_index
    	int video_stream_idx = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);
    	printf("\n#===> Find video_stream_idx = %d\n", video_stream_idx);
    
    	// 4.2 获取到stream 数据
    	AVStream* video_st = fmt_ctx->streams[video_stream_idx];
    
    	// 4.3 根据 codec_id 查找解码器
    	AVCodec* video_dec = avcodec_find_decoder(video_st->codecpar->codec_id);
    	// 4.4 初始化解码器上下文信息
    	AVCodecContext* video_dec_ctx = avcodec_alloc_context3(video_dec);
    
    	// 4.5 复制 codec 相关参数到解码器上下文中
    	avcodec_parameters_to_context(video_dec_ctx, video_st->codecpar);
    	printf("\n#===> Find decoder: %s,  coded_id:%d  long name: %s  pix_fmt=%d (%s)\n", video_dec->name, video_dec->id, video_dec->long_name, video_dec_ctx->pix_fmt, av_get_pix_fmt_name(video_dec_ctx->pix_fmt));
    
    	// 4.6 初始化并打开解码器
    	AVDictionary* video_opts = NULL;
    	avcodec_open2(video_dec_ctx, video_dec, &video_opts);
    
    
    	// 5. 音频解码器初始化
    	// 5.1  获取音频对应的stream_index
    	int audio_stream_idx = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0);
    	printf("\n#===> Find audio_stream_idx = %d\n", audio_stream_idx);
    
    	// 5.2 获取到stream 数据
    	AVStream* audio_st = fmt_ctx->streams[audio_stream_idx];
    
    	// 5.3 根据 codec_id 查找解码器
    	AVCodec* audio_dec = avcodec_find_decoder(audio_st->codecpar->codec_id);
    	printf("\n#===> Find decoder: %s,  coded_id:%d  long name: %s\n", audio_dec->name, audio_dec->id, audio_dec->long_name);
    
    	// 5.4 初始化解码器上下文信息
    	AVCodecContext* audio_dec_ctx = avcodec_alloc_context3(audio_dec);
    
    	// 5.5 复制 codec 相关参数到解码器上下文中
    	avcodec_parameters_to_context(audio_dec_ctx, audio_st->codecpar);
    
    	// 5.6 初化并打开音频解码器
    	AVDictionary* audio_opts = NULL;
    	avcodec_open2(audio_dec_ctx, audio_dec, &audio_opts);
    
    	// 6. 配置视频解复用后要保存的位置
    	FILE* video_dst_file = NULL, * audio_dst_file = NULL;
    
    #ifdef H264_FILE
    	sprintf_s(video_dst_filename, 50, "%s.%s", out_filename, video_dec->name);
    	ret = fopen_s(&video_dst_file, video_dst_filename, "wb");
    	printf("open file:%s   ret:%d\n", video_dst_filename, ret);
    #endif
    
    #ifdef YUV420P_FILE
    	//文件夹名称
    	char folderName[] = "video";
    
    	// 文件夹不存在则创建文件夹
    	if (_access(folderName, 0) == -1)
    	{
    		_mkdir(folderName);
    	}
    
    	snprintf(audio_dst_filename, 50, "video/%s.%s", out_filename, audio_dec->name);
    #else
    	sprintf_s(audio_dst_filename, 50, "%s.%s", out_filename, audio_dec->name);
    #endif
    
    	ret = fopen_s(&audio_dst_file, audio_dst_filename, "wb");
    	printf("open file:%s   ret:%d\n", audio_dst_filename, ret);
    
    
    	uint8_t* video_dst_data[4] = { NULL };
    	int video_dst_linesize[4] = { 0 };
    
    	// 7. 计算视频数据大小
    	size_t video_dst_bufsize = av_image_alloc(video_dst_data, video_dst_linesize,
    		video_dec_ctx->width, video_dec_ctx->height, video_dec_ctx->pix_fmt, 1);
    
    	// 8. 分配并初始化 AVFrame、AVPacket
    	AVFrame* frame = av_frame_alloc();
    	AVPacket pkt;
    	av_init_packet(&pkt);
    	pkt.data = NULL;
    	pkt.size = 0;
    	int video_frame_count = 0, audio_frame_count = 0;
    
    	printf("Start read frame\n");
    	//  9. 循环读取 一帧数据
    	while (av_read_frame(fmt_ctx, &pkt) >= 0) {
    		// 10. 视频数据解码
    		if (pkt.stream_index == video_stream_idx)
    		{
    			// 10.1 将 packet 数据 发送给解码器
    			ret = avcodec_send_packet(video_dec_ctx, &pkt);
    
    			// 10.2 获取解码后的帧数据
    			while (ret >= 0) {
    				ret = avcodec_receive_frame(video_dec_ctx, frame);
    
    				if (ret == AVERROR_EOF || ret == AVERROR(EAGAIN))
    				{
    					ret = 0;
    					break;
    				}
    				// 10.3 保存帧数据到视频文件中
    				//printf("#===> video_frame n:%d  coded_n:%d  ", video_frame_count++, frame->coded_picture_number);
    				av_image_copy(video_dst_data, video_dst_linesize,
    					(const uint8_t**)(frame->data), frame->linesize, video_dec_ctx->pix_fmt, video_dec_ctx->width, video_dec_ctx->height);
    #ifdef YUV420P_FILE
    				// 10.4 写入文件
    				sprintf_s(video_dst_filename, 50, "video/%s.%s.%d.yuv", out_filename, av_get_pix_fmt_name(video_dec_ctx->pix_fmt), video_frame_count++);
    				ret = fopen_s(&video_dst_file, video_dst_filename, "wb");
    				//printf("open file:%s   ret:%d\n", video_dst_filename, ret);
    #endif
    
    				ret = (int)fwrite(video_dst_data[0], 1, video_dst_bufsize, video_dst_file);
    				//printf("Write Size:%d\n", ret);
    #ifdef YUV420P_FILE
    				fclose(video_dst_file);
    #endif
    			}
    		}
    		// 11. 音频数据解码  
    		else if (pkt.stream_index == audio_stream_idx)
    		{
    			// 11.1 将 packet 数据 发送给解码器
    			ret = avcodec_send_packet(audio_dec_ctx, &pkt);
    
    			// 11.2 获取解码后的帧数据
    			while (ret >= 0) {
    				ret = avcodec_receive_frame(audio_dec_ctx, frame);
    
    				if (ret == AVERROR_EOF || ret == AVERROR(EAGAIN))
    				{
    					ret = 0;
    					break;
    				}
    				// 11.3 写入文件
    				//printf("#===> audio_frame n:%d  nb_samples:%d  pts:%s ",
    				//		audio_frame_count++, frame->nb_samples, av_ts2timestr(frame->pts, &audio_dec_ctx->time_base));
    				ret = (int)fwrite(frame->extended_data[0], 1, frame->nb_samples * av_get_bytes_per_sample((AVSampleFormat)(frame->format)), audio_dst_file);
    				//printf("Write Size:%d\n", ret);
    			}
    		}
    
    		av_frame_unref(frame);
    		// 清空AVPacket结构体数据
    		av_packet_unref(&pkt);
    
    		if (ret < 0)
    			break;
    	}
    
    	// 12.发送一个空包,刷新解码器
    	ret = avcodec_send_packet(video_dec_ctx, NULL);
    	// 12.1 获取解码后的帧数据
    	while (ret >= 0) {
    		ret = avcodec_receive_frame(video_dec_ctx, frame);
    
    		if (ret == AVERROR_EOF || ret == AVERROR(EAGAIN))
    		{
    			printf("break, video ret=%d \n", ret);
    			ret = 0;
    			break;
    		}
    	}
    
    	ret = avcodec_send_packet(audio_dec_ctx, NULL);
    
    	// 12.2 获取解码后的帧数据
    	while (ret >= 0) {
    		ret = avcodec_receive_frame(audio_dec_ctx, frame);
    
    		if (ret == AVERROR_EOF || ret == AVERROR(EAGAIN))
    		{
    			printf("break, audio ret=%d \n", ret);
    			ret = 0;
    			break;
    		}
    	}
    
    
    	// 13. 解复用完毕
    	printf("Demuxing succeeded.\n");
    	printf("Play the output video file with the command:\n"
    		"ffplay -f rawvideo -pix_fmt %s -video_size %dx%d %s\n",
    		av_get_pix_fmt_name(video_dec_ctx->pix_fmt), video_dec_ctx->width, video_dec_ctx->height, video_dst_filename);
    
    
    	FILE* bat_dst_file = NULL;
    	char bat_out[100] = "";
    	memset(bat_out, '\0', 100);
    
    #ifdef YUV420P_FILE
    	memset(video_dst_filename, '\0', 50);
    	sprintf_s(video_dst_filename, 50, "%s.%s.%d.yuv", out_filename, av_get_pix_fmt_name(video_dec_ctx->pix_fmt), 0);
    
    #endif
    
    	sprintf_s(bat_out, 99, "ffplay -f rawvideo -pix_fmt %s -video_size %dx%d %s",
    		av_get_pix_fmt_name(video_dec_ctx->pix_fmt), video_dec_ctx->width, video_dec_ctx->height, video_dst_filename);
    
    #ifdef YUV420P_FILE
    	ret = fopen_s(&bat_dst_file, "video/play_video.bat", "wb");
    #else
    	ret = fopen_s(&bat_dst_file, "play_video.bat", "wb");
    #endif
    
    	ret = (int)fwrite(bat_out, 1, sizeof(bat_out), bat_dst_file);
    	fclose(bat_dst_file);
    
    
    
    	enum AVSampleFormat sfmt = audio_dec_ctx->sample_fmt;
    	int n_channels = audio_dec_ctx->channels;
    	const char* fmt;
    
    	if (av_sample_fmt_is_planar(sfmt)) {
    		const char* packed = av_get_sample_fmt_name(sfmt);
    		printf("Warning: the sample format the decoder produced is planar "
    			"(%s). This example will output the first channel only.\n",
    			packed ? packed : "?");
    		sfmt = av_get_packed_sample_fmt(sfmt);
    		n_channels = 1;
    	}
    	if ((ret = get_format_from_sample_fmt(&fmt, sfmt)) < 0)
    		goto end;
    	printf("Play the output audio file with the command:\n"
    		"ffplay -f %s -ac %d -ar %d %s\n",
    		fmt, n_channels, audio_dec_ctx->sample_rate,
    		audio_dst_filename);
    
    	memset(bat_out, '\0', 100);
    #ifdef YUV420P_FILE
    	memset(audio_dst_filename, '\0', 50);
    	sprintf_s(audio_dst_filename, 50, "%s.%s", out_filename, audio_dec->name);
    #endif
    	sprintf_s(bat_out, 99, "ffplay -f %s -ac %d -ar %d %s",
    		fmt, n_channels, audio_dec_ctx->sample_rate,
    		audio_dst_filename);
    #ifdef YUV420P_FILE
    	ret = fopen_s(&video_dst_file, "video/play_audio.bat", "wb");
    #else
    	ret = fopen_s(&video_dst_file, "play_audio.bat", "wb");
    #endif
    	ret = (int)fwrite(bat_out, 1, sizeof(bat_out), bat_dst_file);
    	fclose(video_dst_file);
    
    end:
    	avcodec_free_context(&video_dec_ctx);
    	avcodec_free_context(&audio_dec_ctx);
    	avformat_close_input(&fmt_ctx);
    
    #ifdef H264_FILE
    	fclose(video_dst_file);
    #endif
    
    	fclose(audio_dst_file);
    	av_frame_free(&frame);
    	av_free(video_dst_data[0]);
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290
    • 291
    • 292
    • 293
    • 294
    • 295
    • 296
    • 297
    • 298
    • 299
    • 300
    • 301
    • 302
    • 303
    • 304
    • 305
    • 306
    • 307
    • 308
    • 309
    • 310
    • 311
    • 312
    • 313
    • 314
    • 315
    • 316
    • 317
    • 318
    • 319
    • 320
    • 321
    • 322
    • 323
    • 324
    • 325
    • 326
    • 327
    • 328
    • 329
    • 330
    • 331
    • 332
    • 333
    • 334
    • 335
    • 336
    • 337
    • 338
    • 339
    • 340
    • 341
    • 342
    • 343
    • 344
    • 345
    • 346
    • 347
    • 348
    • 349
    • 350
    • 351
    • 352
    • 353
    • 354
    • 355
    • 356
    • 357
    • 358
    • 359
    • 360
    • 361
    • 362
    • 363
    • 364
    • 365
    • 366
    • 367
    • 368
    • 369
    • 370
    • 371

    然后vs上运行项目(注意重复运行项目时,不要打开里面生成的文件,以免占用)

    在这里插入图片描述

    查看文件

    然后到项目根目录查看,发现多了个video目录,里面有一个.aac文件和很多YUV文件,除此之外,还有俩.bat脚本文件,

    play_audio.bat:
    ffplay -f f32le -ac 1 -ar 44100 video_out.aac

    play_video.bat
    ffplay -f rawvideo -pix_fmt yuv420p -video_size 1050x540 video_out.yuv420p.0.yuv

    我们把ffmpeg可执行文件和动态库文件拷贝进来,然后执行那俩脚本文件,就能播放.aac文件和YUV文件了,不过貌似是播放视频的,我们生成的单帧文件,所以就只能播放出第一帧

    在这里插入图片描述

    双击play_audio.bat能播放.aac文件:

    在这里插入图片描述

    双击play_video.bat能播放查看YUV第一帧:

    在这里插入图片描述

    用YUView也能查看文件,不过要把图片正确的宽高和编码方式写对,宽1050,高540

    在这里插入图片描述

  • 相关阅读:
    (已解决)执行bat脚本文件的@title 设置中文标题后执行,出现中文乱码
    云HIS系统源码,医院管理系信息统源码,融合B/S版四级电子病历系统
    c/c++字符串处理标准库 string 介绍
    【BERT-多标签文本分类实战】之七——训练-评估-测试与运行主程序
    zabbix学习1--zabbix6.x单机
    你被裁了需要知道的一些细节
    【重识云原生】第六章容器6.1.2节——容器安装部署
    谷歌硬件工程师年薪165万,苹果外籍员工222万,在大厂打工“香”吗?
    MKS上游和下游集成式压力控制器的技术分析及其替代解决方案
    五运放蔡氏电路具体求告知
  • 原文地址:https://blog.csdn.net/Dontla/article/details/127807525