ref: 56bf3d803998f47df96f42d16d6c70dced304568
parent: cbe4880728c45081b70ee1b731a8a89dbc065269
author: menno <menno>
date: Thu Sep 4 13:43:40 EDT 2003
in_mp4: Gapless playback in_mp4: Title formatting fixed
--- a/plugins/in_mp4/in_mp4.c
+++ b/plugins/in_mp4/in_mp4.c
@@ -22,7 +22,7 @@
** Commercial non-GPL licensing of this software is possible.
** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
**
-** $Id: in_mp4.c,v 1.39 2003/09/03 20:19:07 menno Exp $
+** $Id: in_mp4.c,v 1.40 2003/09/04 17:43:40 menno Exp $
**/
//#define DEBUG_OUTPUT
@@ -112,6 +112,12 @@
struct seek_list *m_head;
struct seek_list *m_tail;
unsigned long m_length;
+
+ /* for gapless decoding */
+ unsigned int useAacLength;
+ unsigned int framesize;
+ unsigned int initial;
+ unsigned long timescale;
} state;
static state mp4state;
@@ -572,8 +578,7 @@
dummy = 0; dummy2 = 0;
if (MP4GetMetadataTrack(file, &dummy, &dummy2))
{
- wsprintf(dummy1, "%d", dummy);
- lstrcpy(out, dummy1); out += lstrlen(dummy1);
+ out += wsprintf("%d", (int)dummy);
some_info = 1;
}
break;
@@ -582,7 +587,7 @@
pVal = NULL;
if (MP4GetMetadataArtist(file, &pVal))
{
- lstrcpy(out, pVal); out += lstrlen(pVal);
+ out += wsprintf("%s", pVal);
some_info = 1;
}
break;
@@ -591,7 +596,7 @@
pVal = NULL;
if (MP4GetMetadataName(file, &pVal))
{
- lstrcpy(out, pVal); out += lstrlen(pVal);
+ out += wsprintf("%s", pVal);
some_info = 1;
}
break;
@@ -600,7 +605,7 @@
pVal = NULL;
if (MP4GetMetadataAlbum(file, &pVal))
{
- lstrcpy(out, pVal); out += lstrlen(pVal);
+ out += wsprintf("%s", pVal);
some_info = 1;
}
break;
@@ -609,7 +614,7 @@
pVal = NULL;
if (MP4GetMetadataYear(file, &pVal))
{
- lstrcpy(out, pVal); out += lstrlen(pVal);
+ out += wsprintf("%s", pVal);
some_info = 1;
}
break;
@@ -618,7 +623,7 @@
pVal = NULL;
if (MP4GetMetadataComment(file, &pVal))
{
- lstrcpy(out, pVal); out += lstrlen(pVal);
+ out += wsprintf("%s", pVal);
some_info = 1;
}
break;
@@ -627,7 +632,7 @@
pVal = NULL;
if (MP4GetMetadataGenre(file, &pVal))
{
- lstrcpy(out, pVal); out += lstrlen(pVal);
+ out += wsprintf("%s", pVal);
some_info = 1;
}
break;
@@ -1037,6 +1042,25 @@
MP4Close(mp4state.mp4file);
return -1;
}
+
+ /* for gapless decoding */
+ {
+ mp4AudioSpecificConfig mp4ASC;
+
+ mp4state.timescale = MP4GetTrackTimeScale(mp4state.mp4file, mp4state.mp4track);
+ mp4state.framesize = 1024;
+ mp4state.useAacLength = 0;
+
+ if (buffer)
+ {
+ if (AudioSpecificConfig(buffer, buffer_size, &mp4ASC) >= 0)
+ {
+ if (mp4ASC.frameLengthFlag == 1) mp4state.framesize = 960;
+ if (mp4ASC.sbr_present_flag == 1) mp4state.framesize *= 2;
+ }
+ }
+ }
+
free(buffer);
avg_bitrate = MP4GetTrackIntegerProperty(mp4state.mp4file, mp4state.mp4track,
@@ -1438,6 +1462,7 @@
PlayThreadAlive = 1;
mp4state.last_frame = 0;
+ mp4state.initial = 1;
while (!*((int *)b))
{
@@ -1476,6 +1501,12 @@
} else {
int rc;
+ /* for gapless decoding */
+ char *buf;
+ MP4Duration dur;
+ unsigned int sample_count;
+ unsigned int delay = 0;
+
/* get acces unit from MP4 file */
buffer = NULL;
buffer_size = 0;
@@ -1482,7 +1513,7 @@
rc = MP4ReadSample(mp4state.mp4file, mp4state.mp4track,
mp4state.sampleId++, &buffer, &buffer_size,
- NULL, NULL, NULL, NULL);
+ NULL, &dur, NULL, NULL);
if (rc == 0 || buffer == NULL)
{
mp4state.last_frame = 1;
@@ -1497,37 +1528,74 @@
show_error(module.hMainWindow, faacDecGetErrorMessage(frameInfo.error));
mp4state.last_frame = 1;
}
- if (mp4state.sampleId >= mp4state.numSamples)
+ if (mp4state.sampleId > mp4state.numSamples)
mp4state.last_frame = 1;
if (buffer) free(buffer);
- if (!killPlayThread && (frameInfo.samples > 0))
+ 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) && (sample_count != frameInfo.samples))
+ {
+ //fprintf(stderr, "MP4 seems to have incorrect frame duration, using values from AAC data.\n");
+ mp4state.useAacLength = 1;
+ }
+ }
+
+ if (mp4state.initial && (sample_count < mp4state.framesize*frameInfo.channels))
{
+ delay = frameInfo.samples - sample_count;
+ }
+
+ if (!killPlayThread && (sample_count > 0))
+ {
+ buf = (char *)sample_buffer;
+ mp4state.initial = 0;
+
+ switch (res_table[m_resolution])
+ {
+ case 8:
+ buf += delay;
+ break;
+ case 16:
+ default:
+ buf += delay * 2;
+ break;
+ case 24:
+ case 32:
+ buf += delay * 4;
+ break;
+ case 64:
+ buf += delay * 8;
+ }
+
if (res_table[m_resolution] == 24)
{
/* convert libfaad output (3 bytes packed in 4) */
- char *temp_buffer = convert3in4to3in3(sample_buffer, frameInfo.samples);
- memcpy((void*)sample_buffer, (void*)temp_buffer, frameInfo.samples*3);
+ char *temp_buffer = convert3in4to3in3(buf, sample_count);
+ memcpy((void*)buf, (void*)temp_buffer, sample_count*3);
free(temp_buffer);
}
- module.SAAddPCMData(sample_buffer, (int)mp4state.channels, res_table[m_resolution],
+ module.SAAddPCMData(buf, (int)mp4state.channels, res_table[m_resolution],
mp4state.decode_pos_ms);
- module.VSAAddPCMData(sample_buffer, (int)mp4state.channels, res_table[m_resolution],
+ module.VSAAddPCMData(buf, (int)mp4state.channels, res_table[m_resolution],
mp4state.decode_pos_ms);
- mp4state.decode_pos_ms += (double)frameInfo.samples * 1000.0 /
+ mp4state.decode_pos_ms += (double)sample_count * 1000.0 /
((double)frameInfo.samplerate * (double)frameInfo.channels);
- l = frameInfo.samples * res_table[m_resolution] / 8;
+ l = sample_count * res_table[m_resolution] / 8;
if (module.dsp_isactive())
{
void *dsp_buffer = malloc(l*2);
- memcpy(dsp_buffer, sample_buffer, l);
+ memcpy(dsp_buffer, buf, l);
l = module.dsp_dosamples((short*)dsp_buffer,
- frameInfo.samples/frameInfo.channels,
+ sample_count/frameInfo.channels,
res_table[m_resolution],
frameInfo.channels,
frameInfo.samplerate) *
@@ -1536,7 +1604,7 @@
module.outMod->Write(dsp_buffer, l);
if (dsp_buffer) free(dsp_buffer);
} else {
- module.outMod->Write(sample_buffer, l);
+ module.outMod->Write(buf, l);
}
/* VBR bitrate display */
@@ -1544,7 +1612,7 @@
{
seq_frames++;
seq_bytes += frameInfo.bytesconsumed;
- if (seq_frames == (int)(floor((float)frameInfo.samplerate/(float)(frameInfo.samples/frameInfo.channels) + 0.5)))
+ if (seq_frames == (int)(floor((float)frameInfo.samplerate/(float)(sample_count/frameInfo.channels) + 0.5)))
{
module.SetInfo((int)floor(((float)seq_bytes*8.)/1000. + 0.5),
(int)floor(frameInfo.samplerate/1000. + 0.5),