sndfile: Identify 'naked' MPEG streams last, even after rforks (issue 830)

This commit is contained in:
Arthur Taylor 2022-12-12 14:10:08 -08:00
parent e79da07a0a
commit a19fe100cb

View File

@ -2771,6 +2771,17 @@ format_from_extension (SF_PRIVATE *psf)
return format ; return format ;
} /* format_from_extension */ } /* format_from_extension */
static int
identify_mpeg (uint32_t marker)
{ if ((marker & MAKE_MARKER (0xFF, 0xE0, 0, 0)) == MAKE_MARKER (0xFF, 0xE0, 0, 0) && /* Frame sync */
(marker & MAKE_MARKER (0, 0x18, 0, 0)) != MAKE_MARKER (0, 0x08, 0, 0) && /* Valid MPEG version */
(marker & MAKE_MARKER (0, 0x06, 0, 0)) != MAKE_MARKER (0, 0, 0, 0) && /* Valid layer description */
(marker & MAKE_MARKER (0, 0, 0xF0, 0)) != MAKE_MARKER (0, 0, 0xF0, 0) && /* Valid bitrate */
(marker & MAKE_MARKER (0, 0, 0x0C, 0)) != MAKE_MARKER (0, 0, 0x0C, 0)) /* Valid samplerate */
return SF_FORMAT_MPEG ;
return 0 ;
} /* identify_mpeg */
static int static int
guess_file_type (SF_PRIVATE *psf) guess_file_type (SF_PRIVATE *psf)
{ uint32_t buffer [3], format ; { uint32_t buffer [3], format ;
@ -2872,13 +2883,6 @@ retry:
if (buffer [0] == MAKE_MARKER ('R', 'F', '6', '4') && buffer [2] == MAKE_MARKER ('W', 'A', 'V', 'E')) if (buffer [0] == MAKE_MARKER ('R', 'F', '6', '4') && buffer [2] == MAKE_MARKER ('W', 'A', 'V', 'E'))
return SF_FORMAT_RF64 ; return SF_FORMAT_RF64 ;
if ((buffer [0] & MAKE_MARKER (0xFF, 0xE0, 0, 0)) == MAKE_MARKER (0xFF, 0xE0, 0, 0) && /* Frame sync */
(buffer [0] & MAKE_MARKER (0, 0x18, 0, 0)) != MAKE_MARKER (0, 0x08, 0, 0) && /* Valid MPEG version */
(buffer [0] & MAKE_MARKER (0, 0x06, 0, 0)) != MAKE_MARKER (0, 0, 0, 0) && /* Valid layer description */
(buffer [0] & MAKE_MARKER (0, 0, 0xF0, 0)) != MAKE_MARKER (0, 0, 0xF0, 0) && /* Valid bitrate */
(buffer [0] & MAKE_MARKER (0, 0, 0x0C, 0)) != MAKE_MARKER (0, 0, 0x0C, 0)) /* Valid samplerate */
return SF_FORMAT_MPEG ;
if (buffer [0] == MAKE_MARKER ('I', 'D', '3', 2) || buffer [0] == MAKE_MARKER ('I', 'D', '3', 3) if (buffer [0] == MAKE_MARKER ('I', 'D', '3', 2) || buffer [0] == MAKE_MARKER ('I', 'D', '3', 3)
|| buffer [0] == MAKE_MARKER ('I', 'D', '3', 4)) || buffer [0] == MAKE_MARKER ('I', 'D', '3', 4))
{ psf_log_printf (psf, "Found 'ID3' marker.\n") ; { psf_log_printf (psf, "Found 'ID3' marker.\n") ;
@ -2887,6 +2891,10 @@ retry:
return 0 ; return 0 ;
} ; } ;
/* ID3v2 tags + MPEG */
if (psf->id3_header.len > 0 && (format = identify_mpeg (buffer [0])) != 0)
return format ;
/* Turtle Beach SMP 16-bit */ /* Turtle Beach SMP 16-bit */
if (buffer [0] == MAKE_MARKER ('S', 'O', 'U', 'N') && buffer [1] == MAKE_MARKER ('D', ' ', 'S', 'A')) if (buffer [0] == MAKE_MARKER ('S', 'O', 'U', 'N') && buffer [1] == MAKE_MARKER ('D', ' ', 'S', 'A'))
return 0 ; return 0 ;
@ -2898,10 +2906,16 @@ retry:
if (buffer [0] == MAKE_MARKER ('a', 'j', 'k', 'g')) if (buffer [0] == MAKE_MARKER ('a', 'j', 'k', 'g'))
return 0 /*-SF_FORMAT_SHN-*/ ; return 0 /*-SF_FORMAT_SHN-*/ ;
/* This must be the last one. */ /* This must be (almost) the last one. */
if (psf->filelength > 0 && (format = try_resource_fork (psf)) != 0) if (psf->filelength > 0 && (format = try_resource_fork (psf)) != 0)
return format ; return format ;
/* MPEG with no ID3v2 tags. Only have the MPEG sync header for
* identification and it is quite brief, and prone to false positives.
* Check for this last, even after resource forks. */
if (psf->id3_header.len == 0 && (format = identify_mpeg (buffer [0])) != 0)
return format ;
return 0 ; return 0 ;
} /* guess_file_type */ } /* guess_file_type */