📄 in_mp4.cpp
字号:
}
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 + -