Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
parser: add frame parser for all mpeg audio layers (123)
  • Loading branch information
perexg committed Oct 20, 2015
1 parent a8a29d2 commit 2e3dfb6
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 37 deletions.
2 changes: 1 addition & 1 deletion src/muxer/muxer_mkv.c
Expand Up @@ -287,7 +287,7 @@ mk_build_tracks(mk_muxer_t *mk, streaming_start_t *ss)

case SCT_MPEG2AUDIO:
tracktype = 2;
codec_id = "A_MPEG/L2";
codec_id = "A_MPEG/L3";
break;

case SCT_AC3:
Expand Down
103 changes: 67 additions & 36 deletions src/parsers/parsers.c
Expand Up @@ -99,7 +99,7 @@ static void parse_teletext(service_t *t, elementary_stream_t *st,
static int parse_mpa(service_t *t, elementary_stream_t *st, size_t len,
uint32_t next_startcode, int sc_offset);

static int parse_mpa2(service_t *t, elementary_stream_t *st);
static int parse_mpa123(service_t *t, elementary_stream_t *st);

static int parse_ac3(service_t *t, elementary_stream_t *st, size_t len,
uint32_t next_startcode, int sc_offset);
Expand Down Expand Up @@ -444,6 +444,8 @@ depacketize(service_t *t, elementary_stream_t *st, size_t len,

st->es_buf_a.sb_err = st->es_buf.sb_err;

tvhtrace("parser", "depacketize add %zd", len);
tvhlog_hexdump("parser", buf, len);
sbuf_append(&st->es_buf_a, buf, len);
return PARSER_APPEND;
}
Expand Down Expand Up @@ -543,64 +545,93 @@ static void parse_mp4a_data(service_t *t, elementary_stream_t *st,
}
}

const static int mpa_br[16] = {
0, 32, 48, 56,
64, 80, 96, 112,
128, 160, 192, 224,
256, 320, 384, 0
const static int mpa_br[2][3][16] = {
{
{0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 0},
{0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 0},
{0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0},
},
{
{0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, 0},
{0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0},
{0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0},
}
};

const static int mpa_sr[4] = {44100, 48000, 32000, 0};
const static int mpa_sri[4] = {4, 3, 5, 0};

static int
mpa_valid_frame(const uint8_t *buf)
static inline int
mpa_valid_frame(uint32_t h)
{
return buf[0] == 0xff && (buf[1] & 0xfe) == 0xfc;
if ((h & 0xffe00000) != 0xffe00000) return 0; /* start bits */
if ((h & (3<<17)) == 0) return 0; /* unknown MPEG audio layer */
if ((h & (15<<12)) == (15<<12)) return 0; /* invalid bitrate */
if ((h & (3<<10)) == (3<<10)) return 0; /* invalid frequency */
return 1;
}


/**
*
*/
static int
parse_mpa2(service_t *t, elementary_stream_t *st)
parse_mpa123(service_t *t, elementary_stream_t *st)
{
int i, len;
int i, len, layer, lsf, mpeg25, br, sr, pad, fsize, channels, duration;
int64_t dts;
uint32_t h;
const uint8_t *buf;

again:
buf = st->es_buf_a.sb_data;
len = st->es_buf_a.sb_ptr;

for(i = 0; i < len - 4; i++) {
if(mpa_valid_frame(buf + i)) {
int br = mpa_br[ buf[i+2] >> 4 ];
int sr = mpa_sr[(buf[i+2] >> 2) & 3];
int pad = (buf[i+2] >> 1) & 1;
for (i = 0; i < len - 4; i++) {
if (!mpa_valid_frame(h = RB32(buf + i))) continue;

if(br && sr) {
int fsize = 144000 * br / sr + pad;
int duration = 90000 * 1152 / sr;
int64_t dts = st->es_curdts;
int channels = (buf[i + 3] & 0xc0) == 0xc0 ? 1 : 2;
if(dts == PTS_UNSET)
dts = st->es_nextdts;
layer = 4 - ((h >> 17) & 3);
lsf = mpeg25 = 1;
pad = (h >> 9) & 1;
if (h & (1<<20)) {
lsf = ((h >> 19) & 1) ^ 1;
mpeg25 = 0;
}
sr = mpa_sr[(h >> 10) & 3] >> (lsf + mpeg25);
br = (h >> 12) & 0xf;

if(dts != PTS_UNSET &&
len >= i + fsize + 4 &&
mpa_valid_frame(buf + i + fsize)) {
if (br == 0 || sr == 0) continue;

makeapkt(t, st, buf + i, fsize, dts, duration,
channels, mpa_sri[(buf[i+2] >> 2) & 3],
st->es_buf_a.sb_err);
st->es_buf_a.sb_err = 0;
sbuf_cut(&st->es_buf_a, i + fsize);
goto again;
}
}
br = mpa_br[lsf][layer - 1][br];
if (br == 0) continue;

switch (layer) {
case 1: fsize = (((br * 12000) / sr) + pad) * 4; break;
case 2: fsize = ((br * 144000) / sr) + pad; break;
case 3: fsize = ((br * 144000) / (sr << lsf)) + pad; break;
default: fsize = 0;
}

duration = 90000 * 1152 / sr;
channels = ((h >> 6) & 3) == 3 ? 1 : 2;
dts = st->es_curdts;
if (dts == PTS_UNSET) {
dts = st->es_nextdts;
if(dts == PTS_UNSET) continue;
}

if(len < i + fsize + 4) continue;

h = RB32(buf + i + fsize);
if(mpa_valid_frame(h)) {
makeapkt(t, st, buf + i, fsize, dts, duration,
channels, mpa_sri[(buf[i+2] >> 2) & 3],
st->es_buf_a.sb_err);
st->es_buf_a.sb_err = 0;
sbuf_cut(&st->es_buf_a, i + fsize);
goto again;
}
}

return PARSER_RESET;
}

Expand All @@ -615,7 +646,7 @@ parse_mpa(service_t *t, elementary_stream_t *st, size_t ilen,

if((r = depacketize(t, st, ilen, next_startcode, sc_offset)) != PARSER_APPEND)
return r;
return parse_mpa2(t, st);
return parse_mpa123(t, st);
}


Expand Down

0 comments on commit 2e3dfb6

Please sign in to comment.