Fix h264 parser
This commit is contained in:
parent
09129a1ba2
commit
4a18583645
5 changed files with 151 additions and 36 deletions
136
parser_h264.c
136
parser_h264.c
|
@ -30,19 +30,19 @@
|
|||
|
||||
#include "tvhead.h"
|
||||
#include "parsers.h"
|
||||
#include "parser_h264.h"
|
||||
#include "buffer.h"
|
||||
#include "bitstream.h"
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* H.264 parser, nal constructor
|
||||
* H.264 parser, nal escaper
|
||||
*/
|
||||
static int
|
||||
build_nal(bitstream_t *bs, uint8_t *data, int size, int maxsize)
|
||||
int
|
||||
h264_nal_deescape(bitstream_t *bs, uint8_t *data, int size)
|
||||
{
|
||||
int rbsp_size, i;
|
||||
|
||||
bs->data = malloc(maxsize);
|
||||
bs->data = malloc(size);
|
||||
|
||||
/* Escape 0x000003 into 0x0000 */
|
||||
|
||||
|
@ -62,15 +62,42 @@ build_nal(bitstream_t *bs, uint8_t *data, int size, int maxsize)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Level to CPB size table
|
||||
*/
|
||||
|
||||
static const int h264_lev2cpbsize[][2] = {
|
||||
{10, 175},
|
||||
{11, 500},
|
||||
{12, 1000},
|
||||
{13, 2000},
|
||||
{20, 2000},
|
||||
{21, 4000},
|
||||
{22, 4000},
|
||||
{30, 10000},
|
||||
{31, 14000},
|
||||
{32, 20000},
|
||||
{40, 25000},
|
||||
{41, 62500},
|
||||
{42, 62500},
|
||||
{50, 135000},
|
||||
{51, 240000},
|
||||
{-1, -1},
|
||||
};
|
||||
|
||||
|
||||
|
||||
typedef struct h264_private {
|
||||
|
||||
struct {
|
||||
int frame_duration;
|
||||
|
||||
} sps[256];
|
||||
struct {
|
||||
int frame_duration;
|
||||
int cbpsize;
|
||||
} sps[256];
|
||||
|
||||
struct {
|
||||
int sps;
|
||||
} pps[256];
|
||||
|
||||
} h264_private_t;
|
||||
|
||||
|
@ -83,6 +110,7 @@ decode_vui(th_stream_t *st, bitstream_t *bs, int spsid)
|
|||
int units_in_tick;
|
||||
int time_scale;
|
||||
int fixed_rate;
|
||||
return 0;
|
||||
|
||||
if(read_bits1(bs)) {
|
||||
if(read_bits(bs, 8) == 255) {
|
||||
|
@ -110,17 +138,17 @@ decode_vui(th_stream_t *st, bitstream_t *bs, int spsid)
|
|||
read_golomb_ue(bs); /* chroma_sample_location_type_bottom_field */
|
||||
}
|
||||
|
||||
if(!read_bits1(bs)) /* We want timing info */
|
||||
if(!read_bits1(bs)) /* We need timing info */
|
||||
return -1;
|
||||
|
||||
units_in_tick = read_bits(bs, 32);
|
||||
time_scale = read_bits(bs, 32);
|
||||
fixed_rate = read_bits1(bs);
|
||||
|
||||
#if 0
|
||||
printf("units_in_tick = %d\n", units_in_tick);
|
||||
printf("time_scale = %d\n", time_scale);
|
||||
printf("fixed_rate = %d\n", fixed_rate);
|
||||
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -146,9 +174,13 @@ decode_scaling_list(bitstream_t *bs, int size)
|
|||
int
|
||||
h264_decode_seq_parameter_set(th_stream_t *st, bitstream_t *bs)
|
||||
{
|
||||
// h264_private_t *priv = st->st_parser_private;
|
||||
int profile_idc, level_idc, poc_type;
|
||||
unsigned int sps_id, tmp, i;
|
||||
int cbpsize = -1;
|
||||
h264_private_t *p;
|
||||
|
||||
if((p = st->st_priv) == NULL)
|
||||
p = st->st_priv = calloc(1, sizeof(h264_private_t));
|
||||
|
||||
profile_idc= read_bits(bs, 8);
|
||||
read_bits1(bs); //constraint_set0_flag
|
||||
|
@ -159,9 +191,19 @@ h264_decode_seq_parameter_set(th_stream_t *st, bitstream_t *bs)
|
|||
level_idc= read_bits(bs, 8);
|
||||
sps_id= read_golomb_ue(bs);
|
||||
|
||||
printf("profile = %d\n", profile_idc);
|
||||
printf("level_idc = %d\n", level_idc);
|
||||
printf("sps_id = %d\n", sps_id);
|
||||
|
||||
i = 0;
|
||||
while(h264_lev2cpbsize[i][0] != -1) {
|
||||
if(h264_lev2cpbsize[i][0] >= level_idc) {
|
||||
cbpsize = h264_lev2cpbsize[i][1];
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if(cbpsize < 0)
|
||||
return -1;
|
||||
|
||||
p->sps[sps_id].cbpsize = cbpsize * 125; /* Convert from kbit to bytes */
|
||||
|
||||
|
||||
if(profile_idc >= 100){ //high profile
|
||||
|
@ -172,7 +214,6 @@ h264_decode_seq_parameter_set(th_stream_t *st, bitstream_t *bs)
|
|||
read_bits1(bs);
|
||||
|
||||
if(read_bits1(bs)) {
|
||||
printf("scaling\n");
|
||||
/* Scaling matrices */
|
||||
decode_scaling_list(bs, 16);
|
||||
decode_scaling_list(bs, 16);
|
||||
|
@ -188,10 +229,8 @@ h264_decode_seq_parameter_set(th_stream_t *st, bitstream_t *bs)
|
|||
}
|
||||
|
||||
tmp = read_golomb_ue(bs); /* max frame num */
|
||||
printf("maxframenum = %d\n", tmp);
|
||||
poc_type= read_golomb_ue(bs);
|
||||
printf("poc_type = %d\n", poc_type);
|
||||
|
||||
|
||||
if(poc_type == 0){ //FIXME #define
|
||||
read_golomb_ue(bs);
|
||||
} else if(poc_type == 1){//FIXME #define
|
||||
|
@ -203,13 +242,11 @@ h264_decode_seq_parameter_set(th_stream_t *st, bitstream_t *bs)
|
|||
read_golomb_se(bs);
|
||||
|
||||
}else if(poc_type != 2){
|
||||
printf("Illegal POC type %d\n", poc_type);
|
||||
/* Illegal poc */
|
||||
return -1;
|
||||
}
|
||||
|
||||
tmp = read_golomb_ue(bs);
|
||||
printf("reference frames = %d\n", tmp);
|
||||
|
||||
read_bits1(bs);
|
||||
|
||||
|
@ -236,3 +273,56 @@ h264_decode_seq_parameter_set(th_stream_t *st, bitstream_t *bs)
|
|||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
h264_decode_pic_parameter_set(th_stream_t *st, bitstream_t *bs)
|
||||
{
|
||||
h264_private_t *p;
|
||||
int pps_id, sps_id;
|
||||
|
||||
if((p = st->st_priv) == NULL)
|
||||
p = st->st_priv = calloc(1, sizeof(h264_private_t));
|
||||
|
||||
pps_id = read_golomb_ue(bs);
|
||||
sps_id = read_golomb_ue(bs);
|
||||
p->pps[pps_id].sps = sps_id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
h264_decode_slice_header(th_stream_t *st, bitstream_t *bs, int *pkttype)
|
||||
{
|
||||
h264_private_t *p;
|
||||
int slice_type, pps_id, sps_id;
|
||||
|
||||
if((p = st->st_priv) == NULL)
|
||||
return -1;
|
||||
|
||||
read_golomb_ue(bs); /* first_mb_in_slice */
|
||||
slice_type = read_golomb_ue(bs);
|
||||
|
||||
switch(slice_type) {
|
||||
case 0:
|
||||
*pkttype = PKT_P_FRAME;
|
||||
break;
|
||||
case 1:
|
||||
*pkttype = PKT_B_FRAME;
|
||||
break;
|
||||
case 2:
|
||||
*pkttype = PKT_I_FRAME;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
pps_id = read_golomb_ue(bs);
|
||||
sps_id = p->pps[pps_id].sps;
|
||||
if(p->sps[sps_id].cbpsize == 0)
|
||||
return -1;
|
||||
|
||||
st->st_vbv_size = p->sps[sps_id].cbpsize;
|
||||
st->st_vbv_delay = -1;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -21,6 +21,12 @@
|
|||
|
||||
#include "bitstream.h"
|
||||
|
||||
int h264_nal_deescape(bitstream_t *bs, uint8_t *data, int size);
|
||||
|
||||
int h264_decode_seq_parameter_set(th_stream_t *st, bitstream_t *bs);
|
||||
|
||||
int h264_decode_pic_parameter_set(th_stream_t *st, bitstream_t *bs);
|
||||
|
||||
int h264_decode_slice_header(th_stream_t *st, bitstream_t *bs, int *pkttype);
|
||||
|
||||
#endif /* PARSER_H264_H_ */
|
||||
|
|
40
parsers.c
40
parsers.c
|
@ -594,6 +594,8 @@ parse_h264(th_transport_t *t, th_stream_t *st, size_t len,
|
|||
uint8_t *buf = st->st_buffer + sc_offset;
|
||||
uint32_t sc = st->st_startcode;
|
||||
int64_t d;
|
||||
int l2, pkttype;
|
||||
bitstream_t bs;
|
||||
|
||||
if(sc >= 0x000001e0 && sc <= 0x000001ef) {
|
||||
/* System start codes for video */
|
||||
|
@ -610,34 +612,49 @@ parse_h264(th_transport_t *t, th_stream_t *st, size_t len,
|
|||
st->st_prevdts = st->st_curdts;
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("sc = %x\n", sc & 0x1f);
|
||||
|
||||
bs.data = NULL;
|
||||
|
||||
switch(sc & 0x1f) {
|
||||
|
||||
case 7:
|
||||
h264_nal_deescape(&bs, buf + 3, len - 3);
|
||||
if(h264_decode_seq_parameter_set(st, &bs))
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case 8:
|
||||
h264_nal_deescape(&bs, buf + 3, len - 3);
|
||||
if(h264_decode_pic_parameter_set(st, &bs))
|
||||
return 1;
|
||||
break;
|
||||
|
||||
|
||||
case 5: /* IDR+SLICE */
|
||||
/* IDR seen, set DTS offset if not already set */
|
||||
case 1:
|
||||
if(st->st_curpkt != NULL || st->st_frame_duration == 0)
|
||||
break;
|
||||
|
||||
if(t->tht_dts_start == AV_NOPTS_VALUE)
|
||||
t->tht_dts_start = st->st_curdts;
|
||||
|
||||
case 1:
|
||||
if(st->st_curpkt != NULL)
|
||||
break;
|
||||
printf("Creating pkt @ %lld %lld\n", st->st_curpts, st->st_curdts);
|
||||
l2 = len - 3 > 64 ? 64 : len - 3;
|
||||
h264_nal_deescape(&bs, buf + 3, len); /* we just the first stuff */
|
||||
if(h264_decode_slice_header(st, &bs, &pkttype))
|
||||
return 1;
|
||||
|
||||
st->st_curpkt = pkt_alloc(NULL, 0, st->st_curpts, st->st_curdts);
|
||||
st->st_curpkt->pkt_frametype = 0;
|
||||
st->st_curpkt->pkt_frametype = pkttype;
|
||||
st->st_curpkt->pkt_duration = st->st_frame_duration;
|
||||
st->st_curpkt->pkt_commercial = t->tht_tt_commercial_advice;
|
||||
|
||||
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
free(bs.data);
|
||||
|
||||
if(next_startcode >= 0x000001e0 && next_startcode <= 0x000001ef) {
|
||||
/* Complete frame */
|
||||
|
||||
|
@ -652,7 +669,6 @@ parse_h264(th_transport_t *t, th_stream_t *st, size_t len,
|
|||
st->st_buffer = malloc(st->st_buffer_size);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -98,8 +98,10 @@ transport_stop(th_transport_t *t, int flush_subscriptions)
|
|||
st->st_parser = NULL;
|
||||
st->st_ctx = NULL;
|
||||
|
||||
/* Clear reassembly buffer */
|
||||
free(st->st_priv);
|
||||
|
||||
/* Clear reassembly buffer */
|
||||
|
||||
free(st->st_buffer);
|
||||
st->st_buffer = NULL;
|
||||
st->st_buffer_size = 0;
|
||||
|
|
1
tvhead.h
1
tvhead.h
|
@ -299,6 +299,7 @@ typedef struct th_stream {
|
|||
uint32_t st_startcode;
|
||||
uint32_t st_startcode_offset;
|
||||
int st_parser_state;
|
||||
void *st_priv; /* Parser private data */
|
||||
|
||||
struct th_pkt *st_curpkt;
|
||||
int64_t st_curpts;
|
||||
|
|
Loading…
Add table
Reference in a new issue