1. 程式人生 > >FFMPEG解碼海思音訊資料

FFMPEG解碼海思音訊資料

解碼流程: 1、  讀取海思g726音訊資料,海思g726音訊會多4個位元組的海思頭資訊。 2、選擇ffmpeg g726編碼器進行解碼。ffmpeg g726解碼器包括:AV_CODEC_ID_ADPCM_G726、AV_CODEC_ID_ADPCM_G726LE。如果海思g726碼流型別為asf時,請選擇AV_CODEC_ID_ADPCM_G726解碼器型別;如果海思g726碼流型別為RFC3551標準時,請選擇AV_CODEC_ID_ADPCM_G726LE解碼器型別。  例項程式碼:

解碼流程:

1、  讀取海思g726音訊資料,海思g726音訊會多4個位元組的海思頭資訊。

2、選擇ffmpeg g726編碼器進行解碼。ffmpeg g726解碼器包括:AV_CODEC_ID_ADPCM_G726、AV_CODEC_ID_ADPCM_G726LE。如果海思g726碼流型別為asf時,請選擇AV_CODEC_ID_ADPCM_G726解碼器型別;如果海思g726碼流型別為RFC3551標準時,請選擇AV_CODEC_ID_ADPCM_G726LE解碼器型別。

 例項程式碼:

#define  Hisi_AUDIO_HERDER_LEN			4					//hisi 音訊資料頭
extern "C"
{
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libavutil/frame.h"
#include "libswscale/swscale.h"
#include "libavutil/imgutils.h"
}
//連結 ffmpeg lib庫

AVCodec *codec;
	AVCodecContext *c= NULL;
	AVPacket avpkt;
	AVFrame *decoded_frame = NULL;
	avcodec_register_all();
	av_init_packet(&avpkt);
	/* find the mpeg audio decoder */
	/*
	ffmpeg g726編碼器:AV_CODEC_ID_ADPCM_G726
	ffmpeg g726解碼器包括:AV_CODEC_ID_ADPCM_G726、AV_CODEC_ID_ADPCM_G726LE
	如果海思g726碼流型別為asf時,請選擇AV_CODEC_ID_ADPCM_G726解碼器型別
	如果海思g726碼流型別為RFC3551標準時,請選擇AV_CODEC_ID_ADPCM_G726LE解碼器型別
	*/
	codec = avcodec_find_decoder(AV_CODEC_ID_ADPCM_G726LE);
	if (!codec) 
	{
		fprintf(stderr, "codec not found\n");
		return;
	}
	c = avcodec_alloc_context3(codec);
	//取樣率= 8000 每個取樣用的bit數= 16 通道數= 1
	/*
	bits_per_coded_sample:表示編碼壓縮bit值與取樣率的bit值之比。
	如果為g726音訊時,表示g726碼流壓縮與取樣率比值。比如kbps碼流壓縮比為:k/8k = 5,kbps碼流壓縮比為k/8k = 2。
	*/
	c->bits_per_coded_sample = 5;
	c->channels = 1;
	c->sample_fmt = AV_SAMPLE_FMT_S16;
	c->sample_rate = 8000;
	c->codec_type = AVMEDIA_TYPE_AUDIO;
	//c->bit_rate = 16000;
	int iRet = avcodec_open2(c, codec,NULL);
	if ( iRet < 0 ) 
	{
		fprintf(stderr, "could not open codec\n");
		return;
	}

	CString filePath = "";
	CString newlFilePath = "";
	char szFilter[] = {"g726 Files (*.g726_hisi)|*.g726_hisi||"};
	CFileDialog dlg(TRUE,NULL,NULL,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,szFilter,NULL);
	if(dlg.DoModal() == IDOK)
	{
		filePath = dlg.GetPathName();
		newlFilePath = filePath;
		newlFilePath.Replace(".g726_hisi",".hisi2ff.pcm");
		BOOL bRet = 0;
		FILE * fpSrc = fopen(filePath.GetBuffer(filePath.GetLength()),"rb");
		FILE * fpDst = fopen(newlFilePath.GetBuffer(newlFilePath.GetLength()),"wb+");
		char szData[100] = {0};
		char szOutData[320] = {0};
		int  nDataLen = 100;
		int  nOutDataLen = 320;
		int  nReadedSize = 0;
		unsigned short usHisiHeader[2] = {0};
		if(fpSrc != NULL)
		{
			while(TRUE)
			{
				//讀取頭標記
				nDataLen = Hisi_AUDIO_HERDER_LEN;
				nReadedSize = fread(szData,sizeof(char),nDataLen,fpSrc);
				if(nReadedSize < nDataLen)
				{
					break;
				}
				memcpy(usHisiHeader,szData,Hisi_AUDIO_HERDER_LEN);
				int nAudioFrameDataLen = (usHisiHeader[1] & 0x00ff) * sizeof(unsigned short);
				nDataLen = nAudioFrameDataLen;
				//讀取音訊幀資料
				nReadedSize = fread(szData,sizeof(char),nDataLen,fpSrc);
				if(nReadedSize < nDataLen)
				{
					break;
				}
				avpkt.data = (uint8_t *)szData;
				avpkt.size = nReadedSize;
				int got_frame = 0;
				if (!decoded_frame) 
				{
					if (!(decoded_frame = avcodec_alloc_frame())) 
					{
						return;
					}
				} 
				else
				{
					avcodec_get_frame_defaults(decoded_frame);
				}
				int len = avcodec_decode_audio4(c, decoded_frame, &got_frame, &avpkt);
				if (len < 0) 
				{
					return;
				}
				if (got_frame) 
				{
					/* if a frame has been decoded, output it */
					int data_size = av_samples_get_buffer_size(NULL, c->channels,
						decoded_frame->nb_samples,
						c->sample_fmt, 1);

					fwrite(decoded_frame->data[0], 1, data_size, fpDst);
					
				}
			}

			fclose(fpSrc);
			fclose(fpDst);
			avcodec_close(c);
			av_free(c);
			av_free(decoded_frame);
		}

	}