Skip to content
Snippets Groups Projects
vc1.c 148 KiB
Newer Older
  • Learn to ignore specific revisions
  • 
        /* select codingmode used for VLC tables selection */
        switch(v->c_ac_table_index){
        case 0:
            v->codingset = (v->pqindex <= 8) ? CS_HIGH_RATE_INTRA : CS_LOW_MOT_INTRA;
            break;
        case 1:
            v->codingset = CS_HIGH_MOT_INTRA;
            break;
        case 2:
            v->codingset = CS_MID_RATE_INTRA;
            break;
        }
    
        switch(v->c_ac_table_index){
        case 0:
            v->codingset2 = (v->pqindex <= 8) ? CS_HIGH_RATE_INTER : CS_LOW_MOT_INTER;
            break;
        case 1:
            v->codingset2 = CS_HIGH_MOT_INTER;
            break;
        case 2:
            v->codingset2 = CS_MID_RATE_INTER;
            break;
        }
    
        ff_er_add_slice(s, 0, 0, s->mb_width - 1, s->mb_height - 1, (AC_END|DC_END|MV_END));
        s->first_slice_line = 1;
        for(s->mb_y = 0; s->mb_y < s->mb_height; s->mb_y++) {
            for(s->mb_x = 0; s->mb_x < s->mb_width; s->mb_x++) {
                ff_init_block_index(s);
                ff_update_block_index(s);
                s->dsp.clear_blocks(s->block[0]);
    
                vc1_decode_b_mb(v);
                if(get_bits_count(&s->gb) > v->bits || get_bits_count(&s->gb) < 0) {
                    av_log(s->avctx, AV_LOG_ERROR, "Bits overconsumption: %i > %i at %ix%i\n", get_bits_count(&s->gb), v->bits,s->mb_x,s->mb_y);
                    return;
                }
            }
            ff_draw_horiz_band(s, s->mb_y * 16, 16);
            s->first_slice_line = 0;
        }
    }
    
    
    static void vc1_decode_skip_blocks(VC1Context *v)
    {
        MpegEncContext *s = &v->s;
    
        ff_er_add_slice(s, 0, 0, s->mb_width - 1, s->mb_height - 1, (AC_END|DC_END|MV_END));
        s->first_slice_line = 1;
        for(s->mb_y = 0; s->mb_y < s->mb_height; s->mb_y++) {
            s->mb_x = 0;
            ff_init_block_index(s);
            ff_update_block_index(s);
            memcpy(s->dest[0], s->last_picture.data[0] + s->mb_y * 16 * s->linesize, s->linesize * 16);
            memcpy(s->dest[1], s->last_picture.data[1] + s->mb_y * 8 * s->uvlinesize, s->uvlinesize * 8);
            memcpy(s->dest[2], s->last_picture.data[2] + s->mb_y * 8 * s->uvlinesize, s->uvlinesize * 8);
            ff_draw_horiz_band(s, s->mb_y * 16, 16);
            s->first_slice_line = 0;
        }
        s->pict_type = P_TYPE;
    }
    
    
    static void vc1_decode_blocks(VC1Context *v)
    
    anonymous's avatar
    anonymous committed
    
    
        switch(v->s.pict_type) {
        case I_TYPE:
    
            if(v->profile == PROFILE_ADVANCED)
                vc1_decode_i_blocks_adv(v);
            else
                vc1_decode_i_blocks(v);
    
            if(v->p_frame_skipped)
                vc1_decode_skip_blocks(v);
            else
                vc1_decode_p_blocks(v);
    
            if(v->bi_type)
                vc1_decode_i_blocks(v);
            else
                vc1_decode_b_blocks(v);
    
    /** Initialize a VC1/WMV3 decoder
     * @todo TODO: Handle VC-1 IDUs (Transport level?)
    
     * @todo TODO: Decypher remaining bits in extra_data
     */
    
    static int vc1_decode_init(AVCodecContext *avctx)
    
        VC1Context *v = avctx->priv_data;
    
    anonymous's avatar
    anonymous committed
        MpegEncContext *s = &v->s;
    
        GetBitContext gb;
    
        if (!avctx->extradata_size || !avctx->extradata) return -1;
    
        if (!(avctx->flags & CODEC_FLAG_GRAY))
            avctx->pix_fmt = PIX_FMT_YUV420P;
        else
            avctx->pix_fmt = PIX_FMT_GRAY8;
    
    anonymous's avatar
    anonymous committed
        v->s.avctx = avctx;
    
        avctx->flags |= CODEC_FLAG_EMU_EDGE;
        v->s.flags |= CODEC_FLAG_EMU_EDGE;
    
    anonymous's avatar
    anonymous committed
        if(ff_h263_decode_init(avctx) < 0)
            return -1;
    
        if (vc1_init_common(v) < 0) return -1;
    
    anonymous's avatar
    anonymous committed
        avctx->coded_width = avctx->width;
        avctx->coded_height = avctx->height;
    
    anonymous's avatar
    anonymous committed
            // looks like WMV3 has a sequence header stored in the extradata
            // advanced sequence header may be before the first frame
            // the last byte of the extradata is a version number, 1 for the
            // samples we can decode
    
            init_get_bits(&gb, avctx->extradata, avctx->extradata_size*8);
    
            if (decode_sequence_header(avctx, &gb) < 0)
              return -1;
    
    anonymous's avatar
    anonymous committed
            count = avctx->extradata_size*8 - get_bits_count(&gb);
            if (count>0)
            {
                av_log(avctx, AV_LOG_INFO, "Extra data: %i bits left, value: %X\n",
                       count, get_bits(&gb, count));
            }
    
    anonymous's avatar
    anonymous committed
            {
                av_log(avctx, AV_LOG_INFO, "Read %i bits in overflow\n", -count);
            }
    
        } else { // VC1/WVC1
            int edata_size = avctx->extradata_size;
            uint8_t *edata = avctx->extradata;
    
            if(avctx->extradata_size < 16) {
                av_log(avctx, AV_LOG_ERROR, "Extradata size too small: %i\n", edata_size);
                return -1;
            }
            while(edata_size > 8) {
                // test if we've found header
    
                if(AV_RB32(edata) == 0x0000010F) {
    
                    edata += 4;
                    edata_size -= 4;
                    break;
                }
                edata_size--;
                edata++;
            }
    
            init_get_bits(&gb, edata, edata_size*8);
    
            if (decode_sequence_header(avctx, &gb) < 0)
              return -1;
    
            while(edata_size > 8) {
                // test if we've found entry point
    
                if(AV_RB32(edata) == 0x0000010E) {
    
                    edata += 4;
                    edata_size -= 4;
                    break;
                }
                edata_size--;
                edata++;
            }
    
            init_get_bits(&gb, edata, edata_size*8);
    
            if (decode_entry_point(avctx, &gb) < 0)
              return -1;
    
    anonymous's avatar
    anonymous committed
        avctx->has_b_frames= !!(avctx->max_b_frames);
    
        s->low_delay = !avctx->has_b_frames;
    
    anonymous's avatar
    anonymous committed
        s->mb_width = (avctx->coded_width+15)>>4;
        s->mb_height = (avctx->coded_height+15)>>4;
    
        v->mv_type_mb_plane = av_malloc(s->mb_stride * s->mb_height);
    
        v->direct_mb_plane = av_malloc(s->mb_stride * s->mb_height);
    
        v->acpred_plane = av_malloc(s->mb_stride * s->mb_height);
        v->over_flags_plane = av_malloc(s->mb_stride * s->mb_height);
    
    anonymous's avatar
    anonymous committed
    
    
    Kostya Shishkov's avatar
    Kostya Shishkov committed
        /* allocate block type info in that way so it could be used with s->block_index[] */
        v->mb_type_base = av_malloc(s->b8_stride * (s->mb_height * 2 + 1) + s->mb_stride * (s->mb_height + 1) * 2);
        v->mb_type[0] = v->mb_type_base + s->b8_stride + 1;
        v->mb_type[1] = v->mb_type_base + s->b8_stride * (s->mb_height * 2 + 1) + s->mb_stride + 1;
        v->mb_type[2] = v->mb_type[1] + s->mb_stride * (s->mb_height + 1);
    
    
        if (v->profile == PROFILE_ADVANCED)
    
    //        if (alloc_bitplane(&v->over_flags_plane, s->mb_width, s->mb_height) < 0)
    //            return -1;
    //        if (alloc_bitplane(&v->ac_pred_plane, s->mb_width, s->mb_height) < 0)
    //            return -1;
    
    /** Decode a VC1/WMV3 frame
     * @todo TODO: Handle VC-1 IDUs (Transport level?)
    
    static int vc1_decode_frame(AVCodecContext *avctx,
    
        VC1Context *v = avctx->priv_data;
    
    anonymous's avatar
    anonymous committed
        MpegEncContext *s = &v->s;
    
    anonymous's avatar
    anonymous committed
    
        /* no supplementary picture */
        if (buf_size == 0) {
            /* special case for last picture */
            if (s->low_delay==0 && s->next_picture_ptr) {
                *pict= *(AVFrame*)s->next_picture_ptr;
                s->next_picture_ptr= NULL;
    
                *data_size = sizeof(AVFrame);
            }
    
            return 0;
        }
    
        //we need to set current_picture_ptr before reading the header, otherwise we cant store anyting im there
        if(s->current_picture_ptr==NULL || s->current_picture_ptr->data[0]){
    
            int i= ff_find_unused_picture(s, 0);
            s->current_picture_ptr= &s->picture[i];
    
    anonymous's avatar
    anonymous committed
        }
    
    
        //for advanced profile we need to unescape buffer
        if (avctx->codec_id == CODEC_ID_VC1) {
            int i, buf_size2;
            buf2 = av_malloc(buf_size + FF_INPUT_BUFFER_PADDING_SIZE);
            buf_size2 = 0;
            for(i = 0; i < buf_size; i++) {
                if(buf[i] == 3 && i >= 2 && !buf[i-1] && !buf[i-2] && i < buf_size-1 && buf[i+1] < 4) {
                    buf2[buf_size2++] = buf[i+1];
                    i++;
                } else
                    buf2[buf_size2++] = buf[i];
            }
            init_get_bits(&s->gb, buf2, buf_size2*8);
        } else
            init_get_bits(&s->gb, buf, buf_size*8);
    
        if(v->profile < PROFILE_ADVANCED) {
            if(vc1_parse_frame_header(v, &s->gb) == -1) {
    
                return -1;
            }
        } else {
            if(vc1_parse_frame_header_adv(v, &s->gb) == -1) {
    
        if(s->pict_type != I_TYPE && !v->res_rtm_flag){
    
    anonymous's avatar
    anonymous committed
    
        // for hurry_up==5
        s->current_picture.pict_type= s->pict_type;
        s->current_picture.key_frame= s->pict_type == I_TYPE;
    
    
        /* skip B-frames if we don't have reference frames */
    
        if(s->last_picture_ptr==NULL && (s->pict_type==B_TYPE || s->dropable)){
    
    anonymous's avatar
    anonymous committed
        /* skip b frames if we are in a hurry */
    
        if(avctx->hurry_up && s->pict_type==B_TYPE) return -1;//buf_size;
        if(   (avctx->skip_frame >= AVDISCARD_NONREF && s->pict_type==B_TYPE)
           || (avctx->skip_frame >= AVDISCARD_NONKEY && s->pict_type!=I_TYPE)
    
           ||  avctx->skip_frame >= AVDISCARD_ALL) {
    
    anonymous's avatar
    anonymous committed
        /* skip everything if we are in a hurry>=5 */
    
    anonymous's avatar
    anonymous committed
        if(s->next_p_frame_damaged){
            if(s->pict_type==B_TYPE)
    
    anonymous's avatar
    anonymous committed
            else
                s->next_p_frame_damaged=0;
        }
    
    
    anonymous's avatar
    anonymous committed
            return -1;
    
    anonymous's avatar
    anonymous committed
    
        ff_er_frame_start(s);
    
    
        v->bits = buf_size * 8;
        vc1_decode_blocks(v);
    //av_log(s->avctx, AV_LOG_INFO, "Consumed %i/%i bits\n", get_bits_count(&s->gb), buf_size*8);
    //  if(get_bits_count(&s->gb) > buf_size * 8)
    //      return -1;
    
    anonymous's avatar
    anonymous committed
        ff_er_frame_end(s);
    
        MPV_frame_end(s);
    
    
    assert(s->current_picture.pict_type == s->current_picture_ptr->pict_type);
    assert(s->current_picture.pict_type == s->pict_type);
    
        if (s->pict_type == B_TYPE || s->low_delay) {
            *pict= *(AVFrame*)s->current_picture_ptr;
        } else if (s->last_picture_ptr != NULL) {
            *pict= *(AVFrame*)s->last_picture_ptr;
        }
    
        if(s->last_picture_ptr || s->low_delay){
            *data_size = sizeof(AVFrame);
    
    anonymous's avatar
    anonymous committed
            ff_print_debug_info(s, pict);
        }
    
        /* Return the Picture timestamp as the frame number */
        /* we substract 1 because it is added on utils.c    */
        avctx->frame_number = s->picture_number - 1;
    
    
    /** Close a VC1/WMV3 decoder
    
     * @warning Initial try at using MpegEncContext stuff
     */
    
    static int vc1_decode_end(AVCodecContext *avctx)
    
        VC1Context *v = avctx->priv_data;
    
        av_freep(&v->hrd_rate);
        av_freep(&v->hrd_buffer);
    
    anonymous's avatar
    anonymous committed
        MPV_common_end(&v->s);
    
        av_freep(&v->mv_type_mb_plane);
    
        av_freep(&v->acpred_plane);
        av_freep(&v->over_flags_plane);
    
    Kostya Shishkov's avatar
    Kostya Shishkov committed
        av_freep(&v->mb_type_base);
    
    AVCodec vc1_decoder = {
        "vc1",
    
        CODEC_ID_VC1,
        sizeof(VC1Context),
        vc1_decode_init,
    
        vc1_decode_end,
        vc1_decode_frame,
    
        sizeof(VC1Context),
        vc1_decode_init,
    
        vc1_decode_end,
        vc1_decode_frame,