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

📄 in_mp4.cpp

📁 WINCE mp4 format source
💻 CPP
📖 第 1 页 / 共 3 页
字号:
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <tchar.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>

#ifndef _WIN32_WCE
#include <mmsystem.h>
#endif

#include "mapplugin.h"
#include "in_mp4.h"

extern "C" {
#include "utils.h"
}

BOOL GetId3TagV1(FILE* fp, MAP_PLUGIN_FILETAG* pTag);
BOOL GetId3TagV2(FILE* fp, MAP_PLUGIN_FILETAG* pTag);

state mp4state = {0};
uint8_t* leftoutbuf = NULL;
int leftoutbuflen = 0;

void flushleftbuf()
{
	if (leftoutbuf) {
		free(leftoutbuf);
		leftoutbuf = NULL;
	}
	leftoutbuf = 0;
}

uint32_t read_callback(void *user_data, void *buffer, uint32_t length)
{
    return fread(buffer, 1, length, (FILE*)user_data);
}

uint32_t seek_callback(void *user_data, uint64_t position)
{
    return fseek((FILE*)user_data, (uint32_t)position, SEEK_SET);
}

uint32_t write_callback(void *user_data, void *buffer, uint32_t length)
{
    return fwrite(buffer, 1, length, (FILE*)user_data);
}

uint32_t truncate_callback(void *user_data)
{
    //_chsize(fileno((FILE*)user_data), ftell((FILE*)user_data));
    //return 1;

	// update tag future is not supported!
	return 0;
}

int skip_id3v2_tag()
{
    unsigned char buf[10];
    int bread, tagsize = 0;

    bread = fread(buf, 1, 10, mp4state.aacfile);
    if (bread != 10) return -1;

    if (!memcmp(buf, "ID3", 3))
    {
        /* high bit is not used */
        tagsize = (buf[6] << 21) | (buf[7] << 14) | (buf[8] << 7) | (buf[9] << 0);

        tagsize += 10;
        fseek(mp4state.aacfile, tagsize, SEEK_SET);
    } else {
        fseek(mp4state.aacfile, 0, SEEK_SET);
    }

    return tagsize;
}

int fill_buffer(state *st)
{
    int bread;

    if (st->m_aac_bytes_consumed > 0)
    {
        if (st->m_aac_bytes_into_buffer)
        {
            memmove((void*)st->m_aac_buffer, (void*)(st->m_aac_buffer + st->m_aac_bytes_consumed),
                st->m_aac_bytes_into_buffer*sizeof(unsigned char));
        }

        if (!st->m_at_eof)
        {
            bread = fread((void*)(st->m_aac_buffer + st->m_aac_bytes_into_buffer),
                1, st->m_aac_bytes_consumed, st->aacfile);

            if (bread != st->m_aac_bytes_consumed)
                st->m_at_eof = 1;

            st->m_aac_bytes_into_buffer += bread;
        }

        st->m_aac_bytes_consumed = 0;

        if (st->m_aac_bytes_into_buffer > 3)
        {
            if (memcmp(st->m_aac_buffer, "TAG", 3) == 0)
                st->m_aac_bytes_into_buffer = 0;
        }
        if (st->m_aac_bytes_into_buffer > 11)
        {
            if (memcmp(st->m_aac_buffer, "LYRICSBEGIN", 11) == 0)
                st->m_aac_bytes_into_buffer = 0;
        }
        if (st->m_aac_bytes_into_buffer > 8)
        {
            if (memcmp(st->m_aac_buffer, "APETAGEX", 8) == 0)
                st->m_aac_bytes_into_buffer = 0;
        }
    }

    return 1;
}

void advance_buffer(state *st, int bytes)
{
    st->m_file_offset += bytes;
    st->m_aac_bytes_consumed = bytes;
    st->m_aac_bytes_into_buffer -= bytes;
}

int file_length(FILE *f)
{
    long end = 0;
    long cur = ftell(f);
    fseek(f, 0, SEEK_END);
    end = ftell(f);
    fseek(f, cur, SEEK_SET);

    return end;
}

int is_adts_header(unsigned char* buf, int length)
{
	int frame_length;
	if (length < 8)
		return 0;

	// check syncword 
	if (!((buf[0] == 0xFF)&&((buf[1] & 0xF6) == 0xF0)))
		return 0;

	// check samplerate
	if ((buf[2]&0x3c)>>2 > 0x11)
		return 0;

	return 1;
}

int is_adif_header(unsigned char* buf, int length)
{
	if (buf[0] == 'A' && buf[1] == 'D' && buf[2] == 'I' && buf[3] == 'F')
		return 1;

	return 0;
}

int is_aac_frame_header(unsigned char* buf, int length)
{
	if (is_adts_header(buf, length))
		return 1;

	if (is_adif_header(buf, length))
		return 1;

	return 0;
}

#if 0
// too late!!
int adts_parse(state *st, __int64 *bitrate, double *length)
{
    static int sample_rates[] = {96000,88200,64000,48000,44100,32000,24000,22050,16000,12000,11025,8000};
    int frames, frame_length;
    int t_framelength = 0;
    int samplerate;
    double frames_per_sec, bytes_per_frame;

    /* Read all frames to ensure correct time and bitrate */
    for (frames = 0; /* */; frames++)
    {
        fill_buffer(st);

        if (st->m_aac_bytes_into_buffer > 7)
        {
            /* check syncword */
            if (!((st->m_aac_buffer[0] == 0xFF)&&((st->m_aac_buffer[1] & 0xF6) == 0xF0)))
                break;

            st->m_tail->offset = st->m_file_offset;
            st->m_tail->next = (struct seek_list*)malloc(sizeof(struct seek_list));
            st->m_tail = st->m_tail->next;
            st->m_tail->next = NULL;

            if (frames == 0)
                samplerate = sample_rates[(st->m_aac_buffer[2]&0x3c)>>2];

            frame_length = ((((unsigned int)st->m_aac_buffer[3] & 0x3)) << 11)
                | (((unsigned int)st->m_aac_buffer[4]) << 3) | (st->m_aac_buffer[5] >> 5);

            t_framelength += frame_length;

            if (frame_length > st->m_aac_bytes_into_buffer)
                break;

            advance_buffer(st, frame_length);
        } else {
            break;
        }
    }

    frames_per_sec = (double)samplerate/1024.0;
    if (frames != 0)
        bytes_per_frame = (double)t_framelength/(double)(frames*1000);
    else
        bytes_per_frame = 0;
    *bitrate = (__int64)(8. * bytes_per_frame * frames_per_sec + 0.5);
    if (frames_per_sec != 0)
        *length = (double)frames/frames_per_sec;
    else
        *length = 1;

    return 1;
}
#else

// fast! (easy!) 
int adts_parse(state *st, __int64 *bitrate, double *length)
{
    static int sample_rates[] = {96000,88200,64000,48000,44100,32000,24000,22050,16000,12000,11025,8000};
    int frames, frame_length;
    int t_framelength = 0;
    int samplerate;
    double frames_per_sec, bytes_per_frame;
	double filelength = (double)file_length(mp4state.aacfile);

#define MAX_AAC_PARSE_HEADER	128

    /* Read all frames to ensure correct time and bitrate */
    for (frames = 0; frames < MAX_AAC_PARSE_HEADER; frames++)
    {
		fill_buffer(st);

		if (st->m_aac_bytes_into_buffer > 7)
        {
            /* check syncword */
            if (!((st->m_aac_buffer[0] == 0xFF)&&((st->m_aac_buffer[1] & 0xF6) == 0xF0)))
                break;

			if (frames == 0)
                samplerate = sample_rates[(st->m_aac_buffer[2]&0x3c)>>2];

            frame_length = ((((unsigned int)st->m_aac_buffer[3] & 0x3)) << 11)
                | (((unsigned int)st->m_aac_buffer[4]) << 3) | (st->m_aac_buffer[5] >> 5);

            t_framelength += frame_length;

            if (frame_length > st->m_aac_bytes_into_buffer)
                break;

            advance_buffer(st, frame_length);
        } else {
            break;
        }
	}

	frames_per_sec = (double)samplerate/1024.0;
    if (frames != 0)
        bytes_per_frame = (double)t_framelength/(double)(frames*1000);
    else
        bytes_per_frame = 0;
    *bitrate = (__int64)(8. * bytes_per_frame * frames_per_sec);
    if (frames_per_sec != 0)
		*length = filelength / ((8. * bytes_per_frame * frames_per_sec) * 1000 / 8);
    else
        *length = 1;

	return 1;
}

#endif

void *decode_aac_frame(state *st, NeAACDecFrameInfo *frameInfo)
{
    void *sample_buffer = NULL;

    do
    {
        fill_buffer(st);

        if (st->m_aac_bytes_into_buffer != 0)
        {
            sample_buffer = NeAACDecDecode(st->hDecoder, frameInfo,
                st->m_aac_buffer, st->m_aac_bytes_into_buffer);

            if (st->m_header_type != 1)
            {
                if (st->last_offset < st->m_file_offset)
                {
                    st->m_tail->offset = st->m_file_offset;
                    st->m_tail->next = (struct seek_list*)malloc(sizeof(struct seek_list));
                    st->m_tail = st->m_tail->next;
                    st->m_tail->next = NULL;
                    st->last_offset = st->m_file_offset;
                }
            }

            advance_buffer(st, frameInfo->bytesconsumed);
        } else {
            break;
        }

    } while (!frameInfo->samples && !frameInfo->error);

    return sample_buffer;
}

#if 0
// too late!!
int aac_seek(state *st, double seconds)
{
    int i, frames;
    int bread;
    struct seek_list *target = st->m_head;

    if (1 /*can_seek*/ && ((st->m_header_type == 1) || (seconds < st->cur_pos_sec)))
    {
        frames = (int)(seconds*((double)st->samplerate/(double)st->framesize) + 0.5);

        for (i = 0; i < frames; i++)
        {
            if (target->next)
                target = target->next;
            else
                return 0;
        }
        if (target->offset == 0 && frames > 0)
            return 0;
        fseek(st->aacfile, st->m_tagsize + target->offset, SEEK_SET);
        st->m_file_offset = target->offset + st->m_tagsize;

        bread = fread(st->m_aac_buffer, 1, 768*6, st->aacfile);
        if (bread != 768*6)
            st->m_at_eof = 1;
        else
            st->m_at_eof = 0;
        st->m_aac_bytes_into_buffer = bread;
        st->m_aac_bytes_consumed = 0;
        st->m_file_offset += bread;

        NeAACDecPostSeekReset(st->hDecoder, -1);

        return 1;
    } else {
        if (seconds > st->cur_pos_sec)
        {
            NeAACDecFrameInfo frameInfo;

            frames = (int)((seconds - st->cur_pos_sec)*((double)st->samplerate/(double)st->framesize));

            if (frames > 0)
            {
                for (i = 0; i < frames; i++)
                {
                    memset(&frameInfo, 0, sizeof(NeAACDecFrameInfo));
                    decode_aac_frame(st, &frameInfo);

                    if (frameInfo.error || (st->m_aac_bytes_into_buffer == 0))
                    {
                        return 0;
                    }
                }
            }

            NeAACDecPostSeekReset(st->hDecoder, -1);
        }
        return 1;
    }
}
#else
int aac_seek(state *st, double seconds)
{
	double filelength = file_length(st->aacfile);
	double offset;
	unsigned long samplerate;
	unsigned char channels;
	NeAACDecFrameInfo frameInfo = {0};

	//seconds = 63.073000000000000;

	offset = (filelength - st->m_tagsize) / (st->m_length / 1000) * seconds;
	offset += st->m_tagsize;

	fseek(st->aacfile, offset, SEEK_SET);
	st->m_file_offset = offset;
	st->m_at_eof = 0;
	st->m_aac_bytes_consumed = 768*6;
	st->m_aac_bytes_into_buffer = 0;
	fill_buffer(st);

	NeAACDecPostSeekReset(st->hDecoder, -1);

	while (!st->m_at_eof && st->m_aac_bytes_into_buffer) {
		if (is_aac_frame_header(st->m_aac_buffer, st->m_aac_bytes_into_buffer)) {
			memset(&frameInfo, 0, sizeof(frameInfo));
			NeAACDecDecode(mp4state.hDecoder, &frameInfo, mp4state.m_aac_buffer, mp4state.m_aac_bytes_into_buffer);
			if (frameInfo.error == 0) {
				break;
			}
		}

		advance_buffer(st, 1);
		fill_buffer(st);
	}
	
	if (st->m_at_eof || !st->m_aac_bytes_into_buffer)
		return 0;

	NeAACDecPostSeekReset(st->hDecoder, -1);
	return 1;
}
#endif

int isourfile(TCHAR *fn)
{
	if (!_tcsicmp(fn + _tcslen(fn) - 4, _T(".MP4")))
		return 1;
	if (!_tcsicmp(fn + _tcslen(fn) - 4, _T(".M4A")))
		return 1;
	if (!_tcsicmp(fn + _tcslen(fn) - 4, _T(".AAC")))
		return 1;
	if (!_tcsicmp(fn + _tcslen(fn) - 4, _T(".3GP")))
		return 1;
	
	return 0;
}

static void remap_channels(unsigned char *data, unsigned int samples, unsigned int bps)
{
    unsigned int i;

    switch (bps)
    {
    case 8:
        {
            unsigned char r1, r2, r3, r4, r5, r6;
            for (i = 0; i < samples; i += 6)
            {
                r1 = data[i];
                r2 = data[i+1];
                r3 = data[i+2];
                r4 = data[i+3];
                r5 = data[i+4];
                r6 = data[i+5];
                data[i] = r2;
                data[i+1] = r3;
                data[i+2] = r1;
                data[i+3] = r6;
                data[i+4] = r4;
                data[i+5] = r5;
            }
        }
        break;

    case 16:
    default:
        {
            unsigned short r1, r2, r3, r4, r5, r6;
            unsigned short *sample_buffer = (unsigned short *)data;
            for (i = 0; i < samples; i += 6)
            {
                r1 = sample_buffer[i];
                r2 = sample_buffer[i+1];
                r3 = sample_buffer[i+2];
                r4 = sample_buffer[i+3];
                r5 = sample_buffer[i+4];
                r6 = sample_buffer[i+5];
                sample_buffer[i] = r2;
                sample_buffer[i+1] = r3;
                sample_buffer[i+2] = r1;
                sample_buffer[i+3] = r6;
                sample_buffer[i+4] = r4;
                sample_buffer[i+5] = r5;

⌨️ 快捷键说明

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