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

📄 cpi_player_codec_mpeg.c

📁 VC++视频开发实例集锦(包括“远程视频监控”"语音识别系统"等13个经典例子)
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * MPEG 音频解码 (using MAD)
 */
#include "stdafx.h"
#include "globals.h"
#include "CPI_Player_CoDec.h"
#include "libmad/mad.h"
// #include "mmsystem.h"
#include "CPI_Stream.h"
#include "CPI_ID3.h"
#pragma comment(lib, "winmm.lib")

# define SAMPLE_DEPTH	16
# define scale(x, y)	dither((x), (y))

struct xing {
    long flags;
    unsigned long frames;
    unsigned long bytes;
    unsigned char toc[100];
    long scale;
};

enum {
    XING_FRAMES = 0x00000001L,
    XING_BYTES  = 0x00000002L,
    XING_TOC    = 0x00000004L,
    XING_SCALE  = 0x00000008L
};

# define XING_MAGIC	(('X' << 24) | ('i' << 16) | ('n' << 8) | 'g')

struct dither {
    mad_fixed_t error[3];
    mad_fixed_t random;
};

typedef struct {
    CPs_InStream* m_pInStream;

    unsigned long size;				

    CPs_CoDecOptions options;	

    struct xing xing;				

    struct mad_stream stream;	
    struct mad_frame frame;		
    struct mad_synth synth;			

    unsigned int samplecount;		

    mad_timer_t timer;			
    mad_timer_t length;				
    unsigned long rate;				
    unsigned long frames;		

    CPs_FileInfo info;			

    unsigned char buffer[40000];	
    unsigned int buflen;		
} CPs_CoDec_MPEG;


static
int parse_xing(struct xing *xing, struct mad_bitptr ptr, unsigned int bitlen)
{
    if (bitlen < 64 || mad_bit_read(&ptr, 32) != XING_MAGIC)
        goto fail;

    xing->flags = mad_bit_read(&ptr, 32);
    bitlen -= 64;

    if (xing->flags & XING_FRAMES) {
        if (bitlen < 32)
            goto fail;

        xing->frames = mad_bit_read(&ptr, 32);
        bitlen -= 32;
    }

    if (xing->flags & XING_BYTES) {
        if (bitlen < 32)
            goto fail;

        xing->bytes = mad_bit_read(&ptr, 32);
        bitlen -= 32;
    }

    if (xing->flags & XING_TOC) {
        int i;

        if (bitlen < 800)
            goto fail;

        for (i = 0; i < 100; ++i)
            xing->toc[i] = (unsigned char) mad_bit_read(&ptr, 8);

        bitlen -= 800;
    }

    if (xing->flags & XING_SCALE) {
        if (bitlen < 32)
            goto fail;

        xing->scale = mad_bit_read(&ptr, 32);
        bitlen -= 32;
    }

    return 0;

fail:
    xing->flags = 0;
    return -1;
}


static
int scan_header(CPs_InStream* pInStream, struct mad_header *header, struct xing *xing)
{
    struct mad_stream stream;
    struct mad_frame frame;
    unsigned char buffer[8192];
    unsigned int buflen = 0;
    int count = 0, result = 0;

    mad_stream_init(&stream);
    mad_frame_init(&frame);

    if (xing)
        xing->flags = 0;

    while (1) {
        if (buflen < sizeof(buffer)) {
            DWORD bytes;

            if(pInStream->Read(pInStream, buffer + buflen, sizeof(buffer) - buflen, &bytes) == FALSE
                    || bytes == 0)
            {
                result = -1;
                break;
            }

            buflen += bytes;
        }

        mad_stream_buffer(&stream, buffer, buflen);

        while (1) {
            if (mad_frame_decode(&frame, &stream) == -1) {
                if (!MAD_RECOVERABLE(stream.error))
                    break;

                continue;
            }

            if (count++ ||
                    (xing && parse_xing(xing, stream.anc_ptr,
                                        stream.anc_bitlen) == 0))
                break;
        }

        if (count || stream.error != MAD_ERROR_BUFLEN)
            break;

        memmove(buffer, stream.next_frame,
                buflen = &buffer[buflen] - stream.next_frame);
    }

    if (count) {
        if (header)
            *header = frame.header;
    }
    else
        result = -1;

    mad_frame_finish(&frame);
    mad_stream_finish(&stream);

    return result;
}



static __inline
unsigned long prng(unsigned long state)
{
    return (state * 0x0019660dL + 0x3c6ef35fL) & 0xffffffffL;
}


static __inline
signed int dither(mad_fixed_t sample, struct dither *dither)
{
    unsigned int scalebits;
    mad_fixed_t output, mask, random;

    enum {
        MIN = -MAD_F_ONE,
        MAX =  MAD_F_ONE - 1
    };

    sample += dither->error[0] - dither->error[1] + dither->error[2];

    dither->error[2] = dither->error[1];
    dither->error[1] = dither->error[0] / 2;

    output = sample + (1L << (MAD_F_FRACBITS + 1 - SAMPLE_DEPTH - 1));

    scalebits = MAD_F_FRACBITS + 1 - SAMPLE_DEPTH;
    mask = (1L << scalebits) - 1;

    random  = prng(dither->random);
    output += (random & mask) - (dither->random & mask);

    dither->random = random;

    if (output > MAX) {
        output = MAX;

        if (sample > MAX)
            sample = MAX;
    }
    else if (output < MIN) {
        output = MIN;

        if (sample < MIN)
            sample = MIN;
    }

    output &= ~mask;

    dither->error[0] = sample - output;

    return output >> scalebits;
}


static
void pack_pcm(unsigned char **pcm, unsigned int nsamples,
              mad_fixed_t const *ch1, mad_fixed_t const *ch2)
{
    register signed int s0, s1;
    static struct dither d0, d1;

    if (ch2) {  /* stereo */
        while (nsamples--) {
            s0 = scale(*ch1++, &d0);
            s1 = scale(*ch2++, &d1);
# if SAMPLE_DEPTH == 16
            (*pcm)[0 + 0] = s0 >> 0;
            (*pcm)[0 + 1] = s0 >> 8;
            (*pcm)[2 + 0] = s1 >> 0;
            (*pcm)[2 + 1] = s1 >> 8;

            *pcm += 2 * 2;
# elif SAMPLE_DEPTH == 8
            (*pcm)[0] = s0 ^ 0x80;
            (*pcm)[1] = s1 ^ 0x80;

            *pcm += 2;
# else
#  error "bad SAMPLE_DEPTH"
# endif
        }
    }
    else {  /* mono */
        while (nsamples--) {
            s0 = scale(*ch1++, &d0);

# if SAMPLE_DEPTH == 16
            (*pcm)[0] = s0 >> 0;
            (*pcm)[1] = s0 >> 8;

            *pcm += 2;
# elif SAMPLE_DEPTH == 8
            *(*pcm)++ = s0 ^ 0x80;
# endif
        }
    }
}


static void cleanup(CPs_CoDec_MPEG *context)
{
    if(context->m_pInStream)
    {
        context->m_pInStream->Uninitialise(context->m_pInStream);
        context->m_pInStream = NULL;

        mad_synth_finish(&context->synth);
        mad_frame_finish(&context->frame);
        mad_stream_finish(&context->stream);
    }
}

void CPP_OMMP3_Uninitialise(CPs_CoDecModule* pModule);
BOOL CPP_OMMP3_OpenFile(CPs_CoDecModule* pModule, const char* pcFilename, DWORD dwCookie, HWND hWndOwner);
void CPP_OMMP3_CloseFile(CPs_CoDecModule* pModule);
void CPP_OMMP3_Seek(CPs_CoDecModule* pModule, const int iNumerator, const int iDenominator);
void CPP_OMMP3_GetFileInfo(CPs_CoDecModule* pModule, CPs_FileInfo* pInfo);
//
BOOL CPP_OMMP3_GetPCMBlock(CPs_CoDecModule* pModule, void* pBlock, DWORD* pdwBlockSize);
int CPP_OMMP3_GetCurrentPos_secs(CPs_CoDecModule* pModule);
//
void CP_InitialiseCodec_MPEG(CPs_CoDecModule* pCoDec)
{
    CPs_CoDec_MPEG *pContext;

    pCoDec->Uninitialise = CPP_OMMP3_Uninitialise;
    pCoDec->OpenFile = CPP_OMMP3_OpenFile;
    pCoDec->CloseFile = CPP_OMMP3_CloseFile;
    pCoDec->Seek = CPP_OMMP3_Seek;
    pCoDec->GetFileInfo = CPP_OMMP3_GetFileInfo;

    pCoDec->GetPCMBlock = CPP_OMMP3_GetPCMBlock;
    pCoDec->GetCurrentPos_secs = CPP_OMMP3_GetCurrentPos_secs;

    pCoDec->m_pModuleCookie = malloc(sizeof(CPs_CoDec_MPEG));

⌨️ 快捷键说明

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