⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mpeg.c

📁 本程序为ST公司开发的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * $Copyright: 
 * ----------------------------------------------------------------
 * This confidential and proprietary software may be used only as
 * authorised by a licensing agreement from Optomech, Co., Ltd.
 *   (C) COPYRIGHT 2006 Optomech, Co., Ltd.
 *       ALL RIGHTS RESERVED
 * The entire notice above must be reproduced on all authorised
 * copies and copies may only be made to the extent permitted
 * by a licensing agreement from Optomech, Co., Ltd..
 * ----------------------------------------------------------------
 * File:     mpeg.c,v
 * Revision: 1.0
 * ----------------------------------------------------------------
 * $
 *
 * Implementation of mpeg demuxer
 */

#include "gendef.h"

#if (0 != HAVE_AAC)

#include "xfile.h"
#include "constants.h"
#include "storage.h"
#include "mpeg.h"

#define MP4_INVALID_AUDIO_TYPE			0x00
#define MP4_MPEG4_AUDIO_TYPE			0x40
#define MP4_MPEG2_AAC_MAIN_AUDIO_TYPE	0x66
#define MP4_MPEG2_AAC_LC_AUDIO_TYPE		0x67
#define MP4_MPEG2_AAC_SSR_AUDIO_TYPE	0x68
#define MP4_MPEG2_AAC_AUDIO_TYPE		MP4_MPEG2_AAC_MAIN_AUDIO_TYPE

#define AAC_Decoder ((tAAC_Decoder *) handle)

#define MP4_IS_MPEG2_AAC_AUDIO_TYPE(type) \
	(((type) >= MP4_MPEG2_AAC_MAIN_AUDIO_TYPE \
		&& (type) <= MP4_MPEG2_AAC_SSR_AUDIO_TYPE))

#define MP4_GET_UINT(p)     (((p)[0]<<24)|((p)[1]<<16)|((p)[2]<<8)|(p)[3])

#define MP4_INDEX           ((tMpegIndex*)buf)

#define AAC_CHANNEL_BUFFER_SIZE (6144>>3)  // 6144 bits per channel

static const char iDemux_DefaultSpeakers[9][4] =
{
    { 0,0,0,0 },
    { 1,0,0,0 },
    { 2,0,0,0 },
    { 3,0,0,0 },
    { 3,0,1,0 },
    { 3,0,2,0 },
    { 3,0,2,1 },
    { 5,0,2,0 },
    { 5,0,2,1 }
};  // from demux.c

static void iDemux_AssignDefaultPositions(oDecoderHandle handle, int nChans)
{
  if (0 == nChans)  // if CC == 0
  {
    nChans = 2;   // suppose!
  }
  AAC_Decoder->Hdr_NumberOfChannels = (char) nChans;

  if (nChans<=8)
  {
    const char *speakers = iDemux_DefaultSpeakers[nChans];

    AAC_Decoder->Hdr_NumberOfFrontChannels = speakers[0];
    AAC_Decoder->Hdr_NumberOfSideChannels  = speakers[1];
    AAC_Decoder->Hdr_NumberOfBackChannels  = speakers[2];
    AAC_Decoder->Hdr_NumberOfLFEChannels   = speakers[3];
  }
  else
  {
    AAC_Decoder->Hdr_NumberOfFrontChannels = (char) nChans;
    AAC_Decoder->Hdr_NumberOfSideChannels  = 0;
    AAC_Decoder->Hdr_NumberOfBackChannels  = 0;
    AAC_Decoder->Hdr_NumberOfLFEChannels   = 0;
  }
}

eDecoderStatus mpeg_find_tag(unsigned int tag, char** ppos, unsigned int* psize)
{
    char target;
    char* pos;
    char* max;
    if(*psize < sizeof(unsigned int))
    {
        return kDecoderStatus_Error;
    }

    target = (char)(0xFF & (tag >> 24));
    pos = *ppos;
    max = pos + (*psize - 3);
    while(pos < max)
    {
        if(*pos == target)
        {
            if(tag == MPEG_GET_TAG(pos))
            {
                pos -= 4;
                *ppos = pos;
                *psize = MPEG_MAKE_SIZE(pos);
                if((max + 3) < (pos + (*psize)))
                {
                    return kDecoderStatus_MoreData;
                }
                return kDecoderStatus_NoError;
            }
        }
        pos ++;
    }
    return kDecoderStatus_Error;
}

eDecoderStatus mpeg_decode_esds(char* pos, unsigned int size, sMpegEsds* pesds)
{
    unsigned char value;
    unsigned char len;
    
    if(0x2C > size)
    {
        return kDecoderStatus_Fatal_BadBitstream;
    }

    value = (unsigned char)pos[0x19];
    len = (unsigned char)pos[0x2A];
    if(MP4_IS_MPEG2_AAC_AUDIO_TYPE(value))
    {
        pesds->Profile = value - MP4_MPEG2_AAC_MAIN_AUDIO_TYPE;
    }
    else if(MP4_MPEG4_AUDIO_TYPE == value)
    {
        if(1 > len)
        {
            return kDecoderStatus_Fatal_BadBitstream;
        }
        pesds->Profile = (pos[0x2B] >> 3) - 1;
    }
    else
    {
        return kDecoderStatus_Fatal_BadBitstream;
    }
    if(0x01 != pesds->Profile)
    {
        return kDecoderStatus_Fatal_UnsupportedFeature;
    }

    if(2 > len)
    {
        /* Ignore case for a while */
        return kDecoderStatus_Fatal_BadBitstream;
    }
    else
    {
        value = ((pos[0x2B] << 1) | (pos[0x2C] >> 7)) & 0x0F;
        /* Ignore 0x0F case for a while */
        if(eAAC_InvalidFrequency <= value)
        {
            return kDecoderStatus_Fatal_BadBitstream;
        }
        else
        {
            pesds->Frequency = (tAAC_Frequency)value;
            pesds->Channel = 0x0F & (pos[0x2C] >> 3);
            if(7 == pesds->Channel)
            {
                pesds->Channel = 8;
            }
        }
    }

    pesds->BitRate = MP4_GET_UINT(pos + 0x22);

    return kDecoderStatus_NoError;
}

eDecoderStatus mpeg_decode_stsc(char* pos, unsigned int size, void* buf)
{
    if(0x1C > size)
    {
        return kDecoderStatus_Fatal_BadBitstream;
    }

//    if(1 != MP4_GET_UINT(pos + 0x0C))   // entry count
//    {
//        return kDecoderStatus_Fatal_BadBitstream;
//    }
    if(1 != MP4_GET_UINT(pos + 0x10))   // 1st chuck
    {
        return kDecoderStatus_Fatal_BadBitstream;
    }
//    if(1 != MP4_GET_UINT(pos + 0x18))   // 1st sample
//    {
//        return kDecoderStatus_Fatal_BadBitstream;
//    }

    MP4_INDEX->framePerChunk = MP4_GET_UINT(pos + 0x14);
    if(0 == MP4_INDEX->framePerChunk)
    {
        return kDecoderStatus_Fatal_BadBitstream;
    }
    MP4_INDEX->chunkMax = (MP4_INDEX->size - sizeof(tMpegIndex) - sizeof(tFrame) - sizeof(tChunk))
                        / ((MP4_INDEX->framePerChunk * sizeof(tFrame)) + sizeof(tChunk));
    MP4_INDEX->frameMax = MP4_INDEX->framePerChunk * MP4_INDEX->chunkMax;
    MP4_INDEX->chunkCount = 0;
    MP4_INDEX->frameCount = 0;
    MP4_INDEX->chunk = (tChunk*)(MP4_INDEX + 1);
    MP4_INDEX->frame = (tFrame*)(MP4_INDEX->chunk + MP4_INDEX->chunkMax + 1);

    return kDecoderStatus_NoError;
}

eDecoderStatus mpeg_decode_stsz(char** ppos, unsigned int* psize, void* buf)
{
    unsigned int count;

    if(0x14 > *psize)
    {
        return kDecoderStatus_MoreData;
    }

    count = MP4_GET_UINT(*ppos + 0x10);
    if(count < MP4_INDEX->frameMax)
    {
        MP4_INDEX->frameMax = count;
    }
    *ppos += 0x14;
    *psize -= 0x14;
    
    return kDecoderStatus_NoError;
}

eDecoderStatus mpeg_read_stsz(char** ppos, unsigned int size, void* buf)
{
    tFrame* out;
    char* read;
    char* end;

    size >>= 2;
    if((MP4_INDEX->frameCount + size) > MP4_INDEX->frameMax)
    {
        size = MP4_INDEX->frameMax - MP4_INDEX->frameCount;
    }

    read = *ppos;
    end = read + (size << 2);
    out = MP4_INDEX->frame + MP4_INDEX->frameCount;
    while(read < end)
    {
        *out ++ = ((read[2] << 8) | read[3]);
        read += 4;
    }
    *out = 0;
    MP4_INDEX->frameCount += size;
    *ppos = read;

    return (MP4_INDEX->frameMax > MP4_INDEX->frameCount) ? kDecoderStatus_MoreData
                                                         : kDecoderStatus_NoError;
}

eDecoderStatus mpeg_decode_stco(char** ppos, unsigned int* psize, void* buf)
{
    unsigned int count;

    if(0x10 > *psize)
    {
        return kDecoderStatus_MoreData;
    }

    count = MP4_GET_UINT(*ppos + 0x0C);
    if(count < MP4_INDEX->chunkMax)
    {
        MP4_INDEX->chunkMax = count;
    }
    *ppos += 0x10;
    *psize -= 0x10;

    return kDecoderStatus_NoError;
}

eDecoderStatus mpeg_read_stco(char** ppos, unsigned int size, void* buf)
{
    tChunk* out;
    char* read;
    char* end;

    size >>= 2;
    if((MP4_INDEX->chunkCount + size) > MP4_INDEX->chunkMax)
    {
        size = MP4_INDEX->chunkMax - MP4_INDEX->chunkCount;
    }

    read = *ppos;
    end = read + (size << 2);
    out = MP4_INDEX->chunk + MP4_INDEX->chunkCount;
    while(read < end)
    {
        *out ++ = MPEG_MAKE_SIZE(read);
        read += 4;
    }
    *out = 0;
    MP4_INDEX->chunkCount += size;
    *ppos = read;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -