Mercurial > libavcodec.hg
changeset 8997:1c69c50d78f1 libavcodec
Parse NAL units in H264 parser.
Patch by Ivan Schreter, schreter gmx net
author | cehoyos |
---|---|
date | Sat, 21 Feb 2009 19:56:50 +0000 |
parents | e65778184ded |
children | 9339bf262eb5 |
files | h264_parser.c |
diffstat | 1 files changed, 71 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/h264_parser.c Sat Feb 21 19:54:14 2009 +0000 +++ b/h264_parser.c Sat Feb 21 19:56:50 2009 +0000 @@ -27,6 +27,8 @@ #include "parser.h" #include "h264_parser.h" +#include "h264data.h" +#include "golomb.h" #include <assert.h> @@ -96,6 +98,73 @@ return i-(state&5); } +/*! + * Parse NAL units of found picture and decode some basic information. + * + * @param s parser context. + * @param avctx codec context. + * @param buf buffer with field/frame data. + * @param buf_size size of the buffer. + */ +static inline int parse_nal_units(AVCodecParserContext *s, + AVCodecContext *avctx, + const uint8_t *buf, int buf_size) +{ + H264Context *h = s->priv_data; + const uint8_t *buf_end = buf + buf_size; + unsigned int slice_type; + int state; + const uint8_t *ptr; + + /* set some sane default values */ + s->pict_type = FF_I_TYPE; + + h->s.avctx= avctx; + + for(;;) { + int src_length, dst_length, consumed; + buf = ff_find_start_code(buf, buf_end, &state); + if(buf >= buf_end) + break; + --buf; + src_length = buf_end - buf; + switch (state & 0x1f) { + case NAL_SLICE: + case NAL_IDR_SLICE: + // Do not walk the whole buffer just to decode slice header + if (src_length > 20) + src_length = 20; + break; + } + ptr= ff_h264_decode_nal(h, buf, &dst_length, &consumed, src_length); + if (ptr==NULL || dst_length < 0) + break; + + init_get_bits(&h->s.gb, ptr, 8*dst_length); + switch(h->nal_unit_type) { + case NAL_SPS: + ff_h264_decode_seq_parameter_set(h); + break; + case NAL_PPS: + ff_h264_decode_picture_parameter_set(h, h->s.gb.size_in_bits); + break; + case NAL_SEI: + ff_h264_decode_sei(h); + break; + case NAL_IDR_SLICE: + case NAL_SLICE: + get_ue_golomb(&h->s.gb); // skip first_mb_in_slice + slice_type = get_ue_golomb_31(&h->s.gb); + s->pict_type = golomb_to_pict_type[slice_type % 5]; + return 0; /* no need to evaluate the rest */ + } + buf += consumed; + } + /* didn't find a picture! */ + av_log(h->s.avctx, AV_LOG_ERROR, "missing picture in access unit\n"); + return -1; +} + static int h264_parse(AVCodecParserContext *s, AVCodecContext *avctx, const uint8_t **poutbuf, int *poutbuf_size, @@ -120,6 +189,8 @@ assert(pc->last_index + next >= 0 ); ff_h264_find_frame_end(h, &pc->buffer[pc->last_index + next], -next); //update state } + + parse_nal_units(s, avctx, buf, buf_size); } *poutbuf = buf;