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

📄 in_mp4.cpp

📁 WINCE mp4 format source
💻 CPP
📖 第 1 页 / 共 3 页
字号:
		}

		if (mp4state.useAacLength || (mp4state.timescale != mp4state.samplerate)) {
			sample_count = frameInfo.samples;
		}
		else {
			sample_count = (unsigned int)(dur * frameInfo.channels);
			if (!mp4state.useAacLength && !mp4state.initial && (mp4state.sampleId < mp4state.numSamples/2) && (dur*frameInfo.channels != frameInfo.samples)) {
				mp4state.useAacLength = 1;
				sample_count = frameInfo.samples;
			}
		}

		if (mp4state.initial && (sample_count < mp4state.framesize*mp4state.channels) && (frameInfo.samples > sample_count)) {
			delay = frameInfo.samples - sample_count;
		}

		if (sample_count > 0 && sample_buffer) {
			buf = (char *)sample_buffer;
			mp4state.initial = 0;
			buf += delay * 2;
	        
			if (frameInfo.channels == 6 && frameInfo.num_lfe_channels)
				remap_channels((unsigned char*)buf, sample_count, 16);

			int l = sample_count * 16 / 8;

			if (outbuflen - *outbuf < l) {
				memcpy(outbuf + *outlen, buf, outbuflen - *outbuf);
				leftoutbuf = (uint8_t*)malloc(l - outbuflen - *outbuf);
				leftoutbuflen = l - outbuflen - *outbuf;
				memcpy(leftoutbuf, buf + outbuflen - *outbuf, leftoutbuflen);

				*outlen = outbuflen;
			}
			else {
				memcpy(outbuf + *outlen, buf, l);
				*outlen += l;
			}
		}

		mp4state.decode_pos_ms += (double)sample_count * 1000.0 /
                        ((double)frameInfo.samplerate * (double)frameInfo.channels);
	}

	if (mp4state.last_frame && !leftoutbuflen)
		return PLUGIN_RET_EOF;

	return PLUGIN_RET_SUCCESS;
}

int aacdecode(uint8_t *outbuf, uint32_t outbuflen, uint32_t *outlen)
{
	void *sample_buffer;
	char *buf;
	NeAACDecFrameInfo frameInfo;

	*outlen = 0;

	if (!mp4state.aacfile)
		return PLUGIN_RET_ERROR;

	if (leftoutbuf && leftoutbuflen) {
		if (outbuflen < leftoutbuflen) {
			memcpy(outbuf, leftoutbuf, outbuflen);
			*outlen = outbuflen;

			memmove(leftoutbuf, leftoutbuf + outbuflen, leftoutbuflen - outbuflen);
			leftoutbuflen -= outbuflen;
			return PLUGIN_RET_SUCCESS;
		}
		else {
			memcpy(outbuf, leftoutbuf, leftoutbuflen);
			outbuf += leftoutbuflen;
			*outlen += leftoutbuflen;
			
			free(leftoutbuf);
			leftoutbuflen = 0;
		}
	}

	while (outbuflen - *outlen && !mp4state.last_frame) {
		memset(&frameInfo, 0, sizeof(NeAACDecFrameInfo));
		sample_buffer = decode_aac_frame(&mp4state, &frameInfo);
		if (mp4state.m_aac_bytes_into_buffer == 0) {
			mp4state.last_frame = 1;
			break;
		}
		if (frameInfo.error) {
			return PLUGIN_RET_ERROR;
		}
		if (frameInfo.samplerate != mp4state.samplerate) {
 			return PLUGIN_RET_ERROR;
		}

		if (frameInfo.samples > 0 && sample_buffer) {
			buf = (char *)sample_buffer;
			mp4state.initial = 0;
	        
			if (frameInfo.channels == 6 && frameInfo.num_lfe_channels)
				remap_channels((unsigned char*)buf, frameInfo.samples, 16);

			int l = frameInfo.samples * 16 / 8;

			if (outbuflen - *outbuf < l) {
				memcpy(outbuf + *outlen, buf, outbuflen - *outbuf);
				leftoutbuf = (uint8_t*)malloc(l - outbuflen - *outbuf);
				leftoutbuflen = l - outbuflen - *outbuf;
				memcpy(leftoutbuf, buf + outbuflen - *outbuf, leftoutbuflen);

				*outlen = outbuflen;
			}
			else {
				memcpy(outbuf + *outlen, buf, l);
				*outlen += l;
			}
		}

		mp4state.decode_pos_ms += (double)frameInfo.samples * 1000.0 /
			((double)frameInfo.samplerate* (double)frameInfo.channels);

		if (frameInfo.channels > 0 && mp4state.samplerate > 0)
			mp4state.cur_pos_sec += ((double)(frameInfo.samples/frameInfo.channels))/(double)mp4state.samplerate;
	}

	if (mp4state.last_frame && !leftoutbuflen)
		return PLUGIN_RET_EOF;

	return PLUGIN_RET_SUCCESS;
}

int decode(uint8_t *outbuf, uint32_t outbuflen, uint32_t *outlen)
{
	if (mp4state.filetype)
		return aacdecode(outbuf, outbuflen, outlen);
	else
		return mp4decode(outbuf, outbuflen, outlen);
}

/* Convert UTF-8 coded string to UNICODE
   Return number of characters converted */
int utf8ToUnicode( const char* lpMultiByteStr, WCHAR* lpWideCharStr, int cmbChars )
{
    const unsigned char*    pmb = (unsigned char  *)lpMultiByteStr;
    unsigned short*         pwc = (unsigned short *)lpWideCharStr;
    const unsigned char*    pmbe;
    size_t  cwChars = 0;

    if ( cmbChars >= 0 ) {
        pmbe = pmb + cmbChars;
    } else {
        pmbe = (unsigned char *)((size_t)-1);
    }

    while ( pmb < pmbe ) {
        char            mb = *pmb++;
        unsigned int    cc = 0;
        unsigned int    wc;

        while ( (cc < 7) && (mb & (1 << (7 - cc)))) {
            cc++;
        }

        if ( cc == 1 || cc > 6 )                    // illegal character combination for UTF-8
            continue;

        if ( cc == 0 ) {
            wc = mb;
        } else {
            wc = (mb & ((1 << (7 - cc)) - 1)) << ((cc - 1) * 6);
            while ( --cc > 0 ) {
                if ( pmb == pmbe )                  // reached end of the buffer
                    return cwChars;
                mb = *pmb++;
                if ( ((mb >> 6) & 0x03) != 2 )      // not part of multibyte character
                    return cwChars;
                wc |= (mb & 0x3F) << ((cc - 1) * 6);
            }
        }

        if ( wc & 0xFFFF0000 )
            wc = L'?';
        *pwc++ = wc;
        cwChars++;
        if ( wc == L'\0' )
            return cwChars;
    }

    return cwChars;
}

int mp4gettag(mp4ff_t *file, MAP_PLUGIN_FILETAG* tag)
{
	char* val;
	char year[5] = {0};

	memset(tag, 0, sizeof(MAP_PLUGIN_FILETAG));
	mp4ff_meta_get_title(file, &val);
	if (val) {
		utf8ToUnicode(val, tag->szTrack, MAX_PLUGIN_TAG_STR);
	}

	mp4ff_meta_get_artist(file, &val);
	if (val) {
		utf8ToUnicode(val, tag->szArtist, MAX_PLUGIN_TAG_STR);
	}

	mp4ff_meta_get_album(file, &val);
	if (val) {
		utf8ToUnicode(val, tag->szAlbum, MAX_PLUGIN_TAG_STR);
	}

	mp4ff_meta_get_comment(file, &val);
	if (val) {
		utf8ToUnicode(val, tag->szComment, MAX_PLUGIN_TAG_STR);
	}

	mp4ff_meta_get_genre(file, &val);
	if (val) {
		utf8ToUnicode(val, tag->szGenre, MAX_PLUGIN_TAG_STR);
	}

	mp4ff_meta_get_track(file, &val);
	if (val) {
		tag->nTrackNum = strtol(val, 0, 10);
	}

	mp4ff_meta_get_date(file, &val);
	if (val) {
		strncpy(year, val, 4);
		tag->nYear = strtol(year, 0, 10);
	}
	
	return 1;
}

int aacgettag(MAP_PLUGIN_FILETAG* tag)
{
	if (!mp4state.aacfile)
		return 0;

	if (GetId3TagV2(mp4state.aacfile, tag))
		return 1;
	
	return GetId3TagV1(mp4state.aacfile, tag);
}

int gettag(MAP_PLUGIN_FILETAG* tag)
{
	if (!mp4state.mp4File && !mp4state.aacfile)
		return 0;

	if (mp4state.filetype)
		return aacgettag(tag);
	else
		return mp4gettag(mp4state.mp4file, tag);
}

int mp4getfiletag(LPCTSTR pszFile, MAP_PLUGIN_FILETAG* tag)
{
	int ret;
	mp4ff_callback_t mp4cb;
	mp4ff_t* mp4file;

	FILE *fp = _tfopen(pszFile, _T("rb"));
    if (!fp)
        return 0;

	mp4cb.read = read_callback;
    mp4cb.seek = seek_callback;
    mp4cb.user_data = fp;
	mp4file = mp4ff_open_read_metaonly(&mp4cb);
	if (!mp4file) {
		fclose(fp);
		return 0;
	}

	ret = mp4gettag(mp4file, tag);
	mp4ff_close(mp4file);
	fclose(fp);

	return ret;
}

int aacgetfiletag(LPCTSTR pszFile, MAP_PLUGIN_FILETAG* tag)
{
	int ret;
	FILE *fp = _tfopen(pszFile, _T("rb"));
	if (!fp)
		return 0;

	ret = GetId3TagV2(fp, tag) ? 1 : 0;
	if (!ret)
		ret = GetId3TagV1(fp, tag) ? 1 : 0;

	fclose(fp);

	return ret;
}

int getfiletag(LPCTSTR pszFile, MAP_PLUGIN_FILETAG* tag)
{
	unsigned char header[8];
	FILE *fp = _tfopen(pszFile, _T("rb"));
    if (!fp)
        return 0;
    
    fread(header, 1, 8, fp);
    fclose(fp);
  
	if (header[4] == 'f' && header[5] == 't' && header[6] == 'y' && header[7] == 'p')
		return mp4getfiletag(pszFile, tag);
	else
		return aacgetfiletag(pszFile, tag);
}

BOOL aac_open_streaming(LPBYTE pbInBuf, DWORD cbInBuf, MAP_PLUGIN_STREMING_INFO* pInfo)
{
	DWORD i, bytesconsumed;
	NeAACDecFrameInfo frameInfo;
	NeAACDecConfigurationPtr config;

	mp4state.hDecoder = NeAACDecOpen();
    if (!mp4state.hDecoder) {
		close();
        return FALSE;
    }

    config = NeAACDecGetCurrentConfiguration(mp4state.hDecoder);
    config->outputFormat = FAAD_FMT_16BIT;
    config->downMatrix = 1;
    NeAACDecSetConfiguration(mp4state.hDecoder, config);

	// search an aac frame header
	for (i = 0; i < cbInBuf; i++) {
		if (is_aac_frame_header(pbInBuf + i, cbInBuf - i)) {
			if (NeAACDecInit(mp4state.hDecoder, pbInBuf + i, cbInBuf - i, (unsigned long*)&mp4state.samplerate, &mp4state.channels) >= 0) {

				bytesconsumed = 0;

				do {
					memset(&frameInfo, 0, sizeof(frameInfo));
					NeAACDecDecode(mp4state.hDecoder, &frameInfo, pbInBuf + i + bytesconsumed, cbInBuf - i - bytesconsumed);
					bytesconsumed += frameInfo.bytesconsumed;
					if (bytesconsumed + i >= cbInBuf)
						break;
				}
				while  (!frameInfo.samples && !frameInfo.error);

				if (frameInfo.samples && !frameInfo.error) {
					mp4state.channels = frameInfo.channels;
					mp4state.samplerate = frameInfo.samplerate;
					mp4state.framesize = (frameInfo.channels != 0) ? frameInfo.samples/frameInfo.channels : 0;
					mp4state.avg_bitrate = (double)mp4state.samplerate / mp4state.framesize * frameInfo.bytesconsumed * 8 / 1000;
					mp4state.initial = 1;
					mp4state.filetype = 1;

					if (/*m_downmix && */(mp4state.channels == 5 || mp4state.channels == 6))
						mp4state.channels = 2;

					pInfo->nAvgBitrate = mp4state.avg_bitrate;
					pInfo->nBitsPerSample = 16;
					pInfo->nChannels = mp4state.channels;
					pInfo->nSampleRate = mp4state.samplerate;

					NeAACDecPostSeekReset(mp4state.hDecoder, -1);
					return TRUE;
				}
			}
		}
	}

	close();
	return FALSE;
}

BOOL open_streaming(LPBYTE pbInBuf, DWORD cbInBuf, MAP_PLUGIN_STREMING_INFO* pInfo)
{
	if (cbInBuf < 8)
		return FALSE;
	
	// mp4 is currently not supported!
	if (pbInBuf[4] == 'f' && pbInBuf[5] == 't' && pbInBuf[6] == 'y' && pbInBuf[7] == 'p')
		return FALSE;
	
	return aac_open_streaming(pbInBuf, cbInBuf, pInfo);
}

int aac_decode_streaming(LPBYTE pbInBuf, DWORD cbInBuf, DWORD* pcbInUsed, WAVEHDR* pHdr)
{
	void *sample_buffer;
	char *buf;
	NeAACDecFrameInfo frameInfo;
	unsigned long samplerate;
	unsigned char channels;
	uint8_t *outbuf = (uint8_t *)pHdr->lpData;
	uint32_t outbuflen = pHdr->dwBufferLength;
	uint32_t *outlen = &pHdr->dwBytesRecorded;

	if (!mp4state.hDecoder)
		return PLUGIN_RET_ERROR;

	*pcbInUsed = 0;

	if (leftoutbuf && leftoutbuflen) {
		if (outbuflen < leftoutbuflen) {
			memcpy(outbuf, leftoutbuf, outbuflen);
			*outlen = outbuflen;

			memmove(leftoutbuf, leftoutbuf + outbuflen, leftoutbuflen - outbuflen);
			leftoutbuflen -= outbuflen;
			return PLUGIN_RET_SUCCESS;
		}
		else {
			memcpy(outbuf, leftoutbuf, leftoutbuflen);
			outbuf += leftoutbuflen;
			*outlen += leftoutbuflen;
			
			free(leftoutbuf);
			leftoutbuflen = 0;
		}
	}

	while (outbuflen - *outlen) {
		if (!is_aac_frame_header(pbInBuf + *pcbInUsed, cbInBuf - *pcbInUsed)) {
			NeAACDecPostSeekReset(mp4state.hDecoder, -1);

			while (*pcbInUsed < outbuflen) {
				(*pcbInUsed)++;	

				if (is_aac_frame_header(pbInBuf + *pcbInUsed, cbInBuf - *pcbInUsed)){
					memset(&frameInfo, 0, sizeof(NeAACDecFrameInfo));
					NeAACDecDecode(mp4state.hDecoder, &frameInfo, mp4state.m_aac_buffer, mp4state.m_aac_bytes_into_buffer);
					if (frameInfo.error == 0) {
						break;
					}					
				}
			}
		}

		memset(&frameInfo, 0, sizeof(NeAACDecFrameInfo));
		sample_buffer = NeAACDecDecode(mp4state.hDecoder, &frameInfo, pbInBuf + *pcbInUsed, cbInBuf - *pcbInUsed);
		*pcbInUsed += frameInfo.bytesconsumed;

		if (frameInfo.error) {
			return PLUGIN_RET_ERROR;
		}

		if (frameInfo.samples > 0 && sample_buffer) {
			buf = (char *)sample_buffer;
			mp4state.initial = 0;
	        
			if (frameInfo.channels == 6 && frameInfo.num_lfe_channels)
				remap_channels((unsigned char*)buf, frameInfo.samples, 16);

			int l = frameInfo.samples * 16 / 8;

			if (outbuflen - *outbuf < l) {
				memcpy(outbuf + *outlen, buf, outbuflen - *outbuf);
				leftoutbuf = (uint8_t*)malloc(l - outbuflen - *outbuf);
				leftoutbuflen = l - outbuflen - *outbuf;
				memcpy(leftoutbuf, buf + outbuflen - *outbuf, leftoutbuflen);

				*outlen = outbuflen;
			}
			else {
				memcpy(outbuf + *outlen, buf, l);
				*outlen += l;
			}
		}

		mp4state.decode_pos_ms += (double)frameInfo.samples * 1000.0 /
			((double)frameInfo.samplerate* (double)frameInfo.channels);

		if (frameInfo.channels > 0 && mp4state.samplerate > 0)
			mp4state.cur_pos_sec += ((double)(frameInfo.samples/frameInfo.channels))/(double)mp4state.samplerate;
	}

	return PLUGIN_RET_SUCCESS;
}

int decode_streaming(LPBYTE pbInBuf, DWORD cbInBuf, DWORD* pcbInUsed, WAVEHDR* pHdr)
{
	// mp4 is currently not supported!
	return aac_decode_streaming(pbInBuf, cbInBuf, pcbInUsed, pHdr);
}

void close_streaming()
{
	close();
}

⌨️ 快捷键说明

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