`

[转]FFmpeg不求甚解(四)——音频的解码和编码

 
阅读更多

FFmpeg不求甚解(四)——音频的解码和编码

转自http://www.myexception.cn/program/478970.html

      音频和视频其实是一样的,在文件中寻找音频流,然后解压出来,得到音频帧的数据,同样也可以按照设定的编码格式进行压缩,我这里把音频的解码和编码做成了两个工程,也是直接上代码:

#include <stdio.h>
#include <stdlib.h>

extern "C"
{
#include <libavcodec\avcodec.h>
#include <libavformat\avformat.h>
#include <libswscale\swscale.h>
}

int main(char arg,char *argv[])
{
	char *filename = argv[1];

	av_register_all();	//注册所有可解码类型
	AVFormatContext *pInFmtCtx=NULL;	//文件格式
	AVCodecContext *pInCodecCtx=NULL;	//编码格式 
	if (av_open_input_file(&pInFmtCtx, filename, NULL, 0, NULL)!=0)	//获取文件格式
		printf("av_open_input_file error\n");
	if (av_find_stream_info(pInFmtCtx) < 0)	//获取文件内音视频流的信息
		printf("av_find_stream_info error\n");

	unsigned int j;
	// Find the first audio stream

	int audioStream = -1;
	for (j=0; j<pInFmtCtx->nb_streams; j++)	//找到音频对应的stream
	{
		if (pInFmtCtx->streams[j]->codec->codec_type == CODEC_TYPE_AUDIO)
		{
			audioStream = j;
			break;
		}
	}
	if (audioStream == -1)
	{
		printf("input file has no audio stream\n");
		return 0; // Didn't find a audio stream
	}
	printf("audio stream num: %d\n",audioStream);
	pInCodecCtx = pInFmtCtx->streams[audioStream]->codec; //音频的编码上下文
	AVCodec *pInCodec = NULL;

	pInCodec = avcodec_find_decoder(pInCodecCtx->codec_id); //根据编码ID找到用于解码的结构体
	if (pInCodec == NULL)
	{
		printf("error no Codec found\n");
		return -1 ; // Codec not found
	}

	if(avcodec_open(pInCodecCtx, pInCodec)<0)//将两者结合以便在下面的解码函数中调用pInCodec中的对应解码函数
	{
		printf("error avcodec_open failed.\n");
		return -1; // Could not open codec

	}

	static AVPacket packet;

	printf(" bit_rate = %d \r\n", pInCodecCtx->bit_rate);
	printf(" sample_rate = %d \r\n", pInCodecCtx->sample_rate);
	printf(" channels = %d \r\n", pInCodecCtx->channels);
	printf(" code_name = %s \r\n", pInCodecCtx->codec->name);
	printf(" block_align = %d\n",pInCodecCtx->block_align);

	uint8_t *pktdata;
	int pktsize;
	int out_size = AVCODEC_MAX_AUDIO_FRAME_SIZE*100;
	uint8_t * inbuf = (uint8_t *)malloc(out_size);
	FILE* pcm;
	pcm = fopen("result.pcm","wb");
	long start = clock();
	while (av_read_frame(pInFmtCtx, &packet) >= 0)//pInFmtCtx中调用对应格式的packet获取函数
	{
		if(packet.stream_index==audioStream)//如果是音频
		{
			pktdata = packet.data;
			pktsize = packet.size;
			while(pktsize>0)
			{
				out_size = AVCODEC_MAX_AUDIO_FRAME_SIZE*100;
				//解码
				int len = avcodec_decode_audio2(pInCodecCtx, (short*)inbuf, &out_size, pktdata, pktsize);
				if (len < 0)
				{
					printf("Error while decoding.\n");
					break;
				}
				if(out_size > 0)
				{
					fwrite(inbuf,1,out_size,pcm);//pcm记录
					fflush(pcm);
				}
				pktsize -= len;
				pktdata += len;
			}
		} 
		av_free_packet(&packet);
	}
	long end = clock();
	printf("cost time :%f\n",double(end-start)/(double)CLOCKS_PER_SEC);
	free(inbuf);
	fclose(pcm);
	if (pInCodecCtx!=NULL)
	{
		avcodec_close(pInCodecCtx);
	}
	av_close_input_file(pInFmtCtx);

	return 0;
}

 解码后的文件保存为result.pcm中,现在用这个文件压缩出新的音频文件,代码如下:

void main()
{
	int16_t *samples;
	uint8_t *audio_outbuf;
	int audio_outbuf_size;
	int audio_input_frame_size;
	double audio_pts;
	
	const char* filename = "test.wav";
	FILE *fin = fopen("result.pcm", "rb"); //音频源文件 
	AVOutputFormat *fmt;
	AVFormatContext *oc;
	AVStream * audio_st;
	av_register_all();
	fmt = guess_format(NULL, filename, NULL);
	oc = av_alloc_format_context();
	oc->oformat = fmt;
	snprintf(oc->filename, sizeof(oc->filename), "%s", filename);
	audio_st = NULL;

	if (fmt->audio_codec != CODEC_ID_NONE)
	{
		AVCodecContext *c;
		audio_st = av_new_stream(oc, 1);
		c = audio_st->codec;
		c->codec_id = fmt->audio_codec;
		c->codec_type = CODEC_TYPE_AUDIO;
		c->bit_rate = 128000;
		c->sample_rate = 44100;
		c->channels = 2;
	}
	if (av_set_parameters(oc, NULL) < 0)
	{
		return;
	}
	dump_format(oc, 0, filename, 1);
	if (audio_st)
	{
		AVCodecContext* c;
		AVCodec* codec;
		c = audio_st->codec;
		codec = avcodec_find_encoder(c->codec_id);
		avcodec_open(c, codec);
		audio_outbuf_size = 10000;
		audio_outbuf = (uint8_t*)av_malloc(audio_outbuf_size);
		if (c->frame_size <= 1)
		{
			audio_input_frame_size = audio_outbuf_size / c->channels;
			switch (audio_st->codec->codec_id)
			{
			case CODEC_ID_PCM_S16LE:
			case CODEC_ID_PCM_S16BE:
			case CODEC_ID_PCM_U16LE:
			case CODEC_ID_PCM_U16BE:
				audio_input_frame_size >>= 1;
				break;
			default:
				break;
			}
		}
		else
		{
			audio_input_frame_size = c->frame_size;
		}
		samples = (int16_t*)av_malloc(audio_input_frame_size*2*c->channels);
	}
	if (!fmt->flags & AVFMT_NOFILE)
	{
		if (url_fopen(&oc->pb, filename, URL_WRONLY) < 0)
		{
			return;
		}
	}
	av_write_header(oc);
	for (;;)
	{
		if (audio_st)
		{
			audio_pts = (double)audio_st->pts.val * audio_st->time_base.num / audio_st->time_base.den;
		}
		else
		{
			audio_pts = 0.0;
		}
		if (!audio_st || audio_pts >= 360.0)
		{
			break;
		}
		if (fread(samples, 1, audio_input_frame_size*2*audio_st->codec->channels, fin) <= 0)
		{
			break;
		}
		AVCodecContext* c;
		AVPacket pkt;
		av_init_packet(&pkt);
		c = audio_st->codec;
		pkt.size = avcodec_encode_audio(c, audio_outbuf, audio_outbuf_size, samples);
		pkt.pts = av_rescale_q(c->coded_frame->pts, c->time_base, audio_st->time_base);
		pkt.flags |= PKT_FLAG_KEY;
		pkt.stream_index = audio_st->index;
		pkt.data = audio_outbuf;
		if (av_write_frame(oc, &pkt) != 0)
		{
			return;
		}
	}
	if (audio_st)
	{
		avcodec_close(audio_st->codec);
		av_free(samples);
		av_free(audio_outbuf);
	}
	av_write_trailer(oc);
	for (int i=0; i<oc->nb_streams; i++)
	{
		av_freep(&oc->streams[i]->codec);
		av_freep(&oc->streams[i]);
	}
	if (!(fmt->flags & AVFMT_NOFILE))
	{
		url_fclose(oc->pb);
	}
	av_free(oc);
	fclose(fin);
}

对应的下载链接:

 

音频解码:http://download.csdn.net/detail/yang_xian521/4399219

音频编码:http://download.csdn.net/detail/yang_xian521/4399293

至此,我已经实现了视频的解码编码,音频的解码编码,相信有心人肯定可以在此基础上实现视频音频的同步压缩,不过要再看一些网上的资料,也是很轻松的。至于视频的显示播放,大多数是要结合SDL实现,由于我只是浅尝辄止,只实现了图片的显示和简单的视频播放,比起我之前推荐的几个链接是弱爆了的,就不写下去了,这个系列就到这里吧,希望能给像我一样的一些入门级选手点帮助。也欢迎大神来多多指教。

分享到:
评论

相关推荐

    ffmpeg提取音频播放/解码

    FFmpeg是一个C语言编写的命令行工具,它可以解析、转换、编码和解码多种格式的音频和视频文件。它的核心库libavcodec负责解码和编码,libavformat处理容器格式和流,而libavfilter则提供了各种视频和音频滤镜功能。 ...

    C++基于FFmpeg的音频解码和播放

    FFmpeg是一个开源项目,提供了强大的音视频处理工具和库,包括libavcodec(用于编码和解码)、libavformat(用于多媒体容器格式的解析)和libavutil(通用实用工具库)。本示例是针对Visual Studio 2010编译环境的,...

    Android+FFmpeg+OpenSL ES音频解码播放

    1. **FFmpeg**:FFmpeg是一个开源的跨平台多媒体处理工具集,包含音频和视频的编码、解码、转码、格式转换等功能。在Android应用中,FFmpeg用于音频文件的解码,支持广泛的音频格式,如MP3、AAC、WAV等。 2. **音频...

    android端采用FFmpeg实现音频拼接/剪切/混音与转码

    在Android平台上,使用FFmpeg库实现音频处理是一个常见的需求,比如音频拼接、剪切、混音和转码。FFmpeg是一个开源项目,提供了一系列强大的命令行工具和库,用于处理多媒体数据。以下是对这些功能的详细解释: 1. ...

    ffmpeg+opensl的音频解码播放示例

    FFmpeg是一个全面的多媒体处理工具集,包括视频和音频的编码、解码、转码、流处理、格式转换等功能。它支持大量的音频和视频编码标准,如MP3、AAC、H.264等。在Android上,FFmpeg通常通过JNI(Java Native Interface...

    FFmpeg_13_音频解码

    总的来说,FFmpeg音频解码涉及到的知识点包括:FFmpeg框架结构、音频编码和解码原理、C++编程基础、多媒体文件格式、音视频流处理、以及Windows下的库管理和编译环境配置。理解和掌握这些知识点,将能帮助开发者有效...

    用Ffmpeg进行h265编解码的实例

    你可能会遇到的关键函数包括`avformat_write_header()`, `av_interleaved_write_frame()`, `avformat_free_context()`, `avcodec_flush_buffers()`等,这些都是FFmpeg处理输入输出流和控制编码解码流程的重要组成...

    音频格式转换的ffmpeg

    FFmpeg 是一个强大的开源工具,用于处理音频和视频文件,包括格式转换。在本文中,我们将深入探讨如何使用 FFmpeg 在 Java 环境中进行 AMR 转 MP3 的操作,以及如何在 Windows 和 Linux 系统上执行这个过程。 首先...

    使用ffmpeg解码MP3与AMR

    FFmpeg是一款强大的开源多媒体处理工具,它支持各种音频和视频格式的编码、解码、转换、流媒体处理等任务。在本主题中,我们将聚焦于如何使用FFmpeg解码MP3和AMR这两种常见的音频格式。 MP3(MPEG-1 Audio Layer ...

    ffmpeg解码音频并保存PCM的简单demo

    FFmpeg是一款强大的多媒体处理工具,它支持音频、视频的编码、解码、转换以及流传输等功能。在这个“ffmpeg解码音频并保存PCM的简单demo”中,我们将探讨如何使用FFmpeg将音频文件解码为脉冲编码调制(Pulse Code ...

    FFmpeg音频解码实例

    在本实例中,我们将探讨如何在Visual Studio 2008环境下,利用FFmpeg SDK 3.2进行音频解码。 首先,安装FFmpeg SDK 3.2是开发的基础。你需要下载并解压FFmpeg源代码,然后通过configure脚本配置编译环境,生成适用...

    树莓派4B开发板上,通过Qt+FFMPEG以多线程分别解码、编码USB摄像头视频数据

     本项目为在树莓派4B开发板上,通过Qt+FFMPEG以多线程分别解码、编码USB摄像头视频数据。其中USB摄像头视频输入格式为MJPEG。通过树莓派的硬件编码器“h264_omx”进行硬件编码封装成mp4文件。详细说明见...

    FFmpeg音频编码实例

    总之,FFmpeg音频编码和解码实例为我们提供了一个实践平台,通过分析和运行代码,可以深入理解音频编码解码的工作流程,以及FFmpeg库在实际开发中的应用。这对于任何想在多媒体领域进行开发的程序员来说,都是一个...

    FFmpeg滤镜开发——人脸识别 .pdf

    FFmpeg滤镜开发——人脸识别 人脸识别是在计算机视觉和机器学习领域中的一种技术,旨在通过图像或视频中检测、识别和验证人的脸部信息。在FFmpeg中,人脸识别可以通过滤镜来实现。滤镜是FFmpeg中的一种插件,能够对...

    海康视频数据+ffmpeg解码+再编码

    FFmpeg支持多种编码和解码标准,包括H.264,这是海康摄像机常用的视频编码格式。"海康视频数据+ffmpeg解码+再编码"的项目中,首先通过FFmpeg对海康摄像机的视频流进行解码,将原始的H.264编码数据转化为可编辑的像素...

    ffmpeg解码器

    总的来说,FFmpeg解码器是一个复杂而高效的过程,它涉及了多个编码标准和图像处理技术。理解并掌握这一过程对于进行多媒体开发、视频处理以及系统集成工作至关重要。通过使用FFmpeg,开发者可以轻松地处理各种编码...

    ffmpeg之H265解码

    FFmpeg是一款强大的开源多媒体处理工具,它包含了各种音视频编码、解码、转换以及流媒体功能。在本文中,我们将深入探讨如何使用FFmpeg进行H265(High Efficiency Video Coding,高效视频编码)解码。H265是目前广泛...

    利用ffmpeg音频g711转pcm

    FFmpeg是一款强大的开源多媒体处理工具,它支持各种音频和视频格式的编码、解码、转换以及流媒体处理。在本文中,我们将深入探讨如何利用FFmpeg将G.711音频格式转换为PCM(脉冲编码调制)音频格式。 G.711是一种...

    44.1Khz或48Khz两通道使用CoreAudio采集音频ffmpeg编码AAC的demo

    **FFmpeg**: FFmpeg是一个开源的多媒体处理工具,它包含了音频和视频的编码、解码、转码、流媒体等多种功能。在这个项目中,FFmpeg的音频编码功能被调用,它支持多种音频格式和编解码器,包括AAC。通过FFmpeg,...

Global site tag (gtag.js) - Google Analytics