blob: 8a6d25a4185512bec8e6dfaf8909b22ddb66d405 [file] [log] [blame]
/*
* H.26L/H.264/AVC/JVT/14496-10/... decoder
* Copyright (c) 2003 Michael Niedermayer <michaelni@gmx.at>
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file
* H.264 / AVC / MPEG4 part10 codec.
* @author Michael Niedermayer <michaelni@gmx.at>
*/
#include "libavutil/imgutils.h"
#include "internal.h"
#include "dsputil.h"
#include "avcodec.h"
#include "mpegvideo.h"
#include "h264.h"
#include "h264data.h"
#include "h264_mvpred.h"
#include "golomb.h"
#include "mathops.h"
#include "rectangle.h"
#include "thread.h"
#include "vdpau_internal.h"
#include "libavutil/avassert.h"
#include "cabac.h"
//#undef NDEBUG
#include <assert.h>
static const uint8_t rem6[QP_MAX_NUM+1]={
0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3,
};
static const uint8_t div6[QP_MAX_NUM+1]={
0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9,10,10,10,10,
};
static const enum PixelFormat hwaccel_pixfmt_list_h264_jpeg_420[] = {
PIX_FMT_DXVA2_VLD,
PIX_FMT_VAAPI_VLD,
PIX_FMT_YUVJ420P,
PIX_FMT_NONE
};
/**
* checks if the top & left blocks are available if needed & changes the dc mode so it only uses the available blocks.
*/
int ff_h264_check_intra4x4_pred_mode(H264Context *h){
MpegEncContext * const s = &h->s;
static const int8_t top [12]= {-1, 0,LEFT_DC_PRED,-1,-1,-1,-1,-1, 0};
static const int8_t left[12]= { 0,-1, TOP_DC_PRED, 0,-1,-1,-1, 0,-1,DC_128_PRED};
int i;
if(!(h->top_samples_available&0x8000)){
for(i=0; i<4; i++){
int status= top[ h->intra4x4_pred_mode_cache[scan8[0] + i] ];
if(status<0){
av_log(h->s.avctx, AV_LOG_ERROR, "top block unavailable for requested intra4x4 mode %d at %d %d\n", status, s->mb_x, s->mb_y);
return -1;
} else if(status){
h->intra4x4_pred_mode_cache[scan8[0] + i]= status;
}
}
}
if((h->left_samples_available&0x8888)!=0x8888){
static const int mask[4]={0x8000,0x2000,0x80,0x20};
for(i=0; i<4; i++){
if(!(h->left_samples_available&mask[i])){
int status= left[ h->intra4x4_pred_mode_cache[scan8[0] + 8*i] ];
if(status<0){
av_log(h->s.avctx, AV_LOG_ERROR, "left block unavailable for requested intra4x4 mode %d at %d %d\n", status, s->mb_x, s->mb_y);
return -1;
} else if(status){
h->intra4x4_pred_mode_cache[scan8[0] + 8*i]= status;
}
}
}
}
return 0;
} //FIXME cleanup like ff_h264_check_intra_pred_mode
/**
* checks if the top & left blocks are available if needed & changes the dc mode so it only uses the available blocks.
*/
int ff_h264_check_intra_pred_mode(H264Context *h, int mode){
MpegEncContext * const s = &h->s;
static const int8_t top [7]= {LEFT_DC_PRED8x8, 1,-1,-1};
static const int8_t left[7]= { TOP_DC_PRED8x8,-1, 2,-1,DC_128_PRED8x8};
if(mode > 6U) {
av_log(h->s.avctx, AV_LOG_ERROR, "out of range intra chroma pred mode at %d %d\n", s->mb_x, s->mb_y);
return -1;
}
if(!(h->top_samples_available&0x8000)){
mode= top[ mode ];
if(mode<0){
av_log(h->s.avctx, AV_LOG_ERROR, "top block unavailable for requested intra mode at %d %d\n", s->mb_x, s->mb_y);
return -1;
}
}
if((h->left_samples_available&0x8080) != 0x8080){
mode= left[ mode ];
if(h->left_samples_available&0x8080){ //mad cow disease mode, aka MBAFF + constrained_intra_pred
mode= ALZHEIMER_DC_L0T_PRED8x8 + (!(h->left_samples_available&0x8000)) + 2*(mode == DC_128_PRED8x8);
}
if(mode<0){
av_log(h->s.avctx, AV_LOG_ERROR, "left block unavailable for requested intra mode at %d %d\n", s->mb_x, s->mb_y);
return -1;
}
}
return mode;
}
const uint8_t *ff_h264_decode_nal(H264Context *h, const uint8_t *src, int *dst_length, int *consumed, int length){
int i, si, di;
uint8_t *dst;
int bufidx;
// src[0]&0x80; //forbidden bit
h->nal_ref_idc= src[0]>>5;
h->nal_unit_type= src[0]&0x1F;
src++; length--;
#if HAVE_FAST_UNALIGNED
# if HAVE_FAST_64BIT
# define RS 7
for(i=0; i+1<length; i+=9){
if(!((~AV_RN64A(src+i) & (AV_RN64A(src+i) - 0x0100010001000101ULL)) & 0x8000800080008080ULL))
# else
# define RS 3
for(i=0; i+1<length; i+=5){
if(!((~AV_RN32A(src+i) & (AV_RN32A(src+i) - 0x01000101U)) & 0x80008080U))
# endif
continue;
if(i>0 && !src[i]) i--;
while(src[i]) i++;
#else
# define RS 0
for(i=0; i+1<length; i+=2){
if(src[i]) continue;
if(i>0 && src[i-1]==0) i--;
#endif
if(i+2<length && src[i+1]==0 && src[i+2]<=3){
if(src[i+2]!=3){
/* startcode, so we must be past the end */
length=i;
}
break;
}
i-= RS;
}
if(i>=length-1){ //no escaped 0
*dst_length= length;
*consumed= length+1; //+1 for the header
return src;
}
bufidx = h->nal_unit_type == NAL_DPC ? 1 : 0; // use second escape buffer for inter data
av_fast_malloc(&h->rbsp_buffer[bufidx], &h->rbsp_buffer_size[bufidx], length+FF_INPUT_BUFFER_PADDING_SIZE);
dst= h->rbsp_buffer[bufidx];
if (dst == NULL){
return NULL;
}
//printf("decoding esc\n");
memcpy(dst, src, i);
si=di=i;
while(si+2<length){
//remove escapes (very rare 1:2^22)
if(src[si+2]>3){
dst[di++]= src[si++];
dst[di++]= src[si++];
}else if(src[si]==0 && src[si+1]==0){
if(src[si+2]==3){ //escape
dst[di++]= 0;
dst[di++]= 0;
si+=3;
continue;
}else //next start code
goto nsc;
}
dst[di++]= src[si++];
}
while(si<length)
dst[di++]= src[si++];
nsc:
memset(dst+di, 0, FF_INPUT_BUFFER_PADDING_SIZE);
*dst_length= di;
*consumed= si + 1;//+1 for the header
//FIXME store exact number of bits in the getbitcontext (it is needed for decoding)
return dst;
}
/**
* Identify the exact end of the bitstream
* @return the length of the trailing, or 0 if damaged
*/
static int ff_h264_decode_rbsp_trailing(H264Context *h, const uint8_t *src){
int v= *src;
int r;
tprintf(h->s.avctx, "rbsp trailing %X\n", v);
for(r=1; r<9; r++){
if(v&1) return r;
v>>=1;
}
return 0;
}
static inline int get_lowest_part_list_y(H264Context *h, Picture *pic, int n, int height,
int y_offset, int list){
int raw_my= h->mv_cache[list][ scan8[n] ][1];
int filter_height= (raw_my&3) ? 2 : 0;
int full_my= (raw_my>>2) + y_offset;
int top = full_my - filter_height, bottom = full_my + height + filter_height;
return FFMAX(abs(top), bottom);
}
static inline void get_lowest_part_y(H264Context *h, int refs[2][48], int n, int height,
int y_offset, int list0, int list1, int *nrefs){
MpegEncContext * const s = &h->s;
int my;
y_offset += 16*(s->mb_y >> MB_FIELD);
if(list0){
int ref_n = h->ref_cache[0][ scan8[n] ];
Picture *ref= &h->ref_list[0][ref_n];
// Error resilience puts the current picture in the ref list.
// Don't try to wait on these as it will cause a deadlock.
// Fields can wait on each other, though.
if (ref->f.thread_opaque != s->current_picture.f.thread_opaque ||
(ref->f.reference & 3) != s->picture_structure) {
my = get_lowest_part_list_y(h, ref, n, height, y_offset, 0);
if (refs[0][ref_n] < 0) nrefs[0] += 1;
refs[0][ref_n] = FFMAX(refs[0][ref_n], my);
}
}
if(list1){
int ref_n = h->ref_cache[1][ scan8[n] ];
Picture *ref= &h->ref_list[1][ref_n];
if (ref->f.thread_opaque != s->current_picture.f.thread_opaque ||
(ref->f.reference & 3) != s->picture_structure) {
my = get_lowest_part_list_y(h, ref, n, height, y_offset, 1);
if (refs[1][ref_n] < 0) nrefs[1] += 1;
refs[1][ref_n] = FFMAX(refs[1][ref_n], my);
}
}
}
/**
* Wait until all reference frames are available for MC operations.
*
* @param h the H264 context
*/
static void await_references(H264Context *h){
MpegEncContext * const s = &h->s;
const int mb_xy= h->mb_xy;
const int mb_type = s->current_picture.f.mb_type[mb_xy];
int refs[2][48];
int nrefs[2] = {0};
int ref, list;
memset(refs, -1, sizeof(refs));
if(IS_16X16(mb_type)){
get_lowest_part_y(h, refs, 0, 16, 0,
IS_DIR(mb_type, 0, 0), IS_DIR(mb_type, 0, 1), nrefs);
}else if(IS_16X8(mb_type)){
get_lowest_part_y(h, refs, 0, 8, 0,
IS_DIR(mb_type, 0, 0), IS_DIR(mb_type, 0, 1), nrefs);
get_lowest_part_y(h, refs, 8, 8, 8,
IS_DIR(mb_type, 1, 0), IS_DIR(mb_type, 1, 1), nrefs);
}else if(IS_8X16(mb_type)){
get_lowest_part_y(h, refs, 0, 16, 0,
IS_DIR(mb_type, 0, 0), IS_DIR(mb_type, 0, 1), nrefs);
get_lowest_part_y(h, refs, 4, 16, 0,
IS_DIR(mb_type, 1, 0), IS_DIR(mb_type, 1, 1), nrefs);
}else{
int i;
assert(IS_8X8(mb_type));
for(i=0; i<4; i++){
const int sub_mb_type= h->sub_mb_type[i];
const int n= 4*i;
int y_offset= (i&2)<<2;
if(IS_SUB_8X8(sub_mb_type)){
get_lowest_part_y(h, refs, n , 8, y_offset,
IS_DIR(sub_mb_type, 0, 0), IS_DIR(sub_mb_type, 0, 1), nrefs);
}else if(IS_SUB_8X4(sub_mb_type)){
get_lowest_part_y(h, refs, n , 4, y_offset,
IS_DIR(sub_mb_type, 0, 0), IS_DIR(sub_mb_type, 0, 1), nrefs);
get_lowest_part_y(h, refs, n+2, 4, y_offset+4,
IS_DIR(sub_mb_type, 0, 0), IS_DIR(sub_mb_type, 0, 1), nrefs);
}else if(IS_SUB_4X8(sub_mb_type)){
get_lowest_part_y(h, refs, n , 8, y_offset,
IS_DIR(sub_mb_type, 0, 0), IS_DIR(sub_mb_type, 0, 1), nrefs);
get_lowest_part_y(h, refs, n+1, 8, y_offset,
IS_DIR(sub_mb_type, 0, 0), IS_DIR(sub_mb_type, 0, 1), nrefs);
}else{
int j;
assert(IS_SUB_4X4(sub_mb_type));
for(j=0; j<4; j++){
int sub_y_offset= y_offset + 2*(j&2);
get_lowest_part_y(h, refs, n+j, 4, sub_y_offset,
IS_DIR(sub_mb_type, 0, 0), IS_DIR(sub_mb_type, 0, 1), nrefs);
}
}
}
}
for(list=h->list_count-1; list>=0; list--){
for(ref=0; ref<48 && nrefs[list]; ref++){
int row = refs[list][ref];
if(row >= 0){
Picture *ref_pic = &h->ref_list[list][ref];
int ref_field = ref_pic->f.reference - 1;
int ref_field_picture = ref_pic->field_picture;
int pic_height = 16*s->mb_height >> ref_field_picture;
row <<= MB_MBAFF;
nrefs[list]--;
if(!FIELD_PICTURE && ref_field_picture){ // frame referencing two fields
ff_thread_await_progress((AVFrame*)ref_pic, FFMIN((row >> 1) - !(row&1), pic_height-1), 1);
ff_thread_await_progress((AVFrame*)ref_pic, FFMIN((row >> 1) , pic_height-1), 0);
}else if(FIELD_PICTURE && !ref_field_picture){ // field referencing one field of a frame
ff_thread_await_progress((AVFrame*)ref_pic, FFMIN(row*2 + ref_field , pic_height-1), 0);
}else if(FIELD_PICTURE){
ff_thread_await_progress((AVFrame*)ref_pic, FFMIN(row, pic_height-1), ref_field);
}else{
ff_thread_await_progress((AVFrame*)ref_pic, FFMIN(row, pic_height-1), 0);
}
}
}
}
}
#if 0
/**
* DCT transforms the 16 dc values.
* @param qp quantization parameter ??? FIXME
*/
static void h264_luma_dc_dct_c(DCTELEM *block/*, int qp*/){
// const int qmul= dequant_coeff[qp][0];
int i;
int temp[16]; //FIXME check if this is a good idea
static const int x_offset[4]={0, 1*stride, 4* stride, 5*stride};
static const int y_offset[4]={0, 2*stride, 8* stride, 10*stride};
for(i=0; i<4; i++){
const int offset= y_offset[i];
const int z0= block[offset+stride*0] + block[offset+stride*4];
const int z1= block[offset+stride*0] - block[offset+stride*4];
const int z2= block[offset+stride*1] - block[offset+stride*5];
const int z3= block[offset+stride*1] + block[offset+stride*5];
temp[4*i+0]= z0+z3;
temp[4*i+1]= z1+z2;
temp[4*i+2]= z1-z2;
temp[4*i+3]= z0-z3;
}
for(i=0; i<4; i++){
const int offset= x_offset[i];
const int z0= temp[4*0+i] + temp[4*2+i];
const int z1= temp[4*0+i] - temp[4*2+i];
const int z2= temp[4*1+i] - temp[4*3+i];
const int z3= temp[4*1+i] + temp[4*3+i];
block[stride*0 +offset]= (z0 + z3)>>1;
block[stride*2 +offset]= (z1 + z2)>>1;
block[stride*8 +offset]= (z1 - z2)>>1;
block[stride*10+offset]= (z0 - z3)>>1;
}
}
#endif
#undef xStride
#undef stride
#if 0
static void chroma_dc_dct_c(DCTELEM *block){
const int stride= 16*2;
const int xStride= 16;
int a,b,c,d,e;
a= block[stride*0 + xStride*0];
b= block[stride*0 + xStride*1];
c= block[stride*1 + xStride*0];
d= block[stride*1 + xStride*1];
e= a-b;
a= a+b;
b= c-d;
c= c+d;
block[stride*0 + xStride*0]= (a+c);
block[stride*0 + xStride*1]= (e+b);
block[stride*1 + xStride*0]= (a-c);
block[stride*1 + xStride*1]= (e-b);
}
#endif
static inline void mc_dir_part(H264Context *h, Picture *pic, int n, int square, int chroma_height, int delta, int list,
uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr,
int src_x_offset, int src_y_offset,
qpel_mc_func *qpix_op, h264_chroma_mc_func chroma_op,
int pixel_shift, int chroma444){
MpegEncContext * const s = &h->s;
const int mx= h->mv_cache[list][ scan8[n] ][0] + src_x_offset*8;
int my= h->mv_cache[list][ scan8[n] ][1] + src_y_offset*8;
const int luma_xy= (mx&3) + ((my&3)<<2);
int offset = ((mx>>2) << pixel_shift) + (my>>2)*h->mb_linesize;
uint8_t * src_y = pic->f.data[0] + offset;
uint8_t * src_cb, * src_cr;
int extra_width= h->emu_edge_width;
int extra_height= h->emu_edge_height;
int emu=0;
const int full_mx= mx>>2;
const int full_my= my>>2;
const int pic_width = 16*s->mb_width;
const int pic_height = 16*s->mb_height >> MB_FIELD;
if(mx&7) extra_width -= 3;
if(my&7) extra_height -= 3;
if( full_mx < 0-extra_width
|| full_my < 0-extra_height
|| full_mx + 16/*FIXME*/ > pic_width + extra_width
|| full_my + 16/*FIXME*/ > pic_height + extra_height){
s->dsp.emulated_edge_mc(s->edge_emu_buffer, src_y - (2 << pixel_shift) - 2*h->mb_linesize, h->mb_linesize, 16+5, 16+5/*FIXME*/, full_mx-2, full_my-2, pic_width, pic_height);
src_y= s->edge_emu_buffer + (2 << pixel_shift) + 2*h->mb_linesize;
emu=1;
}
qpix_op[luma_xy](dest_y, src_y, h->mb_linesize); //FIXME try variable height perhaps?
if(!square){
qpix_op[luma_xy](dest_y + delta, src_y + delta, h->mb_linesize);
}
if(CONFIG_GRAY && s->flags&CODEC_FLAG_GRAY) return;
if(chroma444){
src_cb = pic->f.data[1] + offset;
if(emu){
s->dsp.emulated_edge_mc(s->edge_emu_buffer, src_cb - (2 << pixel_shift) - 2*h->mb_linesize, h->mb_linesize,
16+5, 16+5/*FIXME*/, full_mx-2, full_my-2, pic_width, pic_height);
src_cb= s->edge_emu_buffer + (2 << pixel_shift) + 2*h->mb_linesize;
}
qpix_op[luma_xy](dest_cb, src_cb, h->mb_linesize); //FIXME try variable height perhaps?
if(!square){
qpix_op[luma_xy](dest_cb + delta, src_cb + delta, h->mb_linesize);
}
src_cr = pic->f.data[2] + offset;
if(emu){
s->dsp.emulated_edge_mc(s->edge_emu_buffer, src_cr - (2 << pixel_shift) - 2*h->mb_linesize, h->mb_linesize,
16+5, 16+5/*FIXME*/, full_mx-2, full_my-2, pic_width, pic_height);
src_cr= s->edge_emu_buffer + (2 << pixel_shift) + 2*h->mb_linesize;
}
qpix_op[luma_xy](dest_cr, src_cr, h->mb_linesize); //FIXME try variable height perhaps?
if(!square){
qpix_op[luma_xy](dest_cr + delta, src_cr + delta, h->mb_linesize);
}
return;
}
if(MB_FIELD){
// chroma offset when predicting from a field of opposite parity
my += 2 * ((s->mb_y & 1) - (pic->f.reference - 1));
emu |= (my>>3) < 0 || (my>>3) + 8 >= (pic_height>>1);
}
src_cb = pic->f.data[1] + ((mx >> 3) << pixel_shift) + (my >> 3) * h->mb_uvlinesize;
src_cr = pic->f.data[2] + ((mx >> 3) << pixel_shift) + (my >> 3) * h->mb_uvlinesize;
if(emu){
s->dsp.emulated_edge_mc(s->edge_emu_buffer, src_cb, h->mb_uvlinesize, 9, 9/*FIXME*/, (mx>>3), (my>>3), pic_width>>1, pic_height>>1);
src_cb= s->edge_emu_buffer;
}
chroma_op(dest_cb, src_cb, h->mb_uvlinesize, chroma_height, mx&7, my&7);
if(emu){
s->dsp.emulated_edge_mc(s->edge_emu_buffer, src_cr, h->mb_uvlinesize, 9, 9/*FIXME*/, (mx>>3), (my>>3), pic_width>>1, pic_height>>1);
src_cr= s->edge_emu_buffer;
}
chroma_op(dest_cr, src_cr, h->mb_uvlinesize, chroma_height, mx&7, my&7);
}
static inline void mc_part_std(H264Context *h, int n, int square, int chroma_height, int delta,
uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr,
int x_offset, int y_offset,
qpel_mc_func *qpix_put, h264_chroma_mc_func chroma_put,
qpel_mc_func *qpix_avg, h264_chroma_mc_func chroma_avg,
int list0, int list1, int pixel_shift, int chroma444){
MpegEncContext * const s = &h->s;
qpel_mc_func *qpix_op= qpix_put;
h264_chroma_mc_func chroma_op= chroma_put;
dest_y += (2*x_offset << pixel_shift) + 2*y_offset*h->mb_linesize;
if(chroma444){
dest_cb += (2*x_offset << pixel_shift) + 2*y_offset*h->mb_linesize;
dest_cr += (2*x_offset << pixel_shift) + 2*y_offset*h->mb_linesize;
}else{
dest_cb += ( x_offset << pixel_shift) + y_offset*h->mb_uvlinesize;
dest_cr += ( x_offset << pixel_shift) + y_offset*h->mb_uvlinesize;
}
x_offset += 8*s->mb_x;
y_offset += 8*(s->mb_y >> MB_FIELD);
if(list0){
Picture *ref= &h->ref_list[0][ h->ref_cache[0][ scan8[n] ] ];
mc_dir_part(h, ref, n, square, chroma_height, delta, 0,
dest_y, dest_cb, dest_cr, x_offset, y_offset,
qpix_op, chroma_op, pixel_shift, chroma444);
qpix_op= qpix_avg;
chroma_op= chroma_avg;
}
if(list1){
Picture *ref= &h->ref_list[1][ h->ref_cache[1][ scan8[n] ] ];
mc_dir_part(h, ref, n, square, chroma_height, delta, 1,
dest_y, dest_cb, dest_cr, x_offset, y_offset,
qpix_op, chroma_op, pixel_shift, chroma444);
}
}
static inline void mc_part_weighted(H264Context *h, int n, int square, int chroma_height, int delta,
uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr,
int x_offset, int y_offset,
qpel_mc_func *qpix_put, h264_chroma_mc_func chroma_put,
h264_weight_func luma_weight_op, h264_weight_func chroma_weight_op,
h264_biweight_func luma_weight_avg, h264_biweight_func chroma_weight_avg,
int list0, int list1, int pixel_shift, int chroma444){
MpegEncContext * const s = &h->s;
dest_y += (2*x_offset << pixel_shift) + 2*y_offset*h->mb_linesize;
if(chroma444){
chroma_weight_avg = luma_weight_avg;
chroma_weight_op = luma_weight_op;
dest_cb += (2*x_offset << pixel_shift) + 2*y_offset*h->mb_linesize;
dest_cr += (2*x_offset << pixel_shift) + 2*y_offset*h->mb_linesize;
}else{
dest_cb += ( x_offset << pixel_shift) + y_offset*h->mb_uvlinesize;
dest_cr += ( x_offset << pixel_shift) + y_offset*h->mb_uvlinesize;
}
x_offset += 8*s->mb_x;
y_offset += 8*(s->mb_y >> MB_FIELD);
if(list0 && list1){
/* don't optimize for luma-only case, since B-frames usually
* use implicit weights => chroma too. */
uint8_t *tmp_cb = s->obmc_scratchpad;
uint8_t *tmp_cr = s->obmc_scratchpad + (16 << pixel_shift);
uint8_t *tmp_y = s->obmc_scratchpad + 16*h->mb_uvlinesize;
int refn0 = h->ref_cache[0][ scan8[n] ];
int refn1 = h->ref_cache[1][ scan8[n] ];
mc_dir_part(h, &h->ref_list[0][refn0], n, square, chroma_height, delta, 0,
dest_y, dest_cb, dest_cr,
x_offset, y_offset, qpix_put, chroma_put, pixel_shift, chroma444);
mc_dir_part(h, &h->ref_list[1][refn1], n, square, chroma_height, delta, 1,
tmp_y, tmp_cb, tmp_cr,
x_offset, y_offset, qpix_put, chroma_put, pixel_shift, chroma444);
if(h->use_weight == 2){
int weight0 = h->implicit_weight[refn0][refn1][s->mb_y&1];
int weight1 = 64 - weight0;
luma_weight_avg( dest_y, tmp_y, h-> mb_linesize, 5, weight0, weight1, 0);
chroma_weight_avg(dest_cb, tmp_cb, h->mb_uvlinesize, 5, weight0, weight1, 0);
chroma_weight_avg(dest_cr, tmp_cr, h->mb_uvlinesize, 5, weight0, weight1, 0);
}else{
luma_weight_avg(dest_y, tmp_y, h->mb_linesize, h->luma_log2_weight_denom,
h->luma_weight[refn0][0][0] , h->luma_weight[refn1][1][0],
h->luma_weight[refn0][0][1] + h->luma_weight[refn1][1][1]);
chroma_weight_avg(dest_cb, tmp_cb, h->mb_uvlinesize, h->chroma_log2_weight_denom,
h->chroma_weight[refn0][0][0][0] , h->chroma_weight[refn1][1][0][0],
h->chroma_weight[refn0][0][0][1] + h->chroma_weight[refn1][1][0][1]);
chroma_weight_avg(dest_cr, tmp_cr, h->mb_uvlinesize, h->chroma_log2_weight_denom,
h->chroma_weight[refn0][0][1][0] , h->chroma_weight[refn1][1][1][0],
h->chroma_weight[refn0][0][1][1] + h->chroma_weight[refn1][1][1][1]);
}
}else{
int list = list1 ? 1 : 0;
int refn = h->ref_cache[list][ scan8[n] ];
Picture *ref= &h->ref_list[list][refn];
mc_dir_part(h, ref, n, square, chroma_height, delta, list,
dest_y, dest_cb, dest_cr, x_offset, y_offset,
qpix_put, chroma_put, pixel_shift, chroma444);
luma_weight_op(dest_y, h->mb_linesize, h->luma_log2_weight_denom,
h->luma_weight[refn][list][0], h->luma_weight[refn][list][1]);
if(h->use_weight_chroma){
chroma_weight_op(dest_cb, h->mb_uvlinesize, h->chroma_log2_weight_denom,
h->chroma_weight[refn][list][0][0], h->chroma_weight[refn][list][0][1]);
chroma_weight_op(dest_cr, h->mb_uvlinesize, h->chroma_log2_weight_denom,
h->chroma_weight[refn][list][1][0], h->chroma_weight[refn][list][1][1]);
}
}
}
static inline void mc_part(H264Context *h, int n, int square, int chroma_height, int delta,
uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr,
int x_offset, int y_offset,
qpel_mc_func *qpix_put, h264_chroma_mc_func chroma_put,
qpel_mc_func *qpix_avg, h264_chroma_mc_func chroma_avg,
h264_weight_func *weight_op, h264_biweight_func *weight_avg,
int list0, int list1, int pixel_shift, int chroma444){
if((h->use_weight==2 && list0 && list1
&& (h->implicit_weight[ h->ref_cache[0][scan8[n]] ][ h->ref_cache[1][scan8[n]] ][h->s.mb_y&1] != 32))
|| h->use_weight==1)
mc_part_weighted(h, n, square, chroma_height, delta, dest_y, dest_cb, dest_cr,
x_offset, y_offset, qpix_put, chroma_put,
weight_op[0], weight_op[3], weight_avg[0],
weight_avg[3], list0, list1, pixel_shift, chroma444);
else
mc_part_std(h, n, square, chroma_height, delta, dest_y, dest_cb, dest_cr,
x_offset, y_offset, qpix_put, chroma_put, qpix_avg,
chroma_avg, list0, list1, pixel_shift, chroma444);
}
static inline void prefetch_motion(H264Context *h, int list, int pixel_shift, int chroma444){
/* fetch pixels for estimated mv 4 macroblocks ahead
* optimized for 64byte cache lines */
MpegEncContext * const s = &h->s;
const int refn = h->ref_cache[list][scan8[0]];
if(refn >= 0){
const int mx= (h->mv_cache[list][scan8[0]][0]>>2) + 16*s->mb_x + 8;
const int my= (h->mv_cache[list][scan8[0]][1]>>2) + 16*s->mb_y;
uint8_t **src = h->ref_list[list][refn].f.data;
int off= (mx << pixel_shift) + (my + (s->mb_x&3)*4)*h->mb_linesize + (64 << pixel_shift);
s->dsp.prefetch(src[0]+off, s->linesize, 4);
if(chroma444){
s->dsp.prefetch(src[1]+off, s->linesize, 4);
s->dsp.prefetch(src[2]+off, s->linesize, 4);
}else{
off= (((mx>>1)+64)<<pixel_shift) + ((my>>1) + (s->mb_x&7))*s->uvlinesize;
s->dsp.prefetch(src[1]+off, src[2]-src[1], 2);
}
}
}
static av_always_inline void hl_motion(H264Context *h, uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr,
qpel_mc_func (*qpix_put)[16], h264_chroma_mc_func (*chroma_put),
qpel_mc_func (*qpix_avg)[16], h264_chroma_mc_func (*chroma_avg),
h264_weight_func *weight_op, h264_biweight_func *weight_avg,
int pixel_shift, int chroma444){
MpegEncContext * const s = &h->s;
const int mb_xy= h->mb_xy;
const int mb_type = s->current_picture.f.mb_type[mb_xy];
assert(IS_INTER(mb_type));
if(HAVE_PTHREADS && (s->avctx->active_thread_type & FF_THREAD_FRAME))
await_references(h);
prefetch_motion(h, 0, pixel_shift, chroma444);
if(IS_16X16(mb_type)){
mc_part(h, 0, 1, 8, 0, dest_y, dest_cb, dest_cr, 0, 0,
qpix_put[0], chroma_put[0], qpix_avg[0], chroma_avg[0],
weight_op, weight_avg,
IS_DIR(mb_type, 0, 0), IS_DIR(mb_type, 0, 1),
pixel_shift, chroma444);
}else if(IS_16X8(mb_type)){
mc_part(h, 0, 0, 4, 8 << pixel_shift, dest_y, dest_cb, dest_cr, 0, 0,
qpix_put[1], chroma_put[0], qpix_avg[1], chroma_avg[0],
&weight_op[1], &weight_avg[1],
IS_DIR(mb_type, 0, 0), IS_DIR(mb_type, 0, 1),
pixel_shift, chroma444);
mc_part(h, 8, 0, 4, 8 << pixel_shift, dest_y, dest_cb, dest_cr, 0, 4,
qpix_put[1], chroma_put[0], qpix_avg[1], chroma_avg[0],
&weight_op[1], &weight_avg[1],
IS_DIR(mb_type, 1, 0), IS_DIR(mb_type, 1, 1),
pixel_shift, chroma444);
}else if(IS_8X16(mb_type)){
mc_part(h, 0, 0, 8, 8*h->mb_linesize, dest_y, dest_cb, dest_cr, 0, 0,
qpix_put[1], chroma_put[1], qpix_avg[1], chroma_avg[1],
&weight_op[2], &weight_avg[2],
IS_DIR(mb_type, 0, 0), IS_DIR(mb_type, 0, 1),
pixel_shift, chroma444);
mc_part(h, 4, 0, 8, 8*h->mb_linesize, dest_y, dest_cb, dest_cr, 4, 0,
qpix_put[1], chroma_put[1], qpix_avg[1], chroma_avg[1],
&weight_op[2], &weight_avg[2],
IS_DIR(mb_type, 1, 0), IS_DIR(mb_type, 1, 1),
pixel_shift, chroma444);
}else{
int i;
assert(IS_8X8(mb_type));
for(i=0; i<4; i++){
const int sub_mb_type= h->sub_mb_type[i];
const int n= 4*i;
int x_offset= (i&1)<<2;
int y_offset= (i&2)<<1;
if(IS_SUB_8X8(sub_mb_type)){
mc_part(h, n, 1, 4, 0, dest_y, dest_cb, dest_cr, x_offset, y_offset,
qpix_put[1], chroma_put[1], qpix_avg[1], chroma_avg[1],
&weight_op[3], &weight_avg[3],
IS_DIR(sub_mb_type, 0, 0), IS_DIR(sub_mb_type, 0, 1),
pixel_shift, chroma444);
}else if(IS_SUB_8X4(sub_mb_type)){
mc_part(h, n , 0, 2, 4 << pixel_shift, dest_y, dest_cb, dest_cr, x_offset, y_offset,
qpix_put[2], chroma_put[1], qpix_avg[2], chroma_avg[1],
&weight_op[4], &weight_avg[4],
IS_DIR(sub_mb_type, 0, 0), IS_DIR(sub_mb_type, 0, 1),
pixel_shift, chroma444);
mc_part(h, n+2, 0, 2, 4 << pixel_shift, dest_y, dest_cb, dest_cr, x_offset, y_offset+2,
qpix_put[2], chroma_put[1], qpix_avg[2], chroma_avg[1],
&weight_op[4], &weight_avg[4],
IS_DIR(sub_mb_type, 0, 0), IS_DIR(sub_mb_type, 0, 1),
pixel_shift, chroma444);
}else if(IS_SUB_4X8(sub_mb_type)){
mc_part(h, n , 0, 4, 4*h->mb_linesize, dest_y, dest_cb, dest_cr, x_offset, y_offset,
qpix_put[2], chroma_put[2], qpix_avg[2], chroma_avg[2],
&weight_op[5], &weight_avg[5],
IS_DIR(sub_mb_type, 0, 0), IS_DIR(sub_mb_type, 0, 1),
pixel_shift, chroma444);
mc_part(h, n+1, 0, 4, 4*h->mb_linesize, dest_y, dest_cb, dest_cr, x_offset+2, y_offset,
qpix_put[2], chroma_put[2], qpix_avg[2], chroma_avg[2],
&weight_op[5], &weight_avg[5],
IS_DIR(sub_mb_type, 0, 0), IS_DIR(sub_mb_type, 0, 1),
pixel_shift, chroma444);
}else{
int j;
assert(IS_SUB_4X4(sub_mb_type));
for(j=0; j<4; j++){
int sub_x_offset= x_offset + 2*(j&1);
int sub_y_offset= y_offset + (j&2);
mc_part(h, n+j, 1, 2, 0, dest_y, dest_cb, dest_cr, sub_x_offset, sub_y_offset,
qpix_put[2], chroma_put[2], qpix_avg[2], chroma_avg[2],
&weight_op[6], &weight_avg[6],
IS_DIR(sub_mb_type, 0, 0), IS_DIR(sub_mb_type, 0, 1),
pixel_shift, chroma444);
}
}
}
}
prefetch_motion(h, 1, pixel_shift, chroma444);
}
static void free_tables(H264Context *h, int free_rbsp){
int i;
H264Context *hx;
av_freep(&h->intra4x4_pred_mode);
av_freep(&h->chroma_pred_mode_table);
av_freep(&h->cbp_table);
av_freep(&h->mvd_table[0]);
av_freep(&h->mvd_table[1]);
av_freep(&h->direct_table);
av_freep(&h->non_zero_count);
av_freep(&h->slice_table_base);
h->slice_table= NULL;
av_freep(&h->list_counts);
av_freep(&h->mb2b_xy);
av_freep(&h->mb2br_xy);
for(i = 0; i < MAX_THREADS; i++) {
hx = h->thread_context[i];
if(!hx) continue;
av_freep(&hx->top_borders[1]);
av_freep(&hx->top_borders[0]);
av_freep(&hx->s.obmc_scratchpad);
if (free_rbsp){
av_freep(&hx->rbsp_buffer[1]);
av_freep(&hx->rbsp_buffer[0]);
hx->rbsp_buffer_size[0] = 0;
hx->rbsp_buffer_size[1] = 0;
}
if (i) av_freep(&h->thread_context[i]);
}
}
static void init_dequant8_coeff_table(H264Context *h){
int i,j,q,x;
const int max_qp = 51 + 6*(h->sps.bit_depth_luma-8);
for(i=0; i<6; i++ ){
h->dequant8_coeff[i] = h->dequant8_buffer[i];
for(j=0; j<i; j++){
if(!memcmp(h->pps.scaling_matrix8[j], h->pps.scaling_matrix8[i], 64*sizeof(uint8_t))){
h->dequant8_coeff[i] = h->dequant8_buffer[j];
break;
}
}
if(j<i)
continue;
for(q=0; q<max_qp+1; q++){
int shift = div6[q];
int idx = rem6[q];
for(x=0; x<64; x++)
h->dequant8_coeff[i][q][(x>>3)|((x&7)<<3)] =
((uint32_t)dequant8_coeff_init[idx][ dequant8_coeff_init_scan[((x>>1)&12) | (x&3)] ] *
h->pps.scaling_matrix8[i][x]) << shift;
}
}
}
static void init_dequant4_coeff_table(H264Context *h){
int i,j,q,x;
const int max_qp = 51 + 6*(h->sps.bit_depth_luma-8);
for(i=0; i<6; i++ ){
h->dequant4_coeff[i] = h->dequant4_buffer[i];
for(j=0; j<i; j++){
if(!memcmp(h->pps.scaling_matrix4[j], h->pps.scaling_matrix4[i], 16*sizeof(uint8_t))){
h->dequant4_coeff[i] = h->dequant4_buffer[j];
break;
}
}
if(j<i)
continue;
for(q=0; q<max_qp+1; q++){
int shift = div6[q] + 2;
int idx = rem6[q];
for(x=0; x<16; x++)
h->dequant4_coeff[i][q][(x>>2)|((x<<2)&0xF)] =
((uint32_t)dequant4_coeff_init[idx][(x&1) + ((x>>2)&1)] *
h->pps.scaling_matrix4[i][x]) << shift;
}
}
}
static void init_dequant_tables(H264Context *h){
int i,x;
init_dequant4_coeff_table(h);
if(h->pps.transform_8x8_mode)
init_dequant8_coeff_table(h);
if(h->sps.transform_bypass){
for(i=0; i<6; i++)
for(x=0; x<16; x++)
h->dequant4_coeff[i][0][x] = 1<<6;
if(h->pps.transform_8x8_mode)
for(i=0; i<6; i++)
for(x=0; x<64; x++)
h->dequant8_coeff[i][0][x] = 1<<6;
}
}
int ff_h264_alloc_tables(H264Context *h){
MpegEncContext * const s = &h->s;
const int big_mb_num= s->mb_stride * (s->mb_height+1);
const int row_mb_num= 2*s->mb_stride*s->avctx->thread_count;
int x,y;
FF_ALLOCZ_OR_GOTO(h->s.avctx, h->intra4x4_pred_mode, row_mb_num * 8 * sizeof(uint8_t), fail)
FF_ALLOCZ_OR_GOTO(h->s.avctx, h->non_zero_count , big_mb_num * 48 * sizeof(uint8_t), fail)
FF_ALLOCZ_OR_GOTO(h->s.avctx, h->slice_table_base , (big_mb_num+s->mb_stride) * sizeof(*h->slice_table_base), fail)
FF_ALLOCZ_OR_GOTO(h->s.avctx, h->cbp_table, big_mb_num * sizeof(uint16_t), fail)
FF_ALLOCZ_OR_GOTO(h->s.avctx, h->chroma_pred_mode_table, big_mb_num * sizeof(uint8_t), fail)
FF_ALLOCZ_OR_GOTO(h->s.avctx, h->mvd_table[0], 16*row_mb_num * sizeof(uint8_t), fail);
FF_ALLOCZ_OR_GOTO(h->s.avctx, h->mvd_table[1], 16*row_mb_num * sizeof(uint8_t), fail);
FF_ALLOCZ_OR_GOTO(h->s.avctx, h->direct_table, 4*big_mb_num * sizeof(uint8_t) , fail);
FF_ALLOCZ_OR_GOTO(h->s.avctx, h->list_counts, big_mb_num * sizeof(uint8_t), fail)
memset(h->slice_table_base, -1, (big_mb_num+s->mb_stride) * sizeof(*h->slice_table_base));
h->slice_table= h->slice_table_base + s->mb_stride*2 + 1;
FF_ALLOCZ_OR_GOTO(h->s.avctx, h->mb2b_xy , big_mb_num * sizeof(uint32_t), fail);
FF_ALLOCZ_OR_GOTO(h->s.avctx, h->mb2br_xy , big_mb_num * sizeof(uint32_t), fail);
for(y=0; y<s->mb_height; y++){
for(x=0; x<s->mb_width; x++){
const int mb_xy= x + y*s->mb_stride;
const int b_xy = 4*x + 4*y*h->b_stride;
h->mb2b_xy [mb_xy]= b_xy;
h->mb2br_xy[mb_xy]= 8*(FMO ? mb_xy : (mb_xy % (2*s->mb_stride)));
}
}
s->obmc_scratchpad = NULL;
if(!h->dequant4_coeff[0])
init_dequant_tables(h);
return 0;
fail:
free_tables(h, 1);
return -1;
}
/**
* Mimic alloc_tables(), but for every context thread.
*/
static void clone_tables(H264Context *dst, H264Context *src, int i){
MpegEncContext * const s = &src->s;
dst->intra4x4_pred_mode = src->intra4x4_pred_mode + i*8*2*s->mb_stride;
dst->non_zero_count = src->non_zero_count;
dst->slice_table = src->slice_table;
dst->cbp_table = src->cbp_table;
dst->mb2b_xy = src->mb2b_xy;
dst->mb2br_xy = src->mb2br_xy;
dst->chroma_pred_mode_table = src->chroma_pred_mode_table;
dst->mvd_table[0] = src->mvd_table[0] + i*8*2*s->mb_stride;
dst->mvd_table[1] = src->mvd_table[1] + i*8*2*s->mb_stride;
dst->direct_table = src->direct_table;
dst->list_counts = src->list_counts;
dst->s.obmc_scratchpad = NULL;
ff_h264_pred_init(&dst->hpc, src->s.codec_id, src->sps.bit_depth_luma);
}
/**
* Init context
* Allocate buffers which are not shared amongst multiple threads.
*/
static int context_init(H264Context *h){
FF_ALLOCZ_OR_GOTO(h->s.avctx, h->top_borders[0], h->s.mb_width * 16*3 * sizeof(uint8_t)*2, fail)
FF_ALLOCZ_OR_GOTO(h->s.avctx, h->top_borders[1], h->s.mb_width * 16*3 * sizeof(uint8_t)*2, fail)
h->ref_cache[0][scan8[5 ]+1] = h->ref_cache[0][scan8[7 ]+1] = h->ref_cache[0][scan8[13]+1] =
h->ref_cache[1][scan8[5 ]+1] = h->ref_cache[1][scan8[7 ]+1] = h->ref_cache[1][scan8[13]+1] = PART_NOT_AVAILABLE;
return 0;
fail:
return -1; // free_tables will clean up for us
}
static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size);
static av_cold void common_init(H264Context *h){
MpegEncContext * const s = &h->s;
s->width = s->avctx->width;
s->height = s->avctx->height;
s->codec_id= s->avctx->codec->id;
ff_h264dsp_init(&h->h264dsp, 8);
ff_h264_pred_init(&h->hpc, s->codec_id, 8);
h->dequant_coeff_pps= -1;
s->unrestricted_mv=1;
s->decode=1; //FIXME
dsputil_init(&s->dsp, s->avctx); // needed so that idct permutation is known early
memset(h->pps.scaling_matrix4, 16, 6*16*sizeof(uint8_t));
memset(h->pps.scaling_matrix8, 16, 2*64*sizeof(uint8_t));
}
int ff_h264_decode_extradata(H264Context *h)
{
AVCodecContext *avctx = h->s.avctx;
if(avctx->extradata[0] == 1){
int i, cnt, nalsize, size_left;
unsigned char *p = avctx->extradata;
size_left = avctx->extradata_size;
h->is_avc = 1;
if(size_left < 7) {
av_log(avctx, AV_LOG_ERROR, "avcC too short\n");
return -1;
}
/* sps and pps in the avcC always have length coded with 2 bytes,
so put a fake nal_length_size = 2 while parsing them */
h->nal_length_size = 2;
// Decode sps from avcC
cnt = *(p+5) & 0x1f; // Number of sps
p += 6;
size_left -= 6;
for (i = 0; i < cnt; i++) {
if (size_left < 2) {
av_log(avctx, AV_LOG_ERROR, "Cannot read sps nalsize\n");
return -1;
}
nalsize = AV_RB16(p) + 2;
if (size_left < nalsize) {
av_log(avctx, AV_LOG_ERROR, "sps nalsize too big\n");
return -1;
}
if(decode_nal_units(h, p, nalsize) < 0) {
av_log(avctx, AV_LOG_ERROR, "Decoding sps %d from avcC failed\n", i);
return -1;
}
p += nalsize;
size_left -= nalsize;
}
// Decode pps from avcC
if(!size_left) {
av_log(avctx, AV_LOG_ERROR, "Cannot read pps count\n");
return -1;
}
cnt = *(p++); // Number of pps
--size_left;
for (i = 0; i < cnt; i++) {
if (size_left < 2) {
av_log(avctx, AV_LOG_ERROR, "Cannot read pps nalsize\n");
return -1;
}
nalsize = AV_RB16(p) + 2;
if (size_left < nalsize) {
av_log(avctx, AV_LOG_ERROR, "pps nalsize too big\n");
return -1;
}
if (decode_nal_units(h, p, nalsize) < 0) {
av_log(avctx, AV_LOG_ERROR, "Decoding pps %d from avcC failed\n", i);
return -1;
}
p += nalsize;
size_left -= nalsize;
}
// Now store right nal length size, that will be use to parse all other nals
h->nal_length_size = (avctx->extradata[4] & 0x03) + 1;
} else {
h->is_avc = 0;
if(decode_nal_units(h, avctx->extradata, avctx->extradata_size) < 0)
return -1;
}
return 0;
}
av_cold int ff_h264_decode_init(AVCodecContext *avctx){
H264Context *h= avctx->priv_data;
MpegEncContext * const s = &h->s;
MPV_decode_defaults(s);
s->avctx = avctx;
common_init(h);
s->out_format = FMT_H264;
s->workaround_bugs= avctx->workaround_bugs;
// set defaults
// s->decode_mb= ff_h263_decode_mb;
s->quarter_sample = 1;
if(!avctx->has_b_frames)
s->low_delay= 1;
avctx->chroma_sample_location = AVCHROMA_LOC_LEFT;
ff_h264_decode_init_vlc();
h->pixel_shift = 0;
h->sps.bit_depth_luma = avctx->bits_per_raw_sample = 8;
h->thread_context[0] = h;
h->outputed_poc = h->next_outputed_poc = INT_MIN;
h->prev_poc_msb= 1<<16;
h->x264_build = -1;
ff_h264_reset_sei(h);
if(avctx->codec_id == CODEC_ID_H264){
if(avctx->ticks_per_frame == 1){
s->avctx->time_base.den *=2;
}
avctx->ticks_per_frame = 2;
}
if(avctx->extradata_size > 0 && avctx->extradata &&
ff_h264_decode_extradata(h))
return -1;
if(h->sps.bitstream_restriction_flag && s->avctx->has_b_frames < h->sps.num_reorder_frames){
s->avctx->has_b_frames = h->sps.num_reorder_frames;
s->low_delay = 0;
}
return 0;
}
#define IN_RANGE(a, b, size) (((a) >= (b)) && ((a) < ((b)+(size))))
static void copy_picture_range(Picture **to, Picture **from, int count, MpegEncContext *new_base, MpegEncContext *old_base)
{
int i;
for (i=0; i<count; i++){
assert((IN_RANGE(from[i], old_base, sizeof(*old_base)) ||
IN_RANGE(from[i], old_base->picture, sizeof(Picture) * old_base->picture_count) ||
!from[i]));
to[i] = REBASE_PICTURE(from[i], new_base, old_base);
}
}
static void copy_parameter_set(void **to, void **from, int count, int size)
{
int i;
for (i=0; i<count; i++){
if (to[i] && !from[i]) av_freep(&to[i]);
else if (from[i] && !to[i]) to[i] = av_malloc(size);
if (from[i]) memcpy(to[i], from[i], size);
}
}
static int decode_init_thread_copy(AVCodecContext *avctx){
H264Context *h= avctx->priv_data;
if (!avctx->is_copy) return 0;
memset(h->sps_buffers, 0, sizeof(h->sps_buffers));
memset(h->pps_buffers, 0, sizeof(h->pps_buffers));
return 0;
}
#define copy_fields(to, from, start_field, end_field) memcpy(&to->start_field, &from->start_field, (char*)&to->end_field - (char*)&to->start_field)
static int decode_update_thread_context(AVCodecContext *dst, const AVCodecContext *src){
H264Context *h= dst->priv_data, *h1= src->priv_data;
MpegEncContext * const s = &h->s, * const s1 = &h1->s;
int inited = s->context_initialized, err;
int i;
if(dst == src || !s1->context_initialized) return 0;
err = ff_mpeg_update_thread_context(dst, src);
if(err) return err;
//FIXME handle width/height changing
if(!inited){
for(i = 0; i < MAX_SPS_COUNT; i++)
av_freep(h->sps_buffers + i);
for(i = 0; i < MAX_PPS_COUNT; i++)
av_freep(h->pps_buffers + i);
memcpy(&h->s + 1, &h1->s + 1, sizeof(H264Context) - sizeof(MpegEncContext)); //copy all fields after MpegEnc
memset(h->sps_buffers, 0, sizeof(h->sps_buffers));
memset(h->pps_buffers, 0, sizeof(h->pps_buffers));
ff_h264_alloc_tables(h);
context_init(h);
for(i=0; i<2; i++){
h->rbsp_buffer[i] = NULL;
h->rbsp_buffer_size[i] = 0;
}
h->thread_context[0] = h;
// frame_start may not be called for the next thread (if it's decoding a bottom field)
// so this has to be allocated here
h->s.obmc_scratchpad = av_malloc(16*6*s->linesize);
s->dsp.clear_blocks(h->mb);
s->dsp.clear_blocks(h->mb+(24*16<<h->pixel_shift));
}
//extradata/NAL handling
h->is_avc = h1->is_avc;
//SPS/PPS
copy_parameter_set((void**)h->sps_buffers, (void**)h1->sps_buffers, MAX_SPS_COUNT, sizeof(SPS));
h->sps = h1->sps;
copy_parameter_set((void**)h->pps_buffers, (void**)h1->pps_buffers, MAX_PPS_COUNT, sizeof(PPS));
h->pps = h1->pps;
//Dequantization matrices
//FIXME these are big - can they be only copied when PPS changes?
copy_fields(h, h1, dequant4_buffer, dequant4_coeff);
for(i=0; i<6; i++)
h->dequant4_coeff[i] = h->dequant4_buffer[0] + (h1->dequant4_coeff[i] - h1->dequant4_buffer[0]);
for(i=0; i<6; i++)
h->dequant8_coeff[i] = h->dequant8_buffer[0] + (h1->dequant8_coeff[i] - h1->dequant8_buffer[0]);
h->dequant_coeff_pps = h1->dequant_coeff_pps;
//POC timing
copy_fields(h, h1, poc_lsb, redundant_pic_count);
//reference lists
copy_fields(h, h1, ref_count, list_count);
copy_fields(h, h1, ref_list, intra_gb);
copy_fields(h, h1, short_ref, cabac_init_idc);
copy_picture_range(h->short_ref, h1->short_ref, 32, s, s1);
copy_picture_range(h->long_ref, h1->long_ref, 32, s, s1);
copy_picture_range(h->delayed_pic, h1->delayed_pic, MAX_DELAYED_PIC_COUNT+2, s, s1);
h->last_slice_type = h1->last_slice_type;
if(!s->current_picture_ptr) return 0;
if(!s->dropable) {
ff_h264_execute_ref_pic_marking(h, h->mmco, h->mmco_index);
h->prev_poc_msb = h->poc_msb;
h->prev_poc_lsb = h->poc_lsb;
}
h->prev_frame_num_offset= h->frame_num_offset;
h->prev_frame_num = h->frame_num;
h->outputed_poc = h->next_outputed_poc;
return 0;
}
int ff_h264_frame_start(H264Context *h){
MpegEncContext * const s = &h->s;
int i;
const int pixel_shift = h->pixel_shift;
int thread_count = (s->avctx->active_thread_type & FF_THREAD_SLICE) ? s->avctx->thread_count : 1;
if(MPV_frame_start(s, s->avctx) < 0)
return -1;
ff_er_frame_start(s);
/*
* MPV_frame_start uses pict_type to derive key_frame.
* This is incorrect for H.264; IDR markings must be used.
* Zero here; IDR markings per slice in frame or fields are ORed in later.
* See decode_nal_units().
*/
s->current_picture_ptr->f.key_frame = 0;
s->current_picture_ptr->mmco_reset= 0;
assert(s->linesize && s->uvlinesize);
for(i=0; i<16; i++){
h->block_offset[i]= (4*((scan8[i] - scan8[0])&7) << pixel_shift) + 4*s->linesize*((scan8[i] - scan8[0])>>3);
h->block_offset[48+i]= (4*((scan8[i] - scan8[0])&7) << pixel_shift) + 8*s->linesize*((scan8[i] - scan8[0])>>3);
}
for(i=0; i<16; i++){
h->block_offset[16+i]=
h->block_offset[32+i]= (4*((scan8[i] - scan8[0])&7) << pixel_shift) + 4*s->uvlinesize*((scan8[i] - scan8[0])>>3);
h->block_offset[48+16+i]=
h->block_offset[48+32+i]= (4*((scan8[i] - scan8[0])&7) << pixel_shift) + 8*s->uvlinesize*((scan8[i] - scan8[0])>>3);
}
/* can't be in alloc_tables because linesize isn't known there.
* FIXME: redo bipred weight to not require extra buffer? */
for(i = 0; i < thread_count; i++)
if(h->thread_context[i] && !h->thread_context[i]->s.obmc_scratchpad)
h->thread_context[i]->s.obmc_scratchpad = av_malloc(16*6*s->linesize);
/* some macroblocks can be accessed before they're available in case of lost slices, mbaff or threading*/
memset(h->slice_table, -1, (s->mb_height*s->mb_stride-1) * sizeof(*h->slice_table));
// s->decode = (s->flags & CODEC_FLAG_PSNR) || !s->encoding || s->current_picture.f.reference /*|| h->contains_intra*/ || 1;
// We mark the current picture as non-reference after allocating it, so
// that if we break out due to an error it can be released automatically
// in the next MPV_frame_start().
// SVQ3 as well as most other codecs have only last/next/current and thus
// get released even with set reference, besides SVQ3 and others do not
// mark frames as reference later "naturally".
if(s->codec_id != CODEC_ID_SVQ3)
s->current_picture_ptr->f.reference = 0;
s->current_picture_ptr->field_poc[0]=
s->current_picture_ptr->field_poc[1]= INT_MAX;
h->next_output_pic = NULL;
assert(s->current_picture_ptr->long_ref==0);
return 0;
}
/**
* Run setup operations that must be run after slice header decoding.
* This includes finding the next displayed frame.
*
* @param h h264 master context
* @param setup_finished enough NALs have been read that we can call
* ff_thread_finish_setup()
*/
static void decode_postinit(H264Context *h, int setup_finished){
MpegEncContext * const s = &h->s;
Picture *out = s->current_picture_ptr;
Picture *cur = s->current_picture_ptr;
int i, pics, out_of_order, out_idx;
s->current_picture_ptr->f.qscale_type = FF_QSCALE_TYPE_H264;
s->current_picture_ptr->f.pict_type = s->pict_type;
if (h->next_output_pic) return;
if (cur->field_poc[0]==INT_MAX || cur->field_poc[1]==INT_MAX) {
//FIXME: if we have two PAFF fields in one packet, we can't start the next thread here.
//If we have one field per packet, we can. The check in decode_nal_units() is not good enough
//to find this yet, so we assume the worst for now.
//if (setup_finished)
// ff_thread_finish_setup(s->avctx);
return;
}
cur->f.interlaced_frame = 0;
cur->f.repeat_pict = 0;
/* Signal interlacing information externally. */
/* Prioritize picture timing SEI information over used decoding process if it exists. */
if(h->sps.pic_struct_present_flag){
switch (h->sei_pic_struct)
{
case SEI_PIC_STRUCT_FRAME:
break;
case SEI_PIC_STRUCT_TOP_FIELD:
case SEI_PIC_STRUCT_BOTTOM_FIELD:
cur->f.interlaced_frame = 1;
break;
case SEI_PIC_STRUCT_TOP_BOTTOM:
case SEI_PIC_STRUCT_BOTTOM_TOP:
if (FIELD_OR_MBAFF_PICTURE)
cur->f.interlaced_frame = 1;
else
// try to flag soft telecine progressive
cur->f.interlaced_frame = h->prev_interlaced_frame;
break;
case SEI_PIC_STRUCT_TOP_BOTTOM_TOP:
case SEI_PIC_STRUCT_BOTTOM_TOP_BOTTOM:
// Signal the possibility of telecined film externally (pic_struct 5,6)
// From these hints, let the applications decide if they apply deinterlacing.
cur->f.repeat_pict = 1;
break;
case SEI_PIC_STRUCT_FRAME_DOUBLING:
// Force progressive here, as doubling interlaced frame is a bad idea.
cur->f.repeat_pict = 2;
break;
case SEI_PIC_STRUCT_FRAME_TRIPLING:
cur->f.repeat_pict = 4;
break;
}
if ((h->sei_ct_type & 3) && h->sei_pic_struct <= SEI_PIC_STRUCT_BOTTOM_TOP)
cur->f.interlaced_frame = (h->sei_ct_type & (1 << 1)) != 0;
}else{
/* Derive interlacing flag from used decoding process. */
cur->f.interlaced_frame = FIELD_OR_MBAFF_PICTURE;
}
h->prev_interlaced_frame = cur->f.interlaced_frame;
if (cur->field_poc[0] != cur->field_poc[1]){
/* Derive top_field_first from field pocs. */
cur->f.top_field_first = cur->field_poc[0] < cur->field_poc[1];
}else{
if (cur->f.interlaced_frame || h->sps.pic_struct_present_flag) {
/* Use picture timing SEI information. Even if it is a information of a past frame, better than nothing. */
if(h->sei_pic_struct == SEI_PIC_STRUCT_TOP_BOTTOM
|| h->sei_pic_struct == SEI_PIC_STRUCT_TOP_BOTTOM_TOP)
cur->f.top_field_first = 1;
else
cur->f.top_field_first = 0;
}else{
/* Most likely progressive */
cur->f.top_field_first = 0;
}
}
//FIXME do something with unavailable reference frames
/* Sort B-frames into display order */
if(h->sps.bitstream_restriction_flag
&& s->avctx->has_b_frames < h->sps.num_reorder_frames){
s->avctx->has_b_frames = h->sps.num_reorder_frames;
s->low_delay = 0;
}
if( s->avctx->strict_std_compliance >= FF_COMPLIANCE_STRICT
&& !h->sps.bitstream_restriction_flag){
s->avctx->has_b_frames= MAX_DELAYED_PIC_COUNT;
s->low_delay= 0;
}
pics = 0;
while(h->delayed_pic[pics]) pics++;
assert(pics <= MAX_DELAYED_PIC_COUNT);
h->delayed_pic[pics++] = cur;
if (cur->f.reference == 0)
cur->f.reference = DELAYED_PIC_REF;
out = h->delayed_pic[0];
out_idx = 0;
for (i = 1; h->delayed_pic[i] && !h->delayed_pic[i]->f.key_frame && !h->delayed_pic[i]->mmco_reset; i++)
if(h->delayed_pic[i]->poc < out->poc){
out = h->delayed_pic[i];
out_idx = i;
}
if (s->avctx->has_b_frames == 0 && (h->delayed_pic[0]->f.key_frame || h->delayed_pic[0]->mmco_reset))
h->next_outputed_poc= INT_MIN;
out_of_order = out->poc < h->next_outputed_poc;
if(h->sps.bitstream_restriction_flag && s->avctx->has_b_frames >= h->sps.num_reorder_frames)
{ }
else if((out_of_order && pics-1 == s->avctx->has_b_frames && s->avctx->has_b_frames < MAX_DELAYED_PIC_COUNT)
|| (s->low_delay &&
((h->next_outputed_poc != INT_MIN && out->poc > h->next_outputed_poc + 2)
|| cur->f.pict_type == AV_PICTURE_TYPE_B)))
{
s->low_delay = 0;
s->avctx->has_b_frames++;
}
if(out_of_order || pics > s->avctx->has_b_frames){
out->f.reference &= ~DELAYED_PIC_REF;
out->owner2 = s; // for frame threading, the owner must be the second field's thread
// or else the first thread can release the picture and reuse it unsafely
for(i=out_idx; h->delayed_pic[i]; i++)
h->delayed_pic[i] = h->delayed_pic[i+1];
}
if(!out_of_order && pics > s->avctx->has_b_frames){
h->next_output_pic = out;
if (out_idx == 0 && h->delayed_pic[0] && (h->delayed_pic[0]->f.key_frame || h->delayed_pic[0]->mmco_reset)) {
h->next_outputed_poc = INT_MIN;
} else
h->next_outputed_poc = out->poc;
}else{
av_log(s->avctx, AV_LOG_DEBUG, "no picture\n");
}
if (setup_finished)
ff_thread_finish_setup(s->avctx);
}
static av_always_inline void backup_mb_border(H264Context *h, uint8_t *src_y, uint8_t *src_cb, uint8_t *src_cr, int linesize, int uvlinesize, int chroma444, int simple){
MpegEncContext * const s = &h->s;
uint8_t *top_border;
int top_idx = 1;
const int pixel_shift = h->pixel_shift;
src_y -= linesize;
src_cb -= uvlinesize;
src_cr -= uvlinesize;
if(!simple && FRAME_MBAFF){
if(s->mb_y&1){
if(!MB_MBAFF){
top_border = h->top_borders[0][s->mb_x];
AV_COPY128(top_border, src_y + 15*linesize);
if (pixel_shift)
AV_COPY128(top_border+16, src_y+15*linesize+16);
if(simple || !CONFIG_GRAY || !(s->flags&CODEC_FLAG_GRAY)){
if(chroma444){
if (pixel_shift){
AV_COPY128(top_border+32, src_cb + 15*uvlinesize);
AV_COPY128(top_border+48, src_cb + 15*uvlinesize+16);
AV_COPY128(top_border+64, src_cr + 15*uvlinesize);
AV_COPY128(top_border+80, src_cr + 15*uvlinesize+16);
} else {
AV_COPY128(top_border+16, src_cb + 15*uvlinesize);
AV_COPY128(top_border+32, src_cr + 15*uvlinesize);
}
} else {
if (pixel_shift) {
AV_COPY128(top_border+32, src_cb+7*uvlinesize);
AV_COPY128(top_border+48, src_cr+7*uvlinesize);
} else {
AV_COPY64(top_border+16, src_cb+7*uvlinesize);
AV_COPY64(top_border+24, src_cr+7*uvlinesize);
}
}
}
}
}else if(MB_MBAFF){
top_idx = 0;
}else
return;
}
top_border = h->top_borders[top_idx][s->mb_x];
// There are two lines saved, the line above the the top macroblock of a pair,
// and the line above the bottom macroblock
AV_COPY128(top_border, src_y + 16*linesize);
if (pixel_shift)
AV_COPY128(top_border+16, src_y+16*linesize+16);
if(simple || !CONFIG_GRAY || !(s->flags&CODEC_FLAG_GRAY)){
if(chroma444){
if (pixel_shift){
AV_COPY128(top_border+32, src_cb + 16*linesize);
AV_COPY128(top_border+48, src_cb + 16*linesize+16);
AV_COPY128(top_border+64, src_cr + 16*linesize);
AV_COPY128(top_border+80, src_cr + 16*linesize+16);
} else {
AV_COPY128(top_border+16, src_cb + 16*linesize);
AV_COPY128(top_border+32, src_cr + 16*linesize);
}
} else {
if (pixel_shift) {
AV_COPY128(top_border+32, src_cb+8*uvlinesize);
AV_COPY128(top_border+48, src_cr+8*uvlinesize);
} else {
AV_COPY64(top_border+16, src_cb+8*uvlinesize);
AV_COPY64(top_border+24, src_cr+8*uvlinesize);
}
}
}
}
static av_always_inline void xchg_mb_border(H264Context *h, uint8_t *src_y,
uint8_t *src_cb, uint8_t *src_cr,
int linesize, int uvlinesize,
int xchg, int chroma444,
int simple, int pixel_shift){
MpegEncContext * const s = &h->s;
int deblock_topleft;
int deblock_top;
int top_idx = 1;
uint8_t *top_border_m1;
uint8_t *top_border;
if(!simple && FRAME_MBAFF){
if(s->mb_y&1){
if(!MB_MBAFF)
return;
}else{
top_idx = MB_MBAFF ? 0 : 1;
}
}
if(h->deblocking_filter == 2) {
deblock_topleft = h->slice_table[h->mb_xy - 1 - s->mb_stride] == h->slice_num;
deblock_top = h->top_type;
} else {
deblock_topleft = (s->mb_x > 0);
deblock_top = (s->mb_y > !!MB_FIELD);
}
src_y -= linesize + 1 + pixel_shift;
src_cb -= uvlinesize + 1 + pixel_shift;
src_cr -= uvlinesize + 1 + pixel_shift;
top_border_m1 = h->top_borders[top_idx][s->mb_x-1];
top_border = h->top_borders[top_idx][s->mb_x];
#define XCHG(a,b,xchg)\
if (pixel_shift) {\
if (xchg) {\
AV_SWAP64(b+0,a+0);\
AV_SWAP64(b+8,a+8);\
} else {\
AV_COPY128(b,a); \
}\
} else \
if (xchg) AV_SWAP64(b,a);\
else AV_COPY64(b,a);
if(deblock_top){
if(deblock_topleft){
XCHG(top_border_m1 + (8 << pixel_shift), src_y - (7 << pixel_shift), 1);
}
XCHG(top_border + (0 << pixel_shift), src_y + (1 << pixel_shift), xchg);
XCHG(top_border + (8 << pixel_shift), src_y + (9 << pixel_shift), 1);
if(s->mb_x+1 < s->mb_width){
XCHG(h->top_borders[top_idx][s->mb_x+1], src_y + (17 << pixel_shift), 1);
}
}
if(simple || !CONFIG_GRAY || !(s->flags&CODEC_FLAG_GRAY)){
if(chroma444){
if(deblock_topleft){
XCHG(top_border_m1 + (24 << pixel_shift), src_cb - (7 << pixel_shift), 1);
XCHG(top_border_m1 + (40 << pixel_shift), src_cr - (7 << pixel_shift), 1);
}
XCHG(top_border + (16 << pixel_shift), src_cb + (1 << pixel_shift), xchg);
XCHG(top_border + (24 << pixel_shift), src_cb + (9 << pixel_shift), 1);
XCHG(top_border + (32 << pixel_shift), src_cr + (1 << pixel_shift), xchg);
XCHG(top_border + (40 << pixel_shift), src_cr + (9 << pixel_shift), 1);
if(s->mb_x+1 < s->mb_width){
XCHG(h->top_borders[top_idx][s->mb_x+1] + (16 << pixel_shift), src_cb + (17 << pixel_shift), 1);
XCHG(h->top_borders[top_idx][s->mb_x+1] + (32 << pixel_shift), src_cr + (17 << pixel_shift), 1);
}
} else {
if(deblock_top){
if(deblock_topleft){
XCHG(top_border_m1 + (16 << pixel_shift), src_cb - (7 << pixel_shift), 1);
XCHG(top_border_m1 + (24 << pixel_shift), src_cr - (7 << pixel_shift), 1);
}
XCHG(top_border + (16 << pixel_shift), src_cb+1+pixel_shift, 1);
XCHG(top_border + (24 << pixel_shift), src_cr+1+pixel_shift, 1);
}
}
}
}
static av_always_inline int dctcoef_get(DCTELEM *mb, int high_bit_depth, int index) {
if (high_bit_depth) {
return AV_RN32A(((int32_t*)mb) + index);
} else
return AV_RN16A(mb + index);
}
static av_always_inline void dctcoef_set(DCTELEM *mb, int high_bit_depth, int index, int value) {
if (high_bit_depth) {
AV_WN32A(((int32_t*)mb) + index, value);
} else
AV_WN16A(mb + index, value);
}
static av_always_inline void hl_decode_mb_predict_luma(H264Context *h, int mb_type, int is_h264, int simple, int transform_bypass,
int pixel_shift, int *block_offset, int linesize, uint8_t *dest_y, int p)
{
MpegEncContext * const s = &h->s;
void (*idct_add)(uint8_t *dst, DCTELEM *block, int stride);
void (*idct_dc_add)(uint8_t *dst, DCTELEM *block, int stride);
int i;
int qscale = p == 0 ? s->qscale : h->chroma_qp[p-1];
block_offset += 16*p;
if(IS_INTRA4x4(mb_type)){
if(simple || !s->encoding){
if(IS_8x8DCT(mb_type)){
if(transform_bypass){
idct_dc_add =
idct_add = s->dsp.add_pixels8;
}else{
idct_dc_add = h->h264dsp.h264_idct8_dc_add;
idct_add = h->h264dsp.h264_idct8_add;
}
for(i=0; i<16; i+=4){
uint8_t * const ptr= dest_y + block_offset[i];
const int dir= h->intra4x4_pred_mode_cache[ scan8[i] ];
if(transform_bypass && h->sps.profile_idc==244 && dir<=1){
h->hpc.pred8x8l_add[dir](ptr, h->mb + (i*16+p*256 << pixel_shift), linesize);
}else{
const int nnz = h->non_zero_count_cache[ scan8[i+p*16] ];
h->hpc.pred8x8l[ dir ](ptr, (h->topleft_samples_available<<i)&0x8000,
(h->topright_samples_available<<i)&0x4000, linesize);
if(nnz){
if(nnz == 1 && dctcoef_get(h->mb, pixel_shift, i*16+p*256))
idct_dc_add(ptr, h->mb + (i*16+p*256 << pixel_shift), linesize);
else
idct_add (ptr, h->mb + (i*16+p*256 << pixel_shift), linesize);
}
}
}
}else{
if(transform_bypass){
idct_dc_add =
idct_add = s->dsp.add_pixels4;
}else{
idct_dc_add = h->h264dsp.h264_idct_dc_add;
idct_add = h->h264dsp.h264_idct_add;
}
for(i=0; i<16; i++){
uint8_t * const ptr= dest_y + block_offset[i];
const int dir= h->intra4x4_pred_mode_cache[ scan8[i] ];
if(transform_bypass && h->sps.profile_idc==244 && dir<=1){
h->hpc.pred4x4_add[dir](ptr, h->mb + (i*16+p*256 << pixel_shift), linesize);
}else{
uint8_t *topright;
int nnz, tr;
uint64_t tr_high;
if(dir == DIAG_DOWN_LEFT_PRED || dir == VERT_LEFT_PRED){
const int topright_avail= (h->topright_samples_available<<i)&0x8000;
assert(s->mb_y || linesize <= block_offset[i]);
if(!topright_avail){
if (pixel_shift) {
tr_high= ((uint16_t*)ptr)[3 - linesize/2]*0x0001000100010001ULL;
topright= (uint8_t*) &tr_high;
} else {
tr= ptr[3 - linesize]*0x01010101;
topright= (uint8_t*) &tr;
}
}else
topright= ptr + (4 << pixel_shift) - linesize;
}else
topright= NULL;
h->hpc.pred4x4[ dir ](ptr, topright, linesize);
nnz = h->non_zero_count_cache[ scan8[i+p*16] ];
if(nnz){
if(is_h264){
if(nnz == 1 && dctcoef_get(h->mb, pixel_shift, i*16+p*256))
idct_dc_add(ptr, h->mb + (i*16+p*256 << pixel_shift), linesize);
else
idct_add (ptr, h->mb + (i*16+p*256 << pixel_shift), linesize);
}else
ff_svq3_add_idct_c(ptr, h->mb + i*16+p*256, linesize, qscale, 0);
}
}
}
}
}
}else{
h->hpc.pred16x16[ h->intra16x16_pred_mode ](dest_y , linesize);
if(is_h264){
if(h->non_zero_count_cache[ scan8[LUMA_DC_BLOCK_INDEX+p] ]){
if(!transform_bypass)
h->h264dsp.h264_luma_dc_dequant_idct(h->mb+(p*256 << pixel_shift), h->mb_luma_dc[p], h->dequant4_coeff[p][qscale][0]);
else{
static const uint8_t dc_mapping[16] = { 0*16, 1*16, 4*16, 5*16, 2*16, 3*16, 6*16, 7*16,
8*16, 9*16,12*16,13*16,10*16,11*16,14*16,15*16};
for(i = 0; i < 16; i++)
dctcoef_set(h->mb+p*256, pixel_shift, dc_mapping[i], dctcoef_get(h->mb_luma_dc[p], pixel_shift, i));
}
}
}else
ff_svq3_luma_dc_dequant_idct_c(h->mb+p*256, h->mb_luma_dc[p], qscale);
}
}
static av_always_inline void hl_decode_mb_idct_luma(H264Context *h, int mb_type, int is_h264, int simple, int transform_bypass,
int pixel_shift, int *block_offset, int linesize, uint8_t *dest_y, int p)
{
MpegEncContext * const s = &h->s;
void (*idct_add)(uint8_t *dst, DCTELEM *block, int stride);
int i;
block_offset += 16*p;
if(!IS_INTRA4x4(mb_type)){
if(is_h264){
if(IS_INTRA16x16(mb_type)){
if(transform_bypass){
if(h->sps.profile_idc==244 && (h->intra16x16_pred_mode==VERT_PRED8x8 || h->intra16x16_pred_mode==HOR_PRED8x8)){
h->hpc.pred16x16_add[h->intra16x16_pred_mode](dest_y, block_offset, h->mb + (p*256 << pixel_shift), linesize);
}else{
for(i=0; i<16; i++){
if(h->non_zero_count_cache[ scan8[i+p*16] ] || dctcoef_get(h->mb, pixel_shift, i*16+p*256))
s->dsp.add_pixels4(dest_y + block_offset[i], h->mb + (i*16+p*256 << pixel_shift), linesize);
}
}
}else{
h->h264dsp.h264_idct_add16intra(dest_y, block_offset, h->mb + (p*256 << pixel_shift), linesize, h->non_zero_count_cache+p*5*8);
}
}else if(h->cbp&15){
if(transform_bypass){
const int di = IS_8x8DCT(mb_type) ? 4 : 1;
idct_add= IS_8x8DCT(mb_type) ? s->dsp.add_pixels8 : s->dsp.add_pixels4;
for(i=0; i<16; i+=di){
if(h->non_zero_count_cache[ scan8[i+p*16] ]){
idct_add(dest_y + block_offset[i], h->mb + (i*16+p*256 << pixel_shift), linesize);
}
}
}else{
if(IS_8x8DCT(mb_type)){
h->h264dsp.h264_idct8_add4(dest_y, block_offset, h->mb + (p*256 << pixel_shift), linesize, h->non_zero_count_cache+p*5*8);
}else{
h->h264dsp.h264_idct_add16(dest_y, block_offset, h->mb + (p*256 << pixel_shift), linesize, h->non_zero_count_cache+p*5*8);
}
}
}
}else{
for(i=0; i<16; i++){
if(h->non_zero_count_cache[ scan8[i+p*16] ] || h->mb[i*16+p*256]){ //FIXME benchmark weird rule, & below
uint8_t * const ptr= dest_y + block_offset[i];
ff_svq3_add_idct_c(ptr, h->mb + i*16 + p*256, linesize, s->qscale, IS_INTRA(mb_type) ? 1 : 0);
}
}
}
}
}
static av_always_inline void hl_decode_mb_internal(H264Context *h, int simple, int pixel_shift){
MpegEncContext * const s = &h->s;
const int mb_x= s->mb_x;
const int mb_y= s->mb_y;
const int mb_xy= h->mb_xy;
const int mb_type = s->current_picture.f.mb_type[mb_xy];
uint8_t *dest_y, *dest_cb, *dest_cr;
int linesize, uvlinesize /*dct_offset*/;
int i, j;
int *block_offset = &h->block_offset[0];
const int transform_bypass = !simple && (s->qscale == 0 && h->sps.transform_bypass);
/* is_h264 should always be true if SVQ3 is disabled. */
const int is_h264 = !CONFIG_SVQ3_DECODER || simple || s->codec_id == CODEC_ID_H264;
void (*idct_add)(uint8_t *dst, DCTELEM *block, int stride);
dest_y = s->current_picture.f.data[0] + ((mb_x << pixel_shift) + mb_y * s->linesize ) * 16;
dest_cb = s->current_picture.f.data[1] + ((mb_x << pixel_shift) + mb_y * s->uvlinesize) * 8;
dest_cr = s->current_picture.f.data[2] + ((mb_x << pixel_shift) + mb_y * s->uvlinesize) * 8;
s->dsp.prefetch(dest_y + (s->mb_x&3)*4*s->linesize + (64 << pixel_shift), s->linesize, 4);
s->dsp.prefetch(dest_cb + (s->mb_x&7)*s->uvlinesize + (64 << pixel_shift), dest_cr - dest_cb, 2);
h->list_counts[mb_xy]= h->list_count;
if (!simple && MB_FIELD) {
linesize = h->mb_linesize = s->linesize * 2;
uvlinesize = h->mb_uvlinesize = s->uvlinesize * 2;
block_offset = &h->block_offset[48];
if(mb_y&1){ //FIXME move out of this function?
dest_y -= s->linesize*15;
dest_cb-= s->uvlinesize*7;
dest_cr-= s->uvlinesize*7;
}
if(FRAME_MBAFF) {
int list;
for(list=0; list<h->list_count; list++){
if(!USES_LIST(mb_type, list))
continue;
if(IS_16X16(mb_type)){
int8_t *ref = &h->ref_cache[list][scan8[0]];
fill_rectangle(ref, 4, 4, 8, (16+*ref)^(s->mb_y&1), 1);
}else{
for(i=0; i<16; i+=4){
int ref = h->ref_cache[list][scan8[i]];
if(ref >= 0)
fill_rectangle(&h->ref_cache[list][scan8[i]], 2, 2, 8, (16+ref)^(s->mb_y&1), 1);
}
}
}
}
} else {
linesize = h->mb_linesize = s->linesize;
uvlinesize = h->mb_uvlinesize = s->uvlinesize;
// dct_offset = s->linesize * 16;
}
if (!simple && IS_INTRA_PCM(mb_type)) {
if (pixel_shift) {
const int bit_depth = h->sps.bit_depth_luma;
int j;
GetBitContext gb;
init_get_bits(&gb, (uint8_t*)h->mb, 384*bit_depth);
for (i = 0; i < 16; i++) {
uint16_t *tmp_y = (uint16_t*)(dest_y + i*linesize);
for (j = 0; j < 16; j++)
tmp_y[j] = get_bits(&gb, bit_depth);
}
if(simple || !CONFIG_GRAY || !(s->flags&CODEC_FLAG_GRAY)){
for (i = 0; i < 8; i++) {
uint16_t *tmp_cb = (uint16_t*)(dest_cb + i*uvlinesize);
for (j = 0; j < 8; j++)
tmp_cb[j] = get_bits(&gb, bit_depth);
}
for (i = 0; i < 8; i++) {
uint16_t *tmp_cr = (uint16_t*)(dest_cr + i*uvlinesize);
for (j = 0; j < 8; j++)
tmp_cr[j] = get_bits(&gb, bit_depth);
}
}
} else {
for (i=0; i<16; i++) {
memcpy(dest_y + i* linesize, h->mb + i*8, 16);
}
if(simple || !CONFIG_GRAY || !(s->flags&CODEC_FLAG_GRAY)){
for (i=0; i<8; i++) {
memcpy(dest_cb+ i*uvlinesize, h->mb + 128 + i*4, 8);
memcpy(dest_cr+ i*uvlinesize, h->mb + 160 + i*4, 8);
}
}
}
} else {
if(IS_INTRA(mb_type)){
if(h->deblocking_filter)
xchg_mb_border(h, dest_y, dest_cb, dest_cr, linesize, uvlinesize, 1, 0, simple, pixel_shift);
if(simple || !CONFIG_GRAY || !(s->flags&CODEC_FLAG_GRAY)){
h->hpc.pred8x8[ h->chroma_pred_mode ](dest_cb, uvlinesize);
h->hpc.pred8x8[ h->chroma_pred_mode ](dest_cr, uvlinesize);
}
hl_decode_mb_predict_luma(h, mb_type, is_h264, simple, transform_bypass, pixel_shift, block_offset, linesize, dest_y, 0);
if(h->deblocking_filter)
xchg_mb_border(h, dest_y, dest_cb, dest_cr, linesize, uvlinesize, 0, 0, simple, pixel_shift);
}else if(is_h264){
hl_motion(h, dest_y, dest_cb, dest_cr,
s->me.qpel_put, s->dsp.put_h264_chroma_pixels_tab,
s->me.qpel_avg, s->dsp.avg_h264_chroma_pixels_tab,
h->h264dsp.weight_h264_pixels_tab,
h->h264dsp.biweight_h264_pixels_tab, pixel_shift, 0);
}
hl_decode_mb_idct_luma(h, mb_type, is_h264, simple, transform_bypass, pixel_shift, block_offset, linesize, dest_y, 0);
if((simple || !CONFIG_GRAY || !(s->flags&CODEC_FLAG_GRAY)) && (h->cbp&0x30)){
uint8_t *dest[2] = {dest_cb, dest_cr};
if(transform_bypass){
if(IS_INTRA(mb_type) && h->sps.profile_idc==244 && (h->chroma_pred_mode==VERT_PRED8x8 || h->chroma_pred_mode==HOR_PRED8x8)){
h->hpc.pred8x8_add[h->chroma_pred_mode](dest[0], block_offset + 16, h->mb + (16*16*1 << pixel_shift), uvlinesize);
h->hpc.pred8x8_add[h->chroma_pred_mode](dest[1], block_offset + 32, h->mb + (16*16*2 << pixel_shift), uvlinesize);
}else{
idct_add = s->dsp.add_pixels4;
for(j=1; j<3; j++){
for(i=j*16; i<j*16+4; i++){
if(h->non_zero_count_cache[ scan8[i] ] || dctcoef_get(h->mb, pixel_shift, i*16))
idct_add (dest[j-1] + block_offset[i], h->mb + (i*16 << pixel_shift), uvlinesize);
}
}
}
}else{
if(is_h264){
if(h->non_zero_count_cache[ scan8[CHROMA_DC_BLOCK_INDEX+0] ])
h->h264dsp.h264_chroma_dc_dequant_idct(h->mb + (16*16*1 << pixel_shift), h->dequant4_coeff[IS_INTRA(mb_type) ? 1:4][h->chroma_qp[0]][0]);
if(h->non_zero_count_cache[ scan8[CHROMA_DC_BLOCK_INDEX+1] ])
h->h264dsp.h264_chroma_dc_dequant_idct(h->mb + (16*16*2 << pixel_shift), h->dequant4_coeff[IS_INTRA(mb_type) ? 2:5][h->chroma_qp[1]][0]);
h->h264dsp.h264_idct_add8(dest, block_offset,
h->mb, uvlinesize,
h->non_zero_count_cache);
}
#if CONFIG_SVQ3_DECODER
else{
h->h264dsp.h264_chroma_dc_dequant_idct(h->mb + 16*16*1, h->dequant4_coeff[IS_INTRA(mb_type) ? 1:4][h->chroma_qp[0]][0]);
h->h264dsp.h264_chroma_dc_dequant_idct(h->mb + 16*16*2, h->dequant4_coeff[IS_INTRA(mb_type) ? 2:5][h->chroma_qp[1]][0]);
for(j=1; j<3; j++){
for(i=j*16; i<j*16+4; i++){
if(h->non_zero_count_cache[ scan8[i] ] || h->mb[i*16]){
uint8_t * const ptr= dest[j-1] + block_offset[i];
ff_svq3_add_idct_c(ptr, h->mb + i*16, uvlinesize, ff_h264_chroma_qp[0][s->qscale + 12] - 12, 2);
}
}
}
}
#endif
}
}
}
if(h->cbp || IS_INTRA(mb_type))
{
s->dsp.clear_blocks(h->mb);
s->dsp.clear_blocks(h->mb+(24*16<<pixel_shift));
}
}
static av_always_inline void hl_decode_mb_444_internal(H264Context *h, int simple, int pixel_shift){
MpegEncContext * const s = &h->s;
const int mb_x= s->mb_x;
const int mb_y= s->mb_y;
const int mb_xy= h->mb_xy;
const int mb_type = s->current_picture.f.mb_type[mb_xy];
uint8_t *dest[3];
int linesize;
int i, j, p;
int *block_offset = &h->block_offset[0];
const int transform_bypass = !simple && (s->qscale == 0 && h->sps.transform_bypass);
const int plane_count = (simple || !CONFIG_GRAY || !(s->flags&CODEC_FLAG_GRAY)) ? 3 : 1;
for (p = 0; p < plane_count; p++)
{
dest[p] = s->current_picture.f.data[p] + ((mb_x << pixel_shift) + mb_y * s->linesize) * 16;
s->dsp.prefetch(dest[p] + (s->mb_x&3)*4*s->linesize + (64 << pixel_shift), s->linesize, 4);
}
h->list_counts[mb_xy]= h->list_count;
if (!simple && MB_FIELD) {
linesize = h->mb_linesize = h->mb_uvlinesize = s->linesize * 2;
block_offset = &h->block_offset[48];
if(mb_y&1) //FIXME move out of this function?
for (p = 0; p < 3; p++)
dest[p] -= s->linesize*15;
if(FRAME_MBAFF) {
int list;
for(list=0; list<h->list_count; list++){
if(!USES_LIST(mb_type, list))
continue;
if(IS_16X16(mb_type)){
int8_t *ref = &h->ref_cache[list][scan8[0]];
fill_rectangle(ref, 4, 4, 8, (16+*ref)^(s->mb_y&1), 1);
}else{
for(i=0; i<16; i+=4){
int ref = h->ref_cache[list][scan8[i]];
if(ref >= 0)
fill_rectangle(&h->ref_cache[list][scan8[i]], 2, 2, 8, (16+ref)^(s->mb_y&1), 1);
}
}
}
}
} else {
linesize = h->mb_linesize = h->mb_uvlinesize = s->linesize;
}
if (!simple && IS_INTRA_PCM(mb_type)) {
if (pixel_shift) {
const int bit_depth = h->sps.bit_depth_luma;
GetBitContext gb;
init_get_bits(&gb, (uint8_t*)h->mb, 768*bit_depth);
for (p = 0; p < plane_count; p++) {
for (i = 0; i < 16; i++) {
uint16_t *tmp = (uint16_t*)(dest[p] + i*linesize);
for (j = 0; j < 16; j++)
tmp[j] = get_bits(&gb, bit_depth);
}
}
} else {
for (p = 0; p < plane_count; p++) {
for (i = 0; i < 16; i++) {
memcpy(dest[p] + i*linesize, h->mb + p*128 + i*8, 16);
}
}
}
} else {
if(IS_INTRA(mb_type)){
if(h->deblocking_filter)
xchg_mb_border(h, dest[0], dest[1], dest[2], linesize, linesize, 1, 1, simple, pixel_shift);
for (p = 0; p < plane_count; p++)
hl_decode_mb_predict_luma(h, mb_type, 1, simple, transform_bypass, pixel_shift, block_offset, linesize, dest[p], p);
if(h->deblocking_filter)
xchg_mb_border(h, dest[0], dest[1], dest[2], linesize, linesize, 0, 1, simple, pixel_shift);
}else{
hl_motion(h, dest[0], dest[1], dest[2],
s->me.qpel_put, s->dsp.put_h264_chroma_pixels_tab,
s->me.qpel_avg, s->dsp.avg_h264_chroma_pixels_tab,
h->h264dsp.weight_h264_pixels_tab,
h->h264dsp.biweight_h264_pixels_tab, pixel_shift, 1);
}
for (p = 0; p < plane_count; p++)
hl_decode_mb_idct_luma(h, mb_type, 1, simple, transform_bypass, pixel_shift, block_offset, linesize, dest[p], p);
}
if(h->cbp || IS_INTRA(mb_type))
{
s->dsp.clear_blocks(h->mb);
s->dsp.clear_blocks(h->mb+(24*16<<pixel_shift));
}
}
/**
* Process a macroblock; this case avoids checks for expensive uncommon cases.
*/
#define hl_decode_mb_simple(sh, bits) \
static void hl_decode_mb_simple_ ## bits(H264Context *h){ \
hl_decode_mb_internal(h, 1, sh); \
}
hl_decode_mb_simple(0, 8);
hl_decode_mb_simple(1, 16);
/**
* Process a macroblock; this handles edge cases, such as interlacing.
*/
static void av_noinline hl_decode_mb_complex(H264Context *h){
hl_decode_mb_internal(h, 0, h->pixel_shift);
}
static void av_noinline hl_decode_mb_444_complex(H264Context *h){
hl_decode_mb_444_internal(h, 0, h->pixel_shift);
}
static void av_noinline hl_decode_mb_444_simple(H264Context *h){
hl_decode_mb_444_internal(h, 1, 0);
}
void ff_h264_hl_decode_mb(H264Context *h){