ffmpeg-3.1.5视频+音频解码代码

之前文章中的代码只能解码视频数据,本文在之前的基础上加入了解码音频数据部分。

与之前只能解码视频的代码相比,本文代码增加了audioCodecCtx和audioCodec的处理部分、循环解码音频流的部分、和音频输出文件的设置部分。

解码后的音频为PCM格式,可以使用“audacity”软件进行分析。需要注意的是,在使用“audacity”软件分析PCM码流时,要通过“文件->导入->裸数据”的方法导入.pcm文件,而不要使用“文件->打开”的方式打开该文件。

上代码。

#include <stdio.h>
extern "C"
{
#include "include\libavcodec\avcodec.h"
#include "include\libavformat\avformat.h"
#include "include\libavutil\imgutils.h"
};

#define __STDC_CONSTANT_MACROS

int _tmain(int argc, _TCHAR* argv[])
{
	//printf("%s", avcodec_configuration());
	AVFormatContext *formatctx;
	AVCodec *videoCodec;
	AVCodec *audioCodec;
	AVCodecContext *videoCodecctx = NULL;
	AVCodecContext *audioCodecctx = NULL;
	AVFrame *frame;
	AVFrame *frameYUV;
	AVPacket avpkt;
	AVPacket *pavpkt = &avpkt;

	//init
	av_register_all();
	avformat_network_init();
	formatctx = avformat_alloc_context();

	//输入文件路径
	char *fileName = "Titanic.ts";
	if (avformat_open_input(&formatctx,fileName,NULL,NULL)!=0)
	{
		printf("could not open input stream.\n");
		return -1;
	}
	if (avformat_find_stream_info(formatctx, NULL) < 0)
	{
		printf("could not find stream information.\n");
		return -1;
	}

	//output file
	FILE *outputfile_video = nullptr;
	FILE *outputfile_audio = nullptr;
	char *outputfilename_video = "output_video.yuv";
	char *outputfilename_audio = "output_audio.pcm";
	fopen_s(&outputfile_video, outputfilename_video, "wb");
	fopen_s(&outputfile_audio, outputfilename_audio, "wb");

	//==============video================
	//find videoindex
	int videoindex = av_find_best_stream(formatctx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);
	if (videoindex < 0)
	{
		printf("could not find a video stream.\n");
		return -1;
	}

	//find the video decoder
	videoCodecctx = avcodec_alloc_context3(NULL);
	if (videoCodecctx == NULL)
	{
		printf("could not allocate video AVCodecContext.\n");
		return -1;
	}
	avcodec_parameters_to_context(videoCodecctx, formatctx->streams[videoindex]->codecpar);
	videoCodec = avcodec_find_decoder(videoCodecctx->codec_id);
	if (videoCodec == NULL)
	{
		printf("vidoe codec not found.\n");
		return -1;
	}

	//open the video decoder
	if (avcodec_open2(videoCodecctx, videoCodec, NULL) < 0)
	{
		printf("could not open video codec.\n");
		return -1;
	}
	//=====================================

	//================audio===================
	//find audioindex
	int audioindex = av_find_best_stream(formatctx, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0);
	if (audioindex < 0)
	{
		printf("could not find a audio stream.\n");
		return -1;
	}

	//find the audio decoder
	audioCodecctx = avcodec_alloc_context3(NULL);
	if (audioCodecctx == NULL)
	{
		printf("could not allocate audio AVCodecContext.\n");
		return -1;
	}
	avcodec_parameters_to_context(audioCodecctx, formatctx->streams[audioindex]->codecpar);
	audioCodec = avcodec_find_decoder(audioCodecctx->codec_id);
	if (audioCodec == NULL)
	{
		printf("audio codec not found.\n");
		return -1;
	}

	//open the audio decoder
	if (avcodec_open2(audioCodecctx, audioCodec, NULL) < 0)
	{
		printf("could not open audio codec.\n");
		return -1;
	}
	//========================================

	//output information
	printf("---------------- File Information --------------\n");
	av_dump_format(formatctx, videoindex, fileName, 0);
	printf("------------------------------------------------\n");
	
	//pre decode
	av_init_packet(&avpkt);
	frame = av_frame_alloc();
	frameYUV = av_frame_alloc();
	int video_dst_bufsize = av_image_alloc((uint8_t**)frameYUV->data, frameYUV->linesize, videoCodecctx->width, videoCodecctx->height, videoCodecctx->pix_fmt, 1);
	printf("decode video file %s to %s and %s\n", fileName, outputfilename_video, outputfilename_audio);

	//decode
	int frame_count = 0;
	while (av_read_frame(formatctx,pavpkt)>=0)
	{
		if (pavpkt->stream_index == videoindex)
		{
			if (avcodec_send_packet(videoCodecctx, pavpkt) != 0){
				printf("input AVPacket to video decoder failed!\n");
				return -1;
			}
			while (0 == avcodec_receive_frame(videoCodecctx, frame)){
				av_image_copy((uint8_t **)frameYUV->data,frameYUV->linesize,(const uint8_t **)frame->data,frame->linesize,videoCodecctx->pix_fmt,videoCodecctx->width,videoCodecctx->height);
				fwrite(frameYUV->data[0], 1, video_dst_bufsize, outputfile_video);
				printf("decoded frame index: %d\n", frame_count);
				frame_count++;
			}
		}
		else if (pavpkt->stream_index == audioindex)
		{
			if (avcodec_send_packet(audioCodecctx, pavpkt) != 0){
				printf("input AVPacket to audio decoder failed!\n");
				return -1;
			}
			while (0 == avcodec_receive_frame(audioCodecctx, frame)){
				size_t unpadded_linesize = frame->nb_samples*av_get_bytes_per_sample((AVSampleFormat)frame->format);
				fwrite(frame->extended_data[0], 1, unpadded_linesize, outputfile_audio);
				printf("decoded audio.\n");
			}
		}
		av_packet_unref(pavpkt);
	}
	
	fclose(outputfile_video);
	fclose(outputfile_audio);
	av_frame_free(&frame);
	av_frame_free(&frameYUV);
	avcodec_close(videoCodecctx);
	avcodec_close(audioCodecctx);
	avformat_close_input(&formatctx);

	return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值