MP4音頻解碼信息

文章轉載自:http://blog.csdn.net/flyingqr/archive/2010/02/02/5282600.aspx 版權歸原作者,編輯:小乙哥

MP4文件格式分為頭部和數據兩部分,頭部是由許多被稱作Atom的結構單元嵌套或排列而成,數據部分則完全為實際數據不包含元信息,因此具體解碼時音視頻幀的位置和大小都要在頭部獲取。詳細內容見以下鏈接:
http://wqyuwss.52rd.net
這里總結下音頻解碼信息獲取的一些經驗,當然詳細內容需要查看quick time file format的文檔。
MP4的音頻解碼信息保存在如下嵌套的Atom中,{moov{mdia{minf{smhd{stbl{stsd}}}}}}
stsd可能包括多個音頻信息的描述,結構如下:

typedef struct stsdtable
{
????unsigned int size;//Atom大小
????char format[4];//音頻編碼格式
????int res1;
????int ref;
????short version;//版本
????short pad1;
????int pad2;
????short channels;//聲道
????short bitspersample;
????short compress_id;
????short res2;
????short samplerate1;//采樣率
????short samplerate2;
????//{if(version==1)

????????int sampleperpacket;
????????int bytesperpacket;
????????int bytesperframe;
????????int bytespersample;
????//}

} stsdtable;

其中format對應音頻編碼格式:
PCM_S32BE,? in32
PCM_S32LE,? in32
PCM_S24BE,? in24
PCM_S24LE,? in24
PCM_S16BE,? twos // 16 bits //
PCM_S16LE,? sowt //?
PCM_S16LE,? lpcm
PCM_F32BE,? fl32
PCM_F64BE,? fl64
PCM_S8,???? sowt
PCM_U8,???? raw? // 8 bits unsigned
PCM_U8,???? NONE // uncompressed
PCM_MULAW,? ulaw //
PCM_ALAW,?? alaw //
ADPCM_IMA_QT, ima4 // IMA-4 ADPCM //
MACE3,????? MAC3 // Macintosh Audio Compression and Expansion 3:1 ///
MACE6,????? MAC6 // Macintosh Audio Compression and Expansion 6:1 //
MP3,??????? .mp3 // MPEG layer 3 */
uint8_t moov[] = "moov";
uint8_t trak[] = "trak";
uint8_t mdia[] = "mdia";
uint8_t minf[] = "minf";
uint8_t stbl[] = "stbl";
uint8_t stsd[] = "stsd";
uint8_t stsc[] = "stsc";
uint8_t stsz[] = "stsz";
uint8_t stco[] = "stco";
uint8_t ftyp[] = "ftyp";
uint8_t mdat[] = "mdat";

typedef struct Atom
{
????unsigned int size;
????uint8_t tag[4];
????int ver_flag;
????unsigned int num_of_entries;
????unsigned int pos;
????uint8_t *data;
} Atom;



uint8_t kmp3[] = {0x6D,0x73,0x00,0x55};
uint8_t fmp3[] = ".mp3";
uint8_t raw[] = "raw ";

uint8_t wave[] = "wave";
uint8_t mp4a[] = "mp4a";
uint8_t enca[] = "enca";//encrypted to ISO/IEC 14496-12 or 3GPP standards

uint8_t smar[] = "smar";//encoded to 3GPP GSM 6.10 AMR narrowband standards

uint8_t sawb[] = "sawb";//encoded to 3GPP GSM 6.10 AMR wideband standards

uint8_t m4ds[] = "m4ds";//encoded to ISO/IEC 14496-10 AVC standards

uint8_t esds[] = "esds";
uint8_t fram[] = "fram";


#define MKTAG(a,b,c,d) (a | (b << 8) | (c << 16) | (d << 24))
typedef struct AVCodecTag {
????int id;
????unsigned int tag;
} AVCodecTag;


typedef struct stsdtable
{
????unsigned int size;
????char format[4];
????int res1;
????int ref;
????short version;
????short pad1;
????int pad2;
????short channels;
????short bitspersample;
????short compress_id;
????short res2;
????short samplerate1;
????short samplerate2;
????//{if(version==1)

????????int sampleperpacket;
????????int bytesperpacket;
????????int bytesperframe;
????????int bytespersample;
????//}

} stsdtable;


typedef struct sampletable
{
????unsigned int size;
????unsigned int id_of_sd;
} sampletable;
//MP4Analyze.cpp
#include "MP4Analyze.h"
#include <vector>
#include <map>
#include <iostream>
#include <string>
#ifdef WIN32
#include <winsock2.h>
#pragma comment(lib, "Ws2_32.lib")
#pragma warning (disable:4786)
#endif

#ifdef __GNUG__
#include <netinet/in.h>
#endif
using namespace std;




int check_format(uint8_t *data, int size)
{
????if(strncmp((char*)moov,(char*)(data+4),4)==0 ||
????????strncmp((char*)ftyp,(char*)(data+4),4)==0 ||strncmp((char*)mdat,(char*)(data+4),4)==0 )
????????return 0;
????return -1;
}

unsigned int get_size(const uint8_t *data,int size)
{
????unsigned int tmp = 0;
????for(int i=0; i<size; ++i)
????{
????????tmp <<= 8;
????????tmp += *data++;
????}
????return tmp;
}

int seek_tag(uint8_t tag[],uint8_t *data, unsigned int size1,uint8_t **pos,unsigned int *size2)
{
????if(data == NULL || size1 == 0)
????????return -1;
????unsigned int tag_size = get_size(data,4);
????if(tag_size >size1 + 8)
????????return -1;
????unsigned int tmp = 0;
????while(strncmp((char*)data+4,(char*)tag,4) != 0)
????{
????//????printf("%s/n",data+4);

????????if(tag_size==0)
????????????return -1;
????????if(tag_size < size1 + 8)
????????{
????????????data += tag_size;
????????????tmp += tag_size;
????????}
????????else
????????????return -1;
????????tag_size = get_size(data,4);
????}
????printf("find :%c%c%c%c/n",tag[0],tag[1],tag[2],tag[3]);
????if(tmp + tag_size > size1 )
???? printf("warning: the atom may be not complete!/n");
????*pos = data+8;
????*size2 = tag_size -8;
????return tmp;
}

v文章轉載自:http://blog.csdn.net/flyingqr/archive/2010/02/02/5282600.aspx 版權歸原作者,編輯:小乙哥

vector<stsdtable>& get_audio_info(uint8_t *data, unsigned int size, vector<stsdtable>& stable)//stsd

{
????uint8_t * datapos = data;
????Atom *stsd_audio =(Atom *)data;
????int tmp_size = 16;

????printf("size : %u/n",ntohl(stsd_audio->size));
????printf("num_entr: %u/n",ntohl(stsd_audio->num_of_entries));

????for(int i=0; i < ntohl(stsd_audio->num_of_entries); ++i)
????{
????????if(tmp_size > size)//注意

????????????return stable;
????????datapos += tmp_size;
????????stsdtable * audio_entry = (stsdtable *)(datapos);
????????stable.push_back(*audio_entry);//這里存入的是網絡序的數據,使用時需進行轉換

????????tmp_size += ntohl(audio_entry->size);

????
????????printf("--tablesize: %d/n",ntohl(audio_entry->size));
????????printf("--format : %s/n",audio_entry->format);
????????printf("--version : %d/n",ntohs(audio_entry->version));
????????printf("--channels: %d/n",ntohs(audio_entry->channels));
????????printf("--bitpersam: %d/n",ntohs(audio_entry->bitspersample));
????????printf("--IDcompress: %d/n",ntohs(audio_entry->compress_id));????
????????printf("--samplerate: %d.%d/n",ntohs(audio_entry->samplerate1),ntohs(audio_entry->samplerate2));
????????

???? tmp_size = sizeof(stsdtable);
????????if(ntohs(audio_entry->version)==0)
????????{
????????????tmp_size -= 16;
????????}
????????datapos += tmp_size;
????????//if(ntohs(audio_entry->compress_id)==-2)//此處尚需考證

????????if(ntohl(audio_entry->size) > sizeof(stsdtable))
????????{
????????????printf("----atom size:%d/n",get_size(datapos,4));
????????????printf("----atom name:%c%c%c%c/n",datapos[4],datapos[5],datapos[6],datapos[7]);
????????????if(strncmp((char*)datapos,(char*)esds,4)==0)
????????????{
????????????????//handle esds

????????????}
????????}
????}
????return stable;
}

map<unsigned int,sampletable> & get_packet_offset(uint8_t *STBL[], map<unsigned int,sampletable>& table)
{
????//table.insert(pair<long,sampletable>(1,sample));

????unsigned int num_sam_to_chunk = get_size(STBL[0]-4,4);//stsc

????unsigned int num_sample = get_size(STBL[1]-4,4);//stsz

????unsigned int num_chunk = get_size(STBL[2]-4,4);//stco

????unsigned int chunk_index = 0;
????unsigned int next_chunk_index = 0;
????uint8_t *cur_sam_to_chunk = STBL[0];
????uint8_t *cur_sam_size = STBL[1];
????uint8_t *cur_chunk_offset = STBL[2];
????sampletable sample;
????printf("number of stsc entries:%d /nnumber of sample size:%d /nnumber of chunk offset:%d/n",num_sam_to_chunk,num_sample,num_chunk);
????for(unsigned int i = 0; i < num_sam_to_chunk; ++i)//對所有的entries

????{
????????chunk_index = get_size(cur_sam_to_chunk,4);
????????next_chunk_index = get_size(cur_sam_to_chunk+12,4);
????????sample.id_of_sd = get_size(cur_sam_to_chunk+8,4);
????????if(i == num_sam_to_chunk -1)//最后一個

????????{
????????????next_chunk_index = num_chunk+1;
????????}
????????printf("chunk_index:(%d---%d)/n",chunk_index,next_chunk_index);
????????for(unsigned int k=chunk_index; k < next_chunk_index; ++k)//當前chunk序號到下一個chunk序號之間的chunk

????????{//處理所有重復的chunk

????????????printf("chunk_index:%d sample num:%d/n",chunk_index,get_size(cur_sam_to_chunk+4,4));
????????????unsigned int offset = get_size(cur_chunk_offset+(chunk_index-1)*4,4);
????????????for(unsigned int j=0; j < get_size(cur_sam_to_chunk+4,4); ++j)//chunk內地sample數目

????????????{//處理該chunk中的sample

????????????????sample.size = get_size(cur_sam_size,4);????
????????????????printf("--sample offset:%d %x size:%d/n",offset,offset,sample.size);
????????????????table.insert(pair<unsigned int,sampletable>(offset,sample));
????????????????offset = offset + sample.size;
????????????????cur_sam_size += 4;
????????????}
????????????system("pause");
????????????chunk_index++;
????????}
????????cur_sam_to_chunk += 12;
????}
????return table;
}
文章轉載自:http://blog.csdn.net/flyingqr/archive/2010/02/02/5282600.aspx 版權歸原作者,編輯:小乙哥

int
seek_audio_atom( uint8_t *data1, unsigned int size1)
{
????uint8_t tag[] = "mdiaminfsmhd";
????uint8_t *datapos;
????unsigned int tag_size;
????uint8_t *data;
????unsigned int size;
????int offset_of_atom = 0;
????if((offset_of_atom = seek_tag(moov, data1, size1, &data, &size)) == -1)
????????return -1;
????if(offset_of_atom + size >size1)
????{
//some handles

????????printf("moov atom is not complete,need more data");
????}
????data1 = data;
????size1 = size;
????uint8_t *nexttrak = data;
????unsigned int traksize = size;
????int i=0;
????while(1)
????{
????????printf("-----/n");
????????if(seek_tag(trak, nexttrak, traksize, &datapos, &tag_size) != -1)
????????{
????????????nexttrak = datapos + tag_size;
????????????if(size1 < (nexttrak - data1))
????????????????return -1;
????????????traksize = size1 - (nexttrak - data1);
????????????data = datapos;
????????????size = tag_size;
????????}
????????else
????????{
????????????return -1;
????????}
????????i=0;
????????while(i<3)
????????{
????????????if(seek_tag(tag+i*4, data, size, &datapos, &tag_size) != -1)
????????????{
????????????????if(i==2)
???????????????? break;
????????????????data = datapos;
????????????????size = tag_size;
????????????????++i;
????????????}
????????????else
????????????{
????????????????break;
????????????}
????????}
????????if(strncmp("smhd",(char*)(datapos-4),4) == 0)
????????{
????????????if(seek_tag(stbl, data, size, &datapos, &tag_size)!= -1)
????????????{
????????????????printf("—find audio stbl—!/n");
????????????????data = datapos;
????????????????size = tag_size;

????????????????if(seek_tag(stsd, data, size, &datapos, &tag_size) != -1)
????????????????{
????????????????????vector<stsdtable> stable;
//音頻信息

????????????????????get_audio_info(datapos-8, tag_size,stable);
????????????????}

????????????????uint8_t *STBL[3] ={NULL,NULL,NULL};
//

????????????????uint8_t *datapos1;
????????????????unsigned int tag_size1;
//

????????????????if(seek_tag(stsc, data, size, &datapos1, &tag_size1) != -1)
????????????????{
????????????????????STBL[0] = datapos1 + 8;
????????????????}
????????????????uint8_t *datapos2;
????????????????unsigned int tag_size2;
????????????????if(seek_tag(stsz, data, size, &datapos2, &tag_size2) != -1)
????????????????{
????????????????????STBL[1] = datapos2 + 12;
????????????????}
????????????????uint8_t *datapos3;
????????????????unsigned int tag_size3;
????????????????if(seek_tag(stco, data, size, &datapos3, &tag_size3) != -1)
????????????????{
????????????????????STBL[2] = datapos3 + 8;
????????????????}
????????????????if(STBL[0] && STBL[1] && STBL[2] )
????????????????{
????????????????????map<unsigned int,sampletable> postable;
//音頻幀信息

????????????????????get_packet_offset(STBL,postable);
????????????????}
????????????}
????????????return 0;
????????}
????}
????return -1;
}
int main(char arg, char *argv[])
{
????FILE *mp4;
????cout<<"please input the file name :"<<endl;
????string filename;
????cin>>filename;
????mp4 = fopen(filename.c_str(),"rb");
????uint8_t buffer[300000];
????fread(buffer,1,300000,mp4);

????seek_audio_atom((uint8_t*)buffer,300000);

????fclose(mp4);
????return 0;
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/455335.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/455335.shtml
英文地址,請注明出處:http://en.pswp.cn/news/455335.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

時序圖 分支_UML用例圖

UML用例圖用例圖有以下東東:用例參與者關聯系統邊界用例使用橢圓來表示&#xff0c;橢圓里邊寫上用例的名稱:這里的用例可以理解為一個動作或行為,或者一個對象。參與者用一個小人兒,在小人兒下面寫上參與者名稱,例如學生:關聯用一條線表示:把很多個用例放到一個大的矩形框里。…

Python腳本實現漢子轉拼音

起步 中華文化博大精深&#xff0c;是中華民族的財富&#xff0c;吸收和繼承發揚中 華文化&#xff0c;是現代每個炎黃子孫無可推卸的天職。 今天小編就交大家用python寫一個腳本,實現漢子和拼音之間的轉換 pinyin.py 漢字轉拼音,With Python Example: from pinyin impor…

MySQL innodb_table_stats表不存在的解決方法

在做實驗時&#xff0c;使用mysqldump命令報錯[rootlinux-mysql02 3306]# mysqldump -uroot -p123456 -S /u02/data/3306/mysql.sock -A -B --events | gzip > /opt/rep.sql.gzmysqldump: Got error: 1146: Table mysql.innodb_index_stats doesnt exist when using LOCK TA…

自定義封裝 banner 組件

1. 效果圖預覽 2.基本功能 一個簡單方便的輪播圖組件&#xff0c;基于viewpager 基礎上進行的封裝。可設置 項目中圖片&#xff0c;網絡圖片&#xff0c; View&#xff1b;支持循環自動播放&#xff0c;手勢滑動切換&#xff0c;item點擊事件,可設置 點點的樣式寬高、顏色、大小…

vb.net服務器啟動后cpu占用了70_記一次服務器被異常程序占用的解決過程(懷疑黑客攻擊)...

最近在跑實驗&#xff0c;但是突然發現程序運行變慢&#xff0c;然后top命令查看程序運行情況&#xff0c;發現有異常進程&#xff0c;名字叫 bash&#xff0c;占用 2400% CPU計算資源。剛開始懷疑是挖礦程序&#xff0c;因實驗室網絡IP為教育網公網&#xff0c;懷疑被攻擊&…

3gp文件格式研究 (轉windcao的專欄)

序言 06我開始做3gp文件的播放器,但是關于3gp的文檔太少了也很難找,在網友luxh的幫助下,我終于有了第一份關于3gp文件格式的文檔《ISO/IEC 14496-12&#xff0c;ISO媒體文件格式》.在此真心感謝luxh的貢獻.當然了是英文版的,有文檔就不錯了.為了便于查閱和理解,我把之后陸續找…

Android開發必用工具及其進階途徑

三百六十行&#xff0c;行行出狀元&#xff0c;怎么樣才能在Android行業中當個狀元了&#xff0c;開發過程中的高效、自我能力的提升顯得至關重要&#xff0c;步入IT行業更是要時時刻刻學習&#xff0c;新技術更新快&#xff0c;今天將介紹一下Android開發中必用工具及其進階途…

MySQL遇到check the manual that corresponds to your MySQL server version for the right syntax錯誤

原來是MySQL表中不能包含關鍵字 轉載于:https://www.cnblogs.com/flycoding/p/7088465.html

Python腳本實現圖片加水印

起步 圖片是指由圖形、圖像等構成的平面媒體,有形式的事物&#xff0c;我們看到的&#xff0c;是圖畫、照片、拓片等的統稱。 為了保護一些原創圖片的版權,某些時候我們需要在圖片上面,加上水印,當然你可以用Photoshop來做,只不過如果圖片數量過多,亦或者圖片的動態生成的時候…

yarn 怎么查看有多個job在跑_flink on yarn 模式下提示yarn資源不足問題分析

背景在實時計算平臺上通過YarnClient向yarn上提交flink任務時一直卡在那里&#xff0c;并在client端一直輸出如下日志&#xff1a;(YarnClusterDescriptor.java:1036)- Deployment took more than 60 seconds. Please check if the requested resources are available in the Y…

MPEG-2TS碼流編輯的原理及其應用(轉載

[作者&#xff1a;遼寧電視臺 趙季偉] 在當今數字媒體不斷發展、新媒體業務不斷涌現 的前提下&#xff0c;實踐證明襁褓中的新媒體只有兩種經營方略可供選擇&#xff1a;或是購買并集成整套節目&#xff0c;或是低成本深加工新節目&#xff0c;再不可能去按照傳統生產模式…

Python中的yield詳解

閱讀別人的python源碼時碰到了這個yield這個關鍵字&#xff0c;各種搜索終于搞懂了&#xff0c;在此做一下總結&#xff1a; 通常的for…in…循環中&#xff0c;in后面是一個數組&#xff0c;這個數組就是一個可迭代對象&#xff0c;類似的還有鏈表&#xff0c;字符串&#xf…

shell循環結構之while循環

while循環 1) while CONDITION; dostatementstatement<改變循環條件真假的語句>done 編寫腳本&#xff0c;計算1---100的和 #!/bin/bash#sum0i1while [ $i -le 100 ]; dolet sum$sum$ilet i$i1doneecho $sum2) while true; do statementstatementdone #!/bin/bash#while …

python 管道隊列_關于python:Multiprocessing-管道與隊列

Python的多處理程序包中的隊列和管道之間的根本區別是什么&#xff1f;在什么情況下應該選擇一種&#xff1f; 什么時候使用Pipe()有優勢&#xff1f; 什么時候使用Queue()有優勢&#xff1f;Pipe()只能有兩個端點。Queue()可以有多個生產者和消費者。何時使用它們如果需要兩個…

pip默認使用國內鏡像地址

很多小伙伴在ubuntu系統下,使用pip安裝會很慢 以為安裝源在國外服務器上面 今天小編就教大家配置成讓pip默認從國內源中尋找安裝包 首先CtrlAltT打開終端 進入家目錄 cd ~在家目錄中創建一個文件夾,命名為.pip mkdir .pip進入目錄,并創建一個名為pip.conf的文件 cd .pip…

“大型票務系統”和“實物電商系統”的數據庫選型

討論請移步至&#xff1a;http://www.zhiliaotech.com/ideajam/idea/detail/423 相關文章&#xff1a; 《今天你買到票了嗎&#xff1f;——從鐵道部12306.cn站點漫談電子商務站點的“海量事務快速處理”系統》 不能簡單套用“實物電商系統”對“大型票務系統”做需求分析 “大…

FLV文件格式(Z)(轉載)

剛才在看一些關于demux的東西&#xff0c;在處理flv格式的文件的時候&#xff0c;由于自己對flv文件的格式不了解&#xff0c;所以就比較云頭轉向&#xff0c;正好看到了一篇講述flv文件格式的文章&#xff0c;寫的比較明白&#xff0c;所以就轉過來了。O(∩_∩)O~flv頭文件比較…

mysql-5.7中的innodb_buffer_pool_prefetching(read-ahead)詳解

一、innodb的read-ahead是什么&#xff1a; 所謂的read-ahead就是innodb根據你現在訪問的數據&#xff0c;推測出你接下來可能要訪問的數據&#xff0c;并把它們(可能要訪問的數據)讀入 內存。 二、read-ahead是怎么做到的&#xff1a; 1、總的來說read-ahead利用的是程序的局部…

python compare excel_python簡單操作excle的方法

Python操作Excle文件&#xff1a;使用xlwt庫將數據寫入Excel表格&#xff0c;使用xlrd 庫從Excel讀取數據。從excle讀取數據存入數據庫1、導入模塊&#xff1a;import xlrd2、打開excle文件&#xff1a;data xlrd.open_workbook(excel.xls)3、獲取表、行/列值、行/列數、單元值…

collections系列

class Counter(dict):  Counter類繼承dict類、繼承了dict的所有功能計數器&#xff1a; 例&#xff1a;import collections obj collections.Counter(sdkasdioasdjoasjdoasd) print(obj)得&#xff1a;Counter({s: 5, d: 5, a: 4, o: 3, j: 2, k: 1, i: 1}) 拿到前幾位&…