Fix parsing of mpeg and ac3 audio
This commit is contained in:
parent
7bc327cbf3
commit
b4593ffba3
2 changed files with 91 additions and 134 deletions
224
parsers.c
224
parsers.c
|
@ -74,8 +74,7 @@ static int parse_h264(th_transport_t *t, th_stream_t *st, size_t len,
|
|||
typedef int (vparser_t)(th_transport_t *t, th_stream_t *st, size_t len,
|
||||
uint32_t next_startcode, int sc_offset);
|
||||
|
||||
typedef void (aparser_t)(th_transport_t *t, th_stream_t *st, uint8_t *data,
|
||||
int len);
|
||||
typedef void (aparser_t)(th_transport_t *t, th_stream_t *st, th_pkt_t *pkt);
|
||||
|
||||
static void parse_video(th_transport_t *t, th_stream_t *st, uint8_t *data,
|
||||
int len, vparser_t *vp);
|
||||
|
@ -83,11 +82,9 @@ static void parse_video(th_transport_t *t, th_stream_t *st, uint8_t *data,
|
|||
static void parse_audio(th_transport_t *t, th_stream_t *st, uint8_t *data,
|
||||
int len, int start, aparser_t *vp);
|
||||
|
||||
static void parse_mpegaudio(th_transport_t *t, th_stream_t *st, uint8_t *data,
|
||||
int len);
|
||||
static void parse_mpegaudio(th_transport_t *t, th_stream_t *st, th_pkt_t *pkt);
|
||||
|
||||
static void parse_ac3(th_transport_t *t, th_stream_t *st, uint8_t *data,
|
||||
int len);
|
||||
static void parse_ac3(th_transport_t *t, th_stream_t *st, th_pkt_t *pkt);
|
||||
|
||||
void parse_compute_pts(th_transport_t *t, th_stream_t *st, th_pkt_t *pkt);
|
||||
|
||||
|
@ -143,7 +140,6 @@ static void
|
|||
parse_video(th_transport_t *t, th_stream_t *st, uint8_t *data, int len,
|
||||
vparser_t *vp)
|
||||
{
|
||||
|
||||
uint32_t sc;
|
||||
int i, r;
|
||||
|
||||
|
@ -197,113 +193,111 @@ parse_video(th_transport_t *t, th_stream_t *st, uint8_t *data, int len,
|
|||
/**
|
||||
* Generic audio parser
|
||||
*
|
||||
* We trust 'start' to be set where a new frame starts
|
||||
* We trust 'start' to be set where a new frame starts, thats where we
|
||||
* can expect to find the system start code.
|
||||
*
|
||||
* We then trust ffmpeg to parse and extract packets for use
|
||||
*/
|
||||
static void
|
||||
parse_audio(th_transport_t *t, th_stream_t *st, uint8_t *data,
|
||||
int len, int start, aparser_t *ap)
|
||||
{
|
||||
int hlen, rlen;
|
||||
uint8_t *outbuf;
|
||||
int outlen;
|
||||
th_pkt_t *pkt;
|
||||
int64_t dts;
|
||||
|
||||
if(start) {
|
||||
if(st->st_buffer_ptr != 0)
|
||||
ap(t, st, st->st_buffer, st->st_buffer_ptr);
|
||||
|
||||
/* Payload unit start */
|
||||
st->st_parser_state = 1;
|
||||
st->st_buffer_ptr = 0;
|
||||
st->st_buffer_errors = 0;
|
||||
|
||||
if(st->st_buffer == NULL) {
|
||||
|
||||
if(st->st_buffer_size < 1000)
|
||||
st->st_buffer_size = 4000;
|
||||
|
||||
st->st_buffer = malloc(st->st_buffer_size);
|
||||
}
|
||||
}
|
||||
|
||||
if(st->st_buffer == NULL)
|
||||
if(st->st_parser_state == 0)
|
||||
return;
|
||||
|
||||
if(st->st_buffer_ptr + len >= st->st_buffer_size) {
|
||||
st->st_buffer_size += len * 4;
|
||||
st->st_buffer = realloc(st->st_buffer, st->st_buffer_size);
|
||||
if(st->st_parser_state == 1) {
|
||||
|
||||
if(st->st_buffer == NULL)
|
||||
st->st_buffer = malloc(1000);
|
||||
|
||||
if(st->st_buffer_ptr + len >= 1000)
|
||||
return;
|
||||
|
||||
memcpy(st->st_buffer + st->st_buffer_ptr, data, len);
|
||||
st->st_buffer_ptr += len;
|
||||
|
||||
if(st->st_buffer_ptr < 9)
|
||||
return;
|
||||
|
||||
if((hlen = parse_pes_header(t, st, st->st_buffer + 6,
|
||||
st->st_buffer_ptr - 6)) < 0)
|
||||
return;
|
||||
|
||||
data = st->st_buffer + hlen + 6;
|
||||
len = st->st_buffer_ptr - hlen - 6;
|
||||
|
||||
st->st_parser_state = 2;
|
||||
|
||||
assert(len >= 0);
|
||||
if(len == 0)
|
||||
return;
|
||||
}
|
||||
|
||||
while(len > 0) {
|
||||
|
||||
rlen = av_parser_parse(st->st_parser, st->st_ctx,
|
||||
&outbuf, &outlen, data, len,
|
||||
st->st_curpts, st->st_curdts);
|
||||
|
||||
st->st_curdts = AV_NOPTS_VALUE;
|
||||
st->st_curpts = AV_NOPTS_VALUE;
|
||||
|
||||
if(outlen) {
|
||||
dts = st->st_parser->dts;
|
||||
if(dts == AV_NOPTS_VALUE)
|
||||
dts = st->st_nextdts;
|
||||
|
||||
pkt = pkt_alloc(outbuf, outlen, dts, dts);
|
||||
pkt->pkt_commercial = t->tht_tt_commercial_advice;
|
||||
|
||||
ap(t, st, pkt);
|
||||
|
||||
}
|
||||
data += rlen;
|
||||
len -= rlen;
|
||||
}
|
||||
|
||||
memcpy(st->st_buffer + st->st_buffer_ptr, data, len);
|
||||
st->st_buffer_ptr += len;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Mpeg audio parser
|
||||
*/
|
||||
//const static int mpegaudio_freq_tab[4] = {44100, 48000, 32000, 0};
|
||||
const static int mpegaudio_freq_tab[4] = {44100, 48000, 32000, 0};
|
||||
|
||||
static void
|
||||
parse_mpegaudio(th_transport_t *t, th_stream_t *st, uint8_t *buf, int len)
|
||||
parse_mpegaudio(th_transport_t *t, th_stream_t *st, th_pkt_t *pkt)
|
||||
{
|
||||
int hlen, l, duration;
|
||||
th_pkt_t *pkt;
|
||||
|
||||
if(len < 9)
|
||||
return;
|
||||
if((hlen = parse_pes_header(t, st, buf + 6, len - 6)) < 0)
|
||||
return;
|
||||
|
||||
l = len - hlen - 6;
|
||||
if(l < 0)
|
||||
return;
|
||||
|
||||
buf += hlen + 6;
|
||||
len -= hlen + 6;
|
||||
#if 0
|
||||
header = 0;
|
||||
duration = 0;
|
||||
|
||||
printf("audioheader %02x.%02x.%02x.%02x\n",
|
||||
buf[0],
|
||||
buf[1],
|
||||
buf[2],
|
||||
buf[3]);
|
||||
|
||||
for(i = 0; i < len; i++) {
|
||||
header = header << 8 | buf[i];
|
||||
|
||||
if((header & 0xffe00000) != 0xffe00000)
|
||||
continue;
|
||||
|
||||
if((header & (3 << 17)) != 2 << 17)
|
||||
continue;
|
||||
|
||||
if((header & (15 << 12)) == 15 << 12)
|
||||
continue;
|
||||
|
||||
if((header & (3 << 10)) == 3 << 10)
|
||||
continue;
|
||||
|
||||
sample_rate = mpegaudio_freq_tab[(header >> 10) & 3];
|
||||
duration += 90000 * 1152 / sample_rate;
|
||||
printf("duration = %d\n", duration);
|
||||
}
|
||||
#endif
|
||||
|
||||
pkt = pkt_alloc(buf, len, st->st_curpts, st->st_curdts);
|
||||
pkt->pkt_commercial = t->tht_tt_commercial_advice;
|
||||
|
||||
|
||||
parser_compute_duration(t, st, pkt);
|
||||
return;
|
||||
uint8_t *buf = pkt->pkt_payload;
|
||||
uint32_t header;
|
||||
int sample_rate, duration;
|
||||
|
||||
header = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | (buf[3]);
|
||||
|
||||
sample_rate = mpegaudio_freq_tab[(header >> 10) & 3];
|
||||
duration = 90000 * 1152 / sample_rate;
|
||||
pkt->pkt_duration = duration;
|
||||
st->st_nextdts = pkt->pkt_dts + duration;
|
||||
|
||||
parser_deliver(t, st, pkt);
|
||||
st->st_curpts += duration;
|
||||
st->st_curdts += duration;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* AC3 audio parser
|
||||
*/
|
||||
#if 0
|
||||
const static int ac3_freq_tab[4] = {48000, 44100, 32000, 0};
|
||||
|
||||
const static uint16_t ac3_frame_size_tab[38][3] = {
|
||||
|
@ -346,65 +340,27 @@ const static uint16_t ac3_frame_size_tab[38][3] = {
|
|||
{ 1280, 1393, 1920 },
|
||||
{ 1280, 1394, 1920 },
|
||||
};
|
||||
#endif
|
||||
|
||||
static void
|
||||
parse_ac3(th_transport_t *t, th_stream_t *st, uint8_t *buf, int len)
|
||||
parse_ac3(th_transport_t *t, th_stream_t *st, th_pkt_t *pkt)
|
||||
{
|
||||
#if 0
|
||||
int hlen, l, src, fsc, sample_rate, v, bsid, frame_size;
|
||||
int o, duration;
|
||||
#endif
|
||||
uint8_t *buf = pkt->pkt_payload;
|
||||
uint32_t src, fsc;
|
||||
int sample_rate, frame_size, duration, bsid;
|
||||
|
||||
int hlen, l;
|
||||
int duration;
|
||||
th_pkt_t *pkt;
|
||||
src = buf[4] >> 6;
|
||||
fsc = buf[4] & 0x3f;
|
||||
bsid = (buf[5] & 0xf) - 8;
|
||||
if(bsid < 0)
|
||||
bsid = 0;
|
||||
|
||||
if(len < 9)
|
||||
return;
|
||||
sample_rate = ac3_freq_tab[src] >> bsid;
|
||||
frame_size = ac3_frame_size_tab[fsc][src] * 2;
|
||||
|
||||
if((hlen = parse_pes_header(t, st, buf + 6, len - 6)) < 0)
|
||||
return;
|
||||
|
||||
l = len - hlen - 6;
|
||||
if(l < 0)
|
||||
return;
|
||||
|
||||
buf += hlen + 6;
|
||||
len -= hlen + 6;
|
||||
|
||||
#if 0
|
||||
duration = 0;
|
||||
o = 0;
|
||||
|
||||
while(o < len - 8) {
|
||||
v = (buf[o] << 8) | buf[o + 1];
|
||||
if(v != 0xb77)
|
||||
break;
|
||||
|
||||
src = buf[o + 4] >> 6;
|
||||
fsc = buf[o + 4] & 0x3f;
|
||||
bsid = (buf[o + 5] & 0xf) - 8;
|
||||
if(bsid < 0)
|
||||
bsid = 0;
|
||||
|
||||
sample_rate = ac3_freq_tab[src] >> bsid;
|
||||
frame_size = ac3_frame_size_tab[fsc][src] * 2;
|
||||
|
||||
o += frame_size;
|
||||
duration += 90000 * 1536 / sample_rate;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
pkt = pkt_alloc(buf, len, st->st_curpts, st->st_curdts);
|
||||
pkt->pkt_commercial = t->tht_tt_commercial_advice;
|
||||
parser_compute_duration(t, st, pkt);
|
||||
return;
|
||||
duration = 90000 * 1536 / sample_rate;
|
||||
|
||||
pkt->pkt_duration = duration;
|
||||
st->st_curpts += duration;
|
||||
st->st_curdts += duration;
|
||||
st->st_nextdts = pkt->pkt_dts + duration;
|
||||
parser_deliver(t, st, pkt);
|
||||
}
|
||||
|
||||
|
|
1
tvhead.h
1
tvhead.h
|
@ -304,6 +304,7 @@ typedef struct th_stream {
|
|||
int64_t st_curpts;
|
||||
int64_t st_curdts;
|
||||
int64_t st_prevdts;
|
||||
int64_t st_nextdts;
|
||||
int st_frame_duration;
|
||||
|
||||
/* DTS generator */
|
||||
|
|
Loading…
Add table
Reference in a new issue