📄 in_mp4.cpp
字号:
}
}
break;
case 24:
case 32:
{
unsigned int r1, r2, r3, r4, r5, r6;
unsigned int *sample_buffer = (unsigned int *)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;
}
}
break;
}
}
int mp4open(TCHAR *fn)
{
unsigned char *buffer;
int buffer_size;
NeAACDecConfigurationPtr config;
unsigned char header[8];
FILE *hMP4File;
memset(&mp4state, 0, sizeof(state));
lstrcpy(mp4state.filename, fn);
hMP4File = _tfopen(mp4state.filename, _T("rb"));
if (!hMP4File)
{
return -1;
}
fread(header, 1, 8, hMP4File);
fclose(hMP4File);
if (header[4] != 'f' || header[5] != 't' || header[6] != 'y' || header[7] != 'p')
return -1;
mp4state.hDecoder = NeAACDecOpen();
if (!mp4state.hDecoder)
{
return -1;
}
config = NeAACDecGetCurrentConfiguration(mp4state.hDecoder);
config->outputFormat = FAAD_FMT_16BIT;
config->downMatrix = 1;
NeAACDecSetConfiguration(mp4state.hDecoder, config);
mp4state.mp4File = _tfopen(mp4state.filename, _T("rb"));
mp4state.mp4cb.read = read_callback;
mp4state.mp4cb.seek = seek_callback;
mp4state.mp4cb.user_data = mp4state.mp4File;
mp4state.mp4file = mp4ff_open_read(&mp4state.mp4cb);
if (!mp4state.mp4file)
{
close();
return -1;
}
if ((mp4state.mp4track = GetAACTrack(mp4state.mp4file)) < 0)
{
close();
return -1;
}
buffer = NULL;
buffer_size = 0;
mp4ff_get_decoder_config(mp4state.mp4file, mp4state.mp4track,
&buffer, (unsigned int*)&buffer_size);
if (!buffer)
{
close();
return -1;
}
if(NeAACDecInit2(mp4state.hDecoder, buffer, buffer_size,
(unsigned long*)&mp4state.samplerate, &mp4state.channels) < 0)
{
/* If some error initializing occured, skip the file */
if (buffer) free (buffer);
close();
return -1;
}
/* for gapless decoding */
{
mp4AudioSpecificConfig mp4ASC;
mp4state.timescale = mp4ff_time_scale(mp4state.mp4file, mp4state.mp4track);
mp4state.framesize = 1024;
mp4state.useAacLength = 0;
if (buffer)
{
if (NeAACDecAudioSpecificConfig(buffer, buffer_size, &mp4ASC) >= 0)
{
if (mp4ASC.frameLengthFlag == 1) mp4state.framesize = 960;
if (mp4ASC.sbr_present_flag == 1) mp4state.framesize *= 2;
}
}
}
free(buffer);
mp4state.avg_bitrate = mp4ff_get_avg_bitrate(mp4state.mp4file, mp4state.mp4track);
mp4state.numSamples = mp4ff_num_samples(mp4state.mp4file, mp4state.mp4track);
mp4state.sampleId = 0;
{
double timescale_div = 1.0 / (double)mp4ff_time_scale(mp4state.mp4file, mp4state.mp4track);
int64_t duration = mp4ff_get_track_duration_use_offsets(mp4state.mp4file, mp4state.mp4track);
if (duration == -1)
{
mp4state.m_length = 0;
} else {
mp4state.m_length = (int)((double)duration * timescale_div * 1000.0);
}
}
mp4state.is_seekable = 1;
if (mp4state.channels == 0)
{
close();
return -1;
}
if (/*m_downmix && */(mp4state.channels == 5 || mp4state.channels == 6))
mp4state.channels = 2;
mp4state.paused = 0;
mp4state.decode_pos_ms = 0;
mp4state.seek_needed = -1;
mp4state.filetype = 0;
NeAACDecPostSeekReset(mp4state.hDecoder, -1);
return 0;
}
int aacopen(TCHAR *fn)
{
unsigned char *buffer;
int buffer_size;
NeAACDecConfigurationPtr config;
unsigned char header[8];
FILE *hMP4File;
int tmp = 0, init;
int bread = 0;
double length = 0.;
__int64 bitrate = 128;
memset(&mp4state, 0, sizeof(state));
lstrcpy(mp4state.filename, fn);
mp4state.is_seekable = 1;
if (!(mp4state.aacfile = _tfopen(mp4state.filename, _T("rb"))))
{
close();
return -1;
}
mp4state.m_tagsize = skip_id3v2_tag();
if (mp4state.m_tagsize<0)
{
close();
return 0;
}
if (!(mp4state.m_aac_buffer = (unsigned char*)malloc(768*6)))
{
close();
return -1;
}
for (init=0; init<2; init++)
{
mp4state.hDecoder = NeAACDecOpen();
if (!mp4state.hDecoder)
{
close();
return -1;
}
config = NeAACDecGetCurrentConfiguration(mp4state.hDecoder);
config->outputFormat = FAAD_FMT_16BIT;
config->downMatrix = 1;
NeAACDecSetConfiguration(mp4state.hDecoder, config);
memset(mp4state.m_aac_buffer, 0, 768*6);
bread = fread(mp4state.m_aac_buffer, 1, 768*6, mp4state.aacfile);
mp4state.m_aac_bytes_into_buffer = bread;
mp4state.m_aac_bytes_consumed = 0;
mp4state.m_file_offset = 0;
mp4state.m_at_eof = (bread != 768*6) ? 1 : 0;
if (init==0)
{
NeAACDecFrameInfo frameInfo;
fill_buffer(&mp4state);
if ((mp4state.m_aac_bytes_consumed = NeAACDecInit(mp4state.hDecoder,
mp4state.m_aac_buffer, mp4state.m_aac_bytes_into_buffer,
(unsigned long*)&mp4state.samplerate, &mp4state.channels)) < 0)
{
close();
return -1;
}
advance_buffer(&mp4state, mp4state.m_aac_bytes_consumed);
do {
memset(&frameInfo, 0, sizeof(NeAACDecFrameInfo));
fill_buffer(&mp4state);
NeAACDecDecode(mp4state.hDecoder, &frameInfo, mp4state.m_aac_buffer, mp4state.m_aac_bytes_into_buffer);
} while (!frameInfo.samples && !frameInfo.error);
if (frameInfo.error)
{
close();
return -1;
}
mp4state.channels = frameInfo.channels;
mp4state.samplerate = frameInfo.samplerate;
mp4state.framesize = (frameInfo.channels != 0) ? frameInfo.samples/frameInfo.channels : 0;
/*
sbr = frameInfo.sbr;
profile = frameInfo.object_type;
header_type = frameInfo.header_type;
*/
NeAACDecClose(mp4state.hDecoder);
fseek(mp4state.aacfile, mp4state.m_tagsize, SEEK_SET);
}
}
mp4state.m_head = (struct seek_list*)malloc(sizeof(struct seek_list));
mp4state.m_tail = mp4state.m_head;
mp4state.m_tail->next = NULL;
mp4state.m_header_type = 0;
if ((mp4state.m_aac_buffer[0] == 0xFF) && ((mp4state.m_aac_buffer[1] & 0xF6) == 0xF0))
{
if (1) //(can_seek)
{
adts_parse(&mp4state, &bitrate, &length);
fseek(mp4state.aacfile, mp4state.m_tagsize, SEEK_SET);
bread = fread(mp4state.m_aac_buffer, 1, 768*6, mp4state.aacfile);
if (bread != 768*6)
mp4state.m_at_eof = 1;
else
mp4state.m_at_eof = 0;
mp4state.m_aac_bytes_into_buffer = bread;
mp4state.m_aac_bytes_consumed = 0;
mp4state.m_header_type = 1;
}
} else if (memcmp(mp4state.m_aac_buffer, "ADIF", 4) == 0) {
int skip_size = (mp4state.m_aac_buffer[4] & 0x80) ? 9 : 0;
bitrate = ((unsigned int)(mp4state.m_aac_buffer[4 + skip_size] & 0x0F)<<19) |
((unsigned int)mp4state.m_aac_buffer[5 + skip_size]<<11) |
((unsigned int)mp4state.m_aac_buffer[6 + skip_size]<<3) |
((unsigned int)mp4state.m_aac_buffer[7 + skip_size] & 0xE0);
length = (double)file_length(mp4state.aacfile);
if (length == -1)
{
mp4state.is_seekable = 0;
length = 0;
} else {
length = ((double)length*8.)/((double)bitrate) + 0.5;
}
mp4state.m_header_type = 2;
} else {
length = (double)file_length(mp4state.aacfile);
length = ((double)length*8.)/((double)bitrate*1000.) + 0.5;
mp4state.is_seekable = 1;
}
mp4state.m_length = (int)(length*1000.);
fill_buffer(&mp4state);
if ((mp4state.m_aac_bytes_consumed = NeAACDecInit(mp4state.hDecoder,
mp4state.m_aac_buffer, mp4state.m_aac_bytes_into_buffer,
(unsigned long*)&mp4state.samplerate, &mp4state.channels)) < 0)
{
close();
return -1;
}
advance_buffer(&mp4state, mp4state.m_aac_bytes_consumed);
if (mp4state.m_header_type == 2)
mp4state.avg_bitrate = bitrate;
else
mp4state.avg_bitrate = bitrate*1000;
if (/*m_downmix && */(mp4state.channels == 5 || mp4state.channels == 6))
mp4state.channels = 2;
mp4state.filetype = 1;
NeAACDecPostSeekReset(mp4state.hDecoder, -1);
return 0;
}
int open(TCHAR *fn)
{
if (!mp4open(fn))
return 0;
if (!aacopen(fn))
return 0;
return -1;
}
void close()
{
struct seek_list *target = mp4state.m_head;
if (mp4state.m_aac_buffer)
free(mp4state.m_aac_buffer);
while (target)
{
struct seek_list *tmp = target;
target = target->next;
if (tmp) free(tmp);
}
if (mp4state.hDecoder) {
NeAACDecClose(mp4state.hDecoder);
}
if (mp4state.aacfile) {
fclose(mp4state.aacfile);
}
if (mp4state.mp4file) {
mp4ff_close(mp4state.mp4file);
}
if (mp4state.mp4File) {
fclose(mp4state.mp4File);
}
flushleftbuf();
memset(&mp4state, 0, sizeof(state));
}
int mp4setoutputtime(int time_in_ms)
{
int64_t duration;
int32_t skip_samples = 0;
if (!mp4state.mp4File)
return -1;
if (!mp4state.is_seekable)
return -1;
duration = (int64_t)(time_in_ms/1000.0 * mp4state.samplerate + 0.5);
mp4state.sampleId = mp4ff_find_sample_use_offsets(mp4state.mp4file, mp4state.mp4track, duration, &skip_samples);
mp4state.decode_pos_ms = time_in_ms;
flushleftbuf();
return time_in_ms;
}
int aacsetoutputtime(int time_in_ms)
{
double ms;
if (!mp4state.aacfile)
return -1;
ms = (double)time_in_ms/1000;
if (aac_seek(&mp4state, ms)!=0)
{
mp4state.cur_pos_sec = ms;
mp4state.decode_pos_ms = time_in_ms;
flushleftbuf();
return time_in_ms;
}
return -1;
}
int setoutputtime(int time_in_ms)
{
if (mp4state.filetype)
return aacsetoutputtime(time_in_ms);
else
return mp4setoutputtime(time_in_ms);
}
int start()
{
if (!mp4state.mp4File && !mp4state.aacfile)
return 0;
mp4state.last_frame = 0;
mp4state.initial = 1;
return 1;
}
void stop()
{
flushleftbuf();
}
int mp4decode(uint8_t *outbuf, uint32_t outbuflen, uint32_t *outlen)
{
unsigned char *buffer = NULL;
int buffer_size = 0;
NeAACDecFrameInfo frameInfo = {0};
void *sample_buffer;
unsigned int sample_count;
unsigned int delay = 0;
char *buf;
*outlen = 0;
if (!mp4state.mp4File)
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) {
buffer = NULL;
buffer_size = 0;
long dur = mp4ff_get_sample_duration(mp4state.mp4file, mp4state.mp4track, mp4state.sampleId);
if (dur == -1)
break;
int rc = mp4ff_read_sample(mp4state.mp4file, mp4state.mp4track, mp4state.sampleId++, &buffer, (unsigned int*)&buffer_size);
if (rc == 0 || buffer == NULL) {
mp4state.last_frame = 1;
sample_buffer = NULL;
frameInfo.samples = 0;
}
else {
sample_buffer = NeAACDecDecode(mp4state.hDecoder, &frameInfo, buffer, buffer_size);
}
if (mp4state.sampleId >= mp4state.numSamples)
mp4state.last_frame = 1;
if (buffer) {
free(buffer);
}
if (frameInfo.error > 0) {
return PLUGIN_RET_ERROR;
}
if (frameInfo.samplerate != mp4state.samplerate) {
return PLUGIN_RET_ERROR;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -