Codecs: aac: Improve ADTS stream detection

Captured ADTS streams might start from some garbage data from previous frame. We should check for sync errors even for first frame.

Change-Id: I70171298b79713aeedf9fa2e6098a03063487649
This commit is contained in:
Roman Artiukhin 2024-01-03 17:30:18 +02:00 committed by Solomon Peachy
parent fd12225861
commit d50470bc7d
2 changed files with 34 additions and 22 deletions

View file

@ -247,6 +247,7 @@ int32_t NEAACDECAPI NeAACDecInit(NeAACDecHandle hDecoder, uint8_t *buffer,
if ((hDecoder == NULL) || (samplerate == NULL) || (channels == NULL)) if ((hDecoder == NULL) || (samplerate == NULL) || (channels == NULL))
return -1; return -1;
adts.old_format = hDecoder->config.useOldADTSFormat;
hDecoder->sf_index = get_sr_index(hDecoder->config.defSampleRate); hDecoder->sf_index = get_sr_index(hDecoder->config.defSampleRate);
hDecoder->object_type = hDecoder->config.defObjectType; hDecoder->object_type = hDecoder->config.defObjectType;
*samplerate = get_sample_rate(hDecoder->sf_index); *samplerate = get_sample_rate(hDecoder->sf_index);
@ -277,12 +278,9 @@ int32_t NEAACDECAPI NeAACDecInit(NeAACDecHandle hDecoder, uint8_t *buffer,
bits = bit2byte(faad_get_processed_bits(&ld)); bits = bit2byte(faad_get_processed_bits(&ld));
/* Check if an ADTS header is present */ /* Check if an ADTS header is present */
} else if (faad_showbits(&ld, 12) == 0xfff) { } else if (adts_frame(&adts, &ld) == 0) {
hDecoder->adts_header_present = 1; hDecoder->adts_header_present = 1;
adts.old_format = hDecoder->config.useOldADTSFormat;
adts_frame(&adts, &ld);
hDecoder->sf_index = adts.sf_index; hDecoder->sf_index = adts.sf_index;
hDecoder->object_type = adts.profile + 1; hDecoder->object_type = adts.profile + 1;

View file

@ -47,6 +47,24 @@ static bool check_adts_syncword(int fd)
return (syncword & 0xFFF6) == 0xFFF0; return (syncword & 0xFFF6) == 0xFFF0;
} }
static bool find_adts_keyword(int fd, struct mp3entry *entry)
{
/* logic is copied from adts_fixed_header libfaad/syntax.c:
* try to recover from sync errors */
for (int i = 0; i < 768; ++i)
{
if (-1 == lseek(fd, entry->first_frame_offset + i, SEEK_SET))
return false;
if (check_adts_syncword(fd))
{
return true;
}
}
return false;
}
bool get_aac_metadata(int fd, struct mp3entry *entry) bool get_aac_metadata(int fd, struct mp3entry *entry)
{ {
unsigned char buf[5]; unsigned char buf[5];
@ -65,8 +83,21 @@ bool get_aac_metadata(int fd, struct mp3entry *entry)
if (-1 == lseek(fd, entry->first_frame_offset, SEEK_SET)) if (-1 == lseek(fd, entry->first_frame_offset, SEEK_SET))
return false; return false;
if (read(fd, buf, 5) != 5)
return false;
if (!memcmp(buf, "ADIF", 4))
{
if (-1 == lseek(fd, (buf[4] & 0x80) ? (entry->first_frame_offset + 9) : entry->first_frame_offset, SEEK_SET))
return false;
if (check_adts_syncword(fd)) uint32_t bitrate;
read_uint32be(fd, &bitrate);
entry->vbr = (bitrate & 0x10000000) != 0;
entry->bitrate = ((bitrate & 0xFFFFFE0) + 16000) / 32000;
read_uint32be(fd, (uint32_t*)(&(entry->frequency)));
entry->frequency = sample_rates[(entry->frequency >> (entry->vbr ? 23 : 3)) & 0x0F];
}
else if (find_adts_keyword(fd, entry))
{ {
int frames; int frames;
int stat_length; int stat_length;
@ -101,23 +132,6 @@ bool get_aac_metadata(int fd, struct mp3entry *entry)
} }
#endif #endif
} }
else
{
uint32_t bitrate;
if (-1 == lseek(fd, entry->first_frame_offset, SEEK_SET))
return false;
if (read(fd, buf, 5) != 5)
return false;
if (memcmp(buf, "ADIF", 4))
return false;
if (-1 == lseek(fd, (buf[4] & 0x80) ? (entry->first_frame_offset + 9) : entry->first_frame_offset, SEEK_SET))
return false;
read_uint32be(fd, &bitrate);
entry->vbr = (bitrate & 0x10000000) != 0;
entry->bitrate = ((bitrate & 0xFFFFFE0) + 16000) / 32000;
read_uint32be(fd, (uint32_t*)(&(entry->frequency)));
entry->frequency = sample_rates[(entry->frequency >> (entry->vbr ? 23 : 3)) & 0x0F];
}
entry->length = (unsigned long)((entry->filesize * 8LL + (entry->bitrate >> 1)) / entry->bitrate); entry->length = (unsigned long)((entry->filesize * 8LL + (entry->bitrate >> 1)) / entry->bitrate);
return true; return true;