diff options
author | Ivan Schreter <schreter@gmx.net> | 2009-02-21 22:56:50 +0300 |
---|---|---|
committer | Carl Eugen Hoyos <cehoyos@rainbow.studorg.tuwien.ac.at> | 2009-02-21 22:56:50 +0300 |
commit | ff6474dd1505411e6875f431379ac4dbb5e45d4a (patch) | |
tree | 6184905e8f387f97bee11d905c8093b0a0aa35fd /libavcodec/h264_parser.c | |
parent | 1790a5e908ab98fcf4a81942b751feef67c9e779 (diff) |
Parse NAL units in H264 parser.
Patch by Ivan Schreter, schreter gmx net
Originally committed as revision 17488 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'libavcodec/h264_parser.c')
-rw-r--r-- | libavcodec/h264_parser.c | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/libavcodec/h264_parser.c b/libavcodec/h264_parser.c index a04fd21d51..e00c15bb60 100644 --- a/libavcodec/h264_parser.c +++ b/libavcodec/h264_parser.c @@ -27,6 +27,8 @@ #include "parser.h" #include "h264_parser.h" +#include "h264data.h" +#include "golomb.h" #include <assert.h> @@ -96,6 +98,73 @@ found: 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 @@ static int h264_parse(AVCodecParserContext *s, 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; |