diff libavcodec/h264_parser.c @ 2:897f711a7157

rearrange to work with autoconf
author Nina Engelhardt <nengel@mailbox.tu-berlin.de>
date Tue, 25 Sep 2012 15:55:33 +0200
parents
children
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/libavcodec/h264_parser.c	Tue Sep 25 15:55:33 2012 +0200
     1.3 @@ -0,0 +1,224 @@
     1.4 +/*
     1.5 + * H.26L/H.264/AVC/JVT/14496-10/... parser
     1.6 + * Copyright (c) 2003 Michael Niedermayer <michaelni@gmx.at>
     1.7 + *
     1.8 + * This file is part of FFmpeg.
     1.9 + *
    1.10 + * FFmpeg is free software; you can redistribute it and/or
    1.11 + * modify it under the terms of the GNU Lesser General Public
    1.12 + * License as published by the Free Software Foundation; either
    1.13 + * version 2.1 of the License, or (at your option) any later version.
    1.14 + *
    1.15 + * FFmpeg is distributed in the hope that it will be useful,
    1.16 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    1.18 + * Lesser General Public License for more details.
    1.19 + *
    1.20 + * You should have received a copy of the GNU Lesser General Public
    1.21 + * License along with FFmpeg; if not, write to the Free Software
    1.22 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
    1.23 + */
    1.24 +
    1.25 +/**
    1.26 + * @file
    1.27 + * H.264 / AVC / MPEG4 part10 parser.
    1.28 + * @author Michael Niedermayer <michaelni@gmx.at>
    1.29 + */
    1.30 +
    1.31 +#include <unistd.h>
    1.32 +
    1.33 +#include "golomb.h"
    1.34 +#include "libavutil/error.h"
    1.35 +#include "h264_types.h"
    1.36 +
    1.37 +#undef NDEBUG
    1.38 +#include <assert.h>
    1.39 +
    1.40 +#define END_NOT_FOUND (-100)
    1.41 +
    1.42 +static int ff_h264_find_frame_end(ParserContext *s, const uint8_t *buf, int buf_size)
    1.43 +{
    1.44 +    int i;
    1.45 +    uint32_t state;
    1.46 +
    1.47 +    state= s->state;
    1.48 +    if(state>13)
    1.49 +        state= 7;
    1.50 +
    1.51 +    for(i=0; i<buf_size; i++){
    1.52 +        if(state==7){
    1.53 +        /* we check i<buf_size instead of i+3/7 because its simpler
    1.54 +         * and there should be FF_INPUT_BUFFER_PADDING_SIZE bytes at the end
    1.55 +         */
    1.56 +            while(i<buf_size && !((~*(const uint64_t*)(buf+i) & (*(const uint64_t*)(buf+i) - 0x0101010101010101ULL)) & 0x8080808080808080ULL))
    1.57 +                i+=8;
    1.58 +
    1.59 +            for(; i<buf_size; i++){
    1.60 +                if(!buf[i]){
    1.61 +                    state=2;
    1.62 +                    break;
    1.63 +                }
    1.64 +            }
    1.65 +        }else if(state<=2){
    1.66 +            if(buf[i]==1)   state^= 5; //2->7, 1->4, 0->5
    1.67 +            else if(buf[i]) state = 7;
    1.68 +            else            state>>=1; //2->1, 1->0, 0->0
    1.69 +        }else if(state<=5){
    1.70 +            int v= buf[i] & 0x1F;
    1.71 +            if(v==6 || v==7 || v==8 || v==9){
    1.72 +                if(s->frame_start_found){
    1.73 +                    i++;
    1.74 +                    goto found;
    1.75 +                }
    1.76 +            }else if(v==1 || v==2 || v==5){
    1.77 +                if(s->frame_start_found){
    1.78 +                    state+=8;
    1.79 +                    continue;
    1.80 +                }else
    1.81 +                    s->frame_start_found = 1;
    1.82 +            }
    1.83 +            state= 7;
    1.84 +        }else{
    1.85 +            if(buf[i] & 0x80)
    1.86 +                goto found;
    1.87 +            state= 7;
    1.88 +        }
    1.89 +    }
    1.90 +    s->state= state;
    1.91 +    return END_NOT_FOUND;
    1.92 +
    1.93 +found:
    1.94 +    s->state=7;
    1.95 +    s->frame_start_found= 0;
    1.96 +    return i-(state&5);
    1.97 +}
    1.98 +
    1.99 +static int ff_combine_frame(ParserContext *s, GetBitContext *gb, int next, uint8_t **buf, int *buf_size)
   1.100 +{
   1.101 +    int i;
   1.102 +    /* Copy overread bytes from last frame into buffer. */
   1.103 +    for(i =0; s->overread_cnt>0; s->overread_cnt--, i++){
   1.104 +        gb->raw[s->index++]= s->overread[i];
   1.105 +    }
   1.106 +
   1.107 +    /* EOF - END_NOT_FOUND means no next frame start is found in current partial read. If buf_size of the partial read is 0 we are at EOF */
   1.108 +    if(!*buf_size && next == END_NOT_FOUND){
   1.109 +        next= 0;
   1.110 +    }
   1.111 +    s->last_index= s->index;
   1.112 +
   1.113 +    /* copy into buffer end return */
   1.114 +    if(next == END_NOT_FOUND){
   1.115 +        gb->raw = av_fast_realloc(gb->raw, &gb->alloc_size, (*buf_size) + s->index + FF_INPUT_BUFFER_PADDING_SIZE);
   1.116 +        memcpy(&gb->raw[s->index], *buf, *buf_size);
   1.117 +        s->index += *buf_size;
   1.118 +        return -1;
   1.119 +    }
   1.120 +
   1.121 +    ///end found
   1.122 +    *buf_size=  s->index + next;
   1.123 +    /* append to buffer */
   1.124 +
   1.125 +    gb->raw = av_fast_realloc(gb->raw, &gb->alloc_size, next + s->index + FF_INPUT_BUFFER_PADDING_SIZE);
   1.126 +    memcpy(&gb->raw[s->index], *buf, next + FF_INPUT_BUFFER_PADDING_SIZE );
   1.127 +    s->index = 0;
   1.128 +
   1.129 +    /* store overread bytes */
   1.130 +    for(i=0; next < 0; next++, i++){
   1.131 +        s->state = (s->state<<8) | gb->raw[s->last_index + next];
   1.132 +        s->overread[i] = gb->raw[s->last_index + next];
   1.133 +        s->overread_cnt++;
   1.134 +    }
   1.135 +
   1.136 +    return 0;
   1.137 +}
   1.138 +
   1.139 +static int h264_parse(ParserContext *s, GetBitContext *gb,
   1.140 +                      uint8_t *buf, int buf_size)
   1.141 +{
   1.142 +    int next;
   1.143 +
   1.144 +    next= ff_h264_find_frame_end(s, buf, buf_size);
   1.145 +
   1.146 +    if (ff_combine_frame(s, gb, next, &buf, &buf_size) < 0) {
   1.147 +        gb->buf_size = 0;
   1.148 +        return buf_size;
   1.149 +    }
   1.150 +
   1.151 +    if(next<0 && next != END_NOT_FOUND){
   1.152 +        assert(s->last_index + next >= 0 );
   1.153 +        ff_h264_find_frame_end(s, &gb->raw[s->last_index + next], -next); //update state
   1.154 +    }
   1.155 +
   1.156 +    gb->buf_size = buf_size;
   1.157 +    return next;
   1.158 +}
   1.159 +
   1.160 +static int ff_raw_read_partial_packet(ParserContext *pc)
   1.161 +{
   1.162 +    int len= -1;
   1.163 +
   1.164 +    if (!pc->eof_reached){
   1.165 +        len = read( pc->ifile, pc->data, pc->buffer_size);
   1.166 +//         printf("read task %d\t%d\n", pc->ifile, len); fflush(NULL);
   1.167 +        if (len < pc->buffer_size) {
   1.168 +            pc->eof_reached = 1;
   1.169 +        }
   1.170 +    }
   1.171 +
   1.172 +    return len;
   1.173 +}
   1.174 +
   1.175 +void av_read_frame_internal(ParserContext *pc, GetBitContext *gb){
   1.176 +    int len;
   1.177 +    uint8_t dummy_buf[FF_INPUT_BUFFER_PADDING_SIZE]={0};
   1.178 +    av_fast_malloc(&gb->raw, &gb->alloc_size, 2048+FF_INPUT_BUFFER_PADDING_SIZE);
   1.179 +
   1.180 +    //Parsing is performed before read, since there are ussually leftovers from parsing the previous frame.
   1.181 +    for(;;) {
   1.182 +        if (pc->cur_len>0){
   1.183 +            len = h264_parse(pc, gb, pc->cur_ptr, pc->cur_len);
   1.184 +            if (len<0)
   1.185 +                len =0;
   1.186 +            //* increment read pointer */
   1.187 +            pc->cur_ptr += len;
   1.188 +            pc->cur_len -= len;
   1.189 +
   1.190 +            if (gb->buf_size) {
   1.191 +                break;
   1.192 +            }
   1.193 +        }
   1.194 +
   1.195 +        //check for ret and not parser->eof_reached as one "read" can contain more than 1 frame
   1.196 +        pc->size= ff_raw_read_partial_packet(pc);
   1.197 +        if (pc->size < 0) {
   1.198 +            pc->final_frame =1;
   1.199 +            /* return the last frames, if any */
   1.200 +            h264_parse(pc, gb, dummy_buf, 0);
   1.201 +            break;
   1.202 +        }
   1.203 +        pc->cur_ptr = pc->data;
   1.204 +        pc->cur_len = pc->size;
   1.205 +    }
   1.206 +
   1.207 +    assert(gb->raw!=NULL);
   1.208 +
   1.209 +}
   1.210 +
   1.211 +ParserContext *get_parse_context(int ifile){
   1.212 +    ParserContext *pc = av_mallocz(sizeof(ParserContext));
   1.213 +    pc->buffer_size = 2048;
   1.214 +    pc->final_frame = 0;
   1.215 +    pc->cur_len= 0;
   1.216 +    pc->data = av_mallocz(2048 + FF_INPUT_BUFFER_PADDING_SIZE);
   1.217 +    pc->size = 2048;
   1.218 +    pc->eof_reached =0;
   1.219 +    pc->ifile = ifile;
   1.220 +
   1.221 +    return pc;
   1.222 +}
   1.223 +
   1.224 +void free_parse_context(ParserContext *pc){
   1.225 +    av_free(pc->data);
   1.226 +    av_free(pc);
   1.227 +}