ffmpeg解密海思音訊
阿新 • • 發佈:2018-12-01
使用海思語音編解碼庫進行 G711、G726、ADPCM 格式的編碼,編碼後的碼流遵循以下表格中描述的幀結構,即在每幀碼流資料的淨荷資料之前填充有 4 個位元組的幀頭;使用語音編解碼庫進行以上格式的解碼時,需要讀取相應的幀頭資訊。
這4個位元組的幀頭內容即為如下陣列中的值:
static char aryHeard[4] = {0,1,160,0}; //hisi audio header
1表示音訊 160表示的實際長度為160 * short = 320
==================================================
解碼流程:
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解碼器型別。
例項程式碼:
[cpp] view plain copy
- #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);
- }
- }