MP4音频解码信息(转帖加注释)

iOS AVDemo(12):视频解码,MP4 → H.264/H.265 → YUV 的源码 iOS/Android 客户端开发同学如果想要开始学习音视频开发,最丝滑的方式是对有一定了解后,再借助 iOS/Android 平台的音视频能力上手去实践音视频的过程,并借助来分析和理解对应的音视频数据。在这个栏目,我们将通过拆解流程并实现 Demo 来向大家介绍如何在 iOS/Android 平台上手音视频开发。。这个 Demo 里包含以下内容:1)实现一个视频解封装模块;2)实现一个视频解码模块; 阅读详情

http://blog.youkuaiyun.com/linzhiji/article/details/5840031

注释:

      1。3gp和MP4中的AAC的私有数据保存在esds的0x05标签的数据,

       结构为 05 + 长度 + 内容。

      将长度赋值给 extradatasize

      将内容赋值给 extradata

      长度的计算函数在ffmpeg中的static int mp4_read_descr_len(ByteIOContext *pb)

 

      2。avc/h264的extradata和extradata信息在avcc atom中,将avcc atom去掉type和长度(8个字节)后的长度赋予extradatasize,内容赋值给extradata.

 

 

 

 

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 */ /* sample files at http://www.3ivx.com/showcase.html use this tag //
MP3,        0x6D730055  // MPEG layer 3 //
OGG_VORBIS, OggS //// sample files at http://heroinewarrior.com/xmovie.php3 use this tag //
AAC,        mp4a // MPEG-4 AAC //
AC3,        ac-3 // ETSI TS 102 366 Annex F //
AMR_NB,     samr // AMR-NB 3gp //
AMR_WB,     sawb // AMR-WB 3gp//
GSM,        agsm
ALAC,       alac // Apple Lossless //
QCELP,      Qclp
QCELP,      sqcp // ISO Media fourcc //
QDM2,       QDM2 // QDM2 //
DVAUDIO,    vdva
DVAUDIO,    dvca
WMAV2,      WMA2
这个获取比较简单,下面是解码私有数据的获取:
这些解码私有数据也保存在Atom中,通常在上面结构体的后面,有esds、frma、mp4a、wave。AAC的私有数据保存在esds的0x05标签的数据,QDM2的则是"wave"Atom的数据部分(以下按顺序分析):
   4字节 长度
   4字节 "esds" or "m4ds" 标志
   4字节 版本标识

   1字节 ES描述类型标签 0x03
   --3字节 扩展描述类型标签 可能没有
   1字节 描述类型长度 
   2字节 ES ID
   1字节 流优先级

   1字节 解码配置描述类型标签 0x04
   --3字节 扩展描述类型标签 可能没有
   1字节 描述类型长度 
   1字节 描述对象ID 
   1字节 
   3字节 
   4字节
   4字节

   1字节 解码配置描述类型标签 0x05
   --3字节 扩展描述类型标签 可能没有
   1字节 长度 

   1字节 0x06
   0x06不再分析
下面是一个例子:
长度 标签 
00015218h: 00 00 00 10 73 6D 68 64 00 00 00 00 00 00 00 00 ; ....smhd........
00015228h: 00 00 00 24 64 69 6E 66 00 00 00 1C 64 72 65 66 ; ...$dinf....dref
00015238h: 00 00 00 00 00 00 00 01 00 00 00 0C 75 72 6C 20 ; ............url 
00015248h: 00 00 00 01 00 02 C0 97 73 74 62 6C 00 00 00 5B ; ......罈stbl...[
00015258h: 73 74 73 64 00 00 00 00 00 00 00 01 00 00 00 4B ; stsd...........K
00015268h: 6D 70 34 61 00 00 00 00 00 00 00 01 00 00 00 00 ; mp4a............
00015278h: 00 00 00 00 00 01 00 10 00 00 00 00 7D 00 00 00 ; ............}...
00015288h: 00 00 00 27 65 73 64 73 00 00 00 00 03 19 00 00 ; ...'esds........
00015298h: 00 04 11 40 15 00 00 D2 00 00 BB 88 00 00 7D 00 ; ...@...?.粓..}.
000152a8h: 05 02 12 88 06 01 02                            ; ...?..

0x12 0x88即私有数据(对应ffmpeg中AVCodecContext.extradata)
下面是mp4音频部分分析的代码:

//MP4Analyze.h

#define uint8_t unsigned char

/******atom tag*******/
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;


/****audio format****/
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";

/*** We may not need these ***/
#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;

/***** result is stored here ******/
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;

/**
*** mp4存在宽度为8字节的wide atom tag,需要注意,这里暂未考虑
**/

/*
* check if a mov/mp4/3gp type
*/
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;
}
/* if found,return the offset from the data[0]*/
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;
}
/*** elementary stream descriptor analyse ***/
/*
unsigned int codec_get_tag(const AVCodecTag *tags, int id)
{
    while (tags->id != CODEC_ID_NONE) {
        if (tags->id == id)
            return tags->tag;
        tags++;
    }
    return 0;
}
/* may not need analyse
int esds_analyze(uint8_t *data, unsigned int size)
{
    return 0;
}
*/

/*version == 2 ??? reffer to ffmpeg source mov.c line 943
if (format == MKTAG('l','p','c','m'))
        st->codec->codec_id = mov_get_lpcm_codec_id(st->codec->bits_per_coded_sample, flags);
*/
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;
}

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;
}


将aac音频流和h264视频流复用成mp4格式文件 上一篇文章给出了将flv文件解复用的解决方案: 从flv文件中提取h264码流(使用av_bsf_send_packet和av_bsf_receive_packet) 这篇文章给出复用mp4文件的解决方案,源代码还是参考了雷神的demo: 最简单的基于FFmpeg的封装格式处理:视音频复用器(muxer) 自己对代码逻辑进行了梳理和注释,对于一些看不懂的逻辑和觉得没必要的逻辑进行了优化,大家可以参考一下。注意这里使用的aac音频是adts封装形式的,h264视频流是annexb封装形式的,也就是说可以直接用 阅读详情

相关推荐

海康威视GigE工业相机的python调用demo

默认路径安装完成后,在路径C:\Program Files (x86)\MVS\Development\Samples\Python\BasicDemo下的BasicDemo.py中,海康威视官方提供了基本的调用方法,本文也是基于这个修改的。BasicDemo.py提供了通过枚举选择相机的方法,在官方的另一个DEMO:ConnectSpecCamera.py中提供了另一种不通过枚举,直接访问特定IP相机的方法,也可以参考。另外,如果每台相机都定义了唯一的用户定义名,也可以通过用户定义名来区分相机。

xulibo5828的博客 2108

MP4音频解码信息

MP4文件格式分为头部和数据两部分,头部是由许多被称作Atom的结构单元嵌套或排列而成,数据部分则完全为实际数据不包含元信息,因此具体解码时音视频帧的位置和大小都要在头部获取。详细内容见以下链接:http://wqyuwss.52rd.net 这里总结下音频解码信息获取的一些经验,当然详细内容需要查看quick time file format的文档。MP4的音频解码信息保存在如下嵌套的Atom中

flyingqr的专栏 1915

001-基础入门-Web演示源码&资源&工具箱等

小迪安全2023笔记

wushangyu32335的博客 4260

mp4解析

mp4解析

u010450027的专栏 2101

ANSYS Help USER300

USER 300概述单元描述输入数据假设与限制条件 概述 单元描述 Mechanical APDL提供了一种方便的方法来创建自定义的单元,命名为USER300,可以创建几乎任何单元类型。 UserElem子程序为Mechanical APDL在单元类型创建上提供了一个接口,可传递用户自定义单元创建时所需的所有数据,然后从自定义单元返回所有数据和结果,以更新数据库和文件。因为通过接口可以访问数据库和文件信息,所以很少需要了解Mechanical APDL数据库程序和文件结构。该接口还提供了获取Mechanic

weixin_47019765的博客 2234

论文阅读--射频电源在半导体领域的应用

射频电源(RF Power Supply)是能够输出300kHz~300GHz正弦波电压的高频交流电源,在半导体制造领域,射频电源的典型工作频率范围为400kHz∼60 MHz,主要由射频发生器(功率源)、匹配器及配套控制电路组件构成,其关键组件包括变压器与电抗器、晶闸管、绝缘栅双极型晶体管(IGBT)、钣金件、铜材及各种电子元器件。射频电源是刻蚀和薄膜沉积工艺的核心,主要用于产生等离子体,以增强气体反应活性,其性能直接影响反应腔体内等离子体的浓度、均匀性和稳定性。

伊丽莎白的学习之路 2337

MP4系列之--如何获取mp4文件信息

转自http://zhangwenxin82.blog.163.com/blog/static/1145959562009612024837/,转载请注明出处。         计算电影长度 方法1 从mvhd - movie header atom中找到time scale和duration,duration除以time scale即是整部电影的长度。 time scale相当于定义

simon的天空 5712

Mac Studio M5 Ultra本地部署大模型实战:从内存原理到Ollama开发工作流

大模型推理的性能瓶颈往往不在算力,而在于内存能否装下整个模型、带宽能否持续供得上。Transformer架构每生成一个token都需要把权重完整扫一遍,决定了这本质上是内存密集型任务——统一内存架构因此成为本地部署的关键通路,超大容量与高带宽并行,让“装得下”和“跑得快”同时成立。模型量化技术(如Q4_K_M)则是另一项决定性软件策略,用轻微精度损失换取更低的硬件门槛,也是Ollama本地部署从7B到70B各类模型必做的前置功课。当本地推理服务跑起来后,借助VS Code等开发工具的OpenAI兼容API接

weixin_29043895的博客 446

MTK 视频默认都是用mp4

---------------- frameworks/av/media/libmedia/MediaProfiles.cpp ---------------- index fbdd16b..0ed2d94 100644 @@ -780,7 +780,7 @@ MediaProfiles::createDefaultCamcorderTimeLapseQcifProfile(camcorder_q...

Me_Ordinary的专栏 1369

在WIN10系统中安装TIA博途V18,重启后提示安装介质不可用,请插入DVD 或检查网络连接的解决办法

在WIN10系统中安装TIA博途V18,重启后提示安装介质不可用,请插入DVD 或检查网络连接的解决办法

Robot_PLC_HMI_Automation 1万+

YOLOv8 改进涨点 | 模块即插即用 直接可用

在目标检测任务中,注意力机制能够帮助模型聚焦于图像中的关键区域,显著提升检测精度。。创建模块代码注册模块修改任务解析tasks.py创建YAML配置文件模块核心优势适用场景计算开销SOCA捕获二阶统计信息,增强通道间相关性需要精细特征区分的场景中等SK自适应多尺度核选择多尺度目标检测中等偏高显式特征聚集-分配机制全局上下文建模中等A2-Net双线性注意力,高效全局交互复杂场景理解中等偏高CrissCross线性复杂度全局上下文高分辨率输入,长距离依赖较低。

u012133341的博客 2257

MP4文件格式详解——结构概述

MP4文件格式详解(ISO-14496-12/14) Author:Pirate Leo Email:codeevoship@gmail.com 一、基本概念 1、 文件,由许多Box和FullBox组成。 2、 Box,每个Box由Header和Data组成。 3、 FullBox,是Box的扩展,Box结构的基础上在Header中增加8bits version和24bits fla

胡同里的庇护所(Pirate Leo's Shelter) 7万+

基于STM32开发板的USB MIDI键盘实现

在本文中,我们介绍了如何使用STM32开发板和相应的软件工具来实现USB MIDI键盘。通过配置STM32CubeMX和编写相应的源代码,我们能够将STM32开发板转换为一个功能齐全的USB MIDI设备。我们将使用STM32开发板和相应的软件工具来实现这一功能,并提供相应的源代码供参考。此时,您应该可以使用STM32开发板作为USB MIDI键盘,并在按键按下时听到相应的音符。在STM32CubeMX中,选择适当的STM32型号,并启动一个新的项目。然后,将生成的可执行文件烧录到STM32开发板中。

2301_79326616的博客 1588

海思HI3531D使用ffmpeg实时封装多路H264视频+AAC音频为MP4

零、前提: 多路实时封装H264裸码流和AAC音频到mp4容器,不涉及编解码方面。 第一次做视音频方面项目,以此文做个笔记。 参考了雷神写的许多ffmpeg的文章,雷神的是对封装容器的转换。 同时参考了https://blog.youkuaiyun.com/zhenglie110/article/details/88030925的实时封装,他的代码已经实现了大部分主要功能,我也是在项目中拿他的代码进行加工的,...

qq_30659437的博客 7676

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

android使用FFmpeg解码MP4中的音频并使用AudioTrack播放

虽然网上有很多类似标题的博客,但是他们的代码运行之后一般都会有杂音或者其他的播放问题,原因也很简单,就是他们的代码太老了,网上现在一般流传的都是FFmpeg2点多的相关代码,而官网都是4点多了,所以一些方法的废弃更替导致了别人说能正常播放,而你的代码却运行异常。 废话不多说了,我使用的的ffmpeg-3.3.9编译的.so库,android-ndk-r14b。如果你也跟我的配置一样那就OK了,如...

wozuihaole的博客 769

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

iOS音视频开发五:音频解码

这里是第五篇:iOS 音频解码 Demo。这个 Demo 里包含以下内容: 1)实现一个音频解封装模块; 2)实现一个音频解码模块; 3)实现对 MP4 文件中音频部分的解封装和解码逻辑,并将解封装、解码后的数据存储为 PCM 文件; 4)详尽的代码注释,帮你理解代码逻辑和原理。 前四篇: iOS要开发,采集音频并存储为 PCM 文件 iOS音视频开发二:音频编码,采集 PCM 数据编码为 AAC iOS音视频开发三:音频封装,采集编码并封装为 M4A iOS

m0_60259116的博客 1596

iOS AVDemo(5):音频解码

iOS/Android 客户端开发同学如果想要开始学习音视频开发,最丝滑的方式是对有一定了解后,再借助本地平台的音视频能力上手去实践音视频的过程,并借助来分析和理解对应的音视频数据。在这个栏目,我们将通过拆解流程并实现 Demo 来向大家介绍如何在 iOS/Android 平台上手音视频开发。。这个 Demo 里包含以下内容:1)实现一个音频解封装模块;2)实现一个音频解码模块;3)实现对 MP4 文件中音频部分的解封装和解码逻辑,并将解封装、解码后的数据存储为 PCM 文件;

irainsa的博客 290

ffmpeg学习(6)音频解码、音频数据处理

ffmpeg项目巨大,本文针对 ffmpeg学习(3)编码、解码的流程介绍 中解码部分,实现了一个最简单的音频解码器,之后再对解码后的音频数据进行处理,例如调整位深度/采样率。最后将音频数据保存为pcm文件并使用Audacity播放。先给出基本的流程,如下图。 流程图中使用的函数,可以通过其名称了解其用处,网上参考较多,也可以直接看api文档。 其中关于结构体AVFrame和AVPackt的介绍参看文章: ffmpeg学习 结构体分析AVFrame ffmpeg学习 结构体分析AVPack 关于音频采样数

热爱生活,忠于自己 2657

h264和pcm文件打包成mp4文件

h264和pcm文件打包成mp4文件 测试命令为Debug目录下执行:conver_mp4.exe 1280 720 16000 enc.h264 000.pcm out.mp4; conver_mp4.exe 视频宽 视频高 音频采样率 h264文件 pcm文件 输出mp4文件 欢迎使用Markdown编辑器 你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用...

maokedou的博客 3765

iOS音视频开发十二:视频解码,MP4 → H.264/H.265 → YUV 的源码

本系列文章通过拆解采集 → 编码 → 封装 → 解封装 → 解码 → 渲染流程并实现 Demo 来向大家介绍如何在 iOS/Android 平台上手音视频开发。 这里是第十二篇:iOS 视频解码 Demo。这个 Demo 里包含以下内容: 1)实现一个视频解封装模块; 2)实现一个视频解码模块; 3)串联视频解封装和解码模块,将解封装的 H.264/H.265 数据输入给解码模块进行解码,并存储解码后的 YUV 数据; 4)详尽的代码注释,帮你理解代码逻辑和原理。

m0_60259116的博客 956

终极MPV音频解码实战指南:从无声到高保真的完整解决方案

你是否在使用MPV命令行媒体播放器时遭遇过音频无声、杂音干扰或音画不同步的困扰?作为一款功能强大的开源播放器,MPV在视频播放方面表现出色,但在音频解码上偶尔会出现一些意想不到的问题。今天,让我们一起来探索如何彻底解决MPV音频解码异常,让每一次播放都清晰流畅。🎧 ## 🎯 核心问题定位:为什么MPV音频会出问题? MPV的音频处理流程就像一个精密的音响系统,从文件解码到最终输出需要多个环

gitblog_00184的博客 730

FFmpeg分离(解封装)视频和音频

FFmpeg分离(解封装)视频和音频

m0_60259116的博客 1992

3步终极指南:快速修复MPV播放器音频解码异常与声音卡顿问题

你是否曾满怀期待地打开MPV播放器准备欣赏一部电影,却发现音频断断续续、无声或充满杂音?这种音频解码异常不仅破坏观影体验,更可能让你错过关键剧情。作为一款强大的命令行媒体播放器,MPV在处理复杂音频格式时偶尔会遇到挑战,但通过正确的诊断和配置,这些问题都能迎刃而解。 本文将为你提供从快速诊断到深度优化的完整解决方案,帮助你彻底解决MPV音频问题,让声音还原如初。 ## 问题识别:你的MPV音频

gitblog_00272的博客 945
上一篇: 网上偶然间看到的,转一下
下一篇: 实现kodak V系DC 充当MP4 的方法!!!
eustoma
博客等级 码龄18年 79粉丝 54原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值