*dst_length= di;
*consumed= si + 1;//+1 for the header
-//FIXME store exact number of bits in the getbitcontext (its needed for decoding)
+//FIXME store exact number of bits in the getbitcontext (it is needed for decoding)
return dst;
}
return chroma_qp[av_clip(qscale + chroma_qp_index_offset, 0, 51)];
}
-//FIXME need to check that this doesnt overflow signed 32 bit for low qp, i am not sure, it's very close
+//FIXME need to check that this does not overflow signed 32 bit for low qp, i am not sure, it's very close
//FIXME check that gcc inlines this (and optimizes intra & separate_dc stuff away)
static inline int quantize_c(DCTELEM *block, uint8_t *scantable, int qscale, int intra, int separate_dc){
int i;
#define LOAD_TOP_RIGHT_EDGE\
- const int t4= topright[0];\
- const int t5= topright[1];\
- const int t6= topright[2];\
- const int t7= topright[3];\
+ const int av_unused t4= topright[0];\
+ const int av_unused t5= topright[1];\
+ const int av_unused t6= topright[2];\
+ const int av_unused t7= topright[3];\
#define LOAD_LEFT_EDGE\
- const int l0= src[-1+0*stride];\
- const int l1= src[-1+1*stride];\
- const int l2= src[-1+2*stride];\
- const int l3= src[-1+3*stride];\
+ const int av_unused l0= src[-1+0*stride];\
+ const int av_unused l1= src[-1+1*stride];\
+ const int av_unused l2= src[-1+2*stride];\
+ const int av_unused l3= src[-1+3*stride];\
#define LOAD_TOP_EDGE\
- const int t0= src[ 0-1*stride];\
- const int t1= src[ 1-1*stride];\
- const int t2= src[ 2-1*stride];\
- const int t3= src[ 3-1*stride];\
+ const int av_unused t0= src[ 0-1*stride];\
+ const int av_unused t1= src[ 1-1*stride];\
+ const int av_unused t2= src[ 2-1*stride];\
+ const int av_unused t3= src[ 3-1*stride];\
static void pred4x4_down_right_c(uint8_t *src, uint8_t *topright, int stride){
const int lt= src[-1-1*stride];
const int lt= src[-1-1*stride];
LOAD_TOP_EDGE
LOAD_LEFT_EDGE
- const attribute_unused int unu= l3;
src[0+0*stride]=
src[1+2*stride]=(lt + t0 + 1)>>1;
static void pred4x4_vertical_left_c(uint8_t *src, uint8_t *topright, int stride){
LOAD_TOP_EDGE
LOAD_TOP_RIGHT_EDGE
- const attribute_unused int unu= t7;
src[0+0*stride]=(t0 + t1 + 1)>>1;
src[1+0*stride]=
const int lt= src[-1-1*stride];
LOAD_TOP_EDGE
LOAD_LEFT_EDGE
- const attribute_unused int unu= t3;
src[0+0*stride]=
src[2+1*stride]=(lt + l0 + 1)>>1;
}
}
-static void pred16x16_left_dc_c(uint8_t *src, int stride){
+void ff_pred16x16_left_dc_c(uint8_t *src, int stride){
int i, dc=0;
for(i=0;i<16; i++){
}
}
-static void pred16x16_top_dc_c(uint8_t *src, int stride){
+void ff_pred16x16_top_dc_c(uint8_t *src, int stride){
int i, dc=0;
for(i=0;i<16; i++){
}
}
-static void pred8x8_left_dc_c(uint8_t *src, int stride){
+void ff_pred8x8_left_dc_c(uint8_t *src, int stride){
int i;
int dc0, dc2;
}
}
-static void pred8x8_top_dc_c(uint8_t *src, int stride){
+void ff_pred8x8_top_dc_c(uint8_t *src, int stride){
int i;
int dc0, dc1;
const int l0 = ((has_topleft ? SRC(-1,-1) : SRC(-1,0)) \
+ 2*SRC(-1,0) + SRC(-1,1) + 2) >> 2; \
PL(1) PL(2) PL(3) PL(4) PL(5) PL(6) \
- const int l7 attribute_unused = (SRC(-1,6) + 3*SRC(-1,7) + 2) >> 2
+ const int l7 av_unused = (SRC(-1,6) + 3*SRC(-1,7) + 2) >> 2
#define PT(x) \
const int t##x = (SRC(x-1,-1) + 2*SRC(x,-1) + SRC(x+1,-1) + 2) >> 2;
const int t0 = ((has_topleft ? SRC(-1,-1) : SRC(0,-1)) \
+ 2*SRC(0,-1) + SRC(1,-1) + 2) >> 2; \
PT(1) PT(2) PT(3) PT(4) PT(5) PT(6) \
- const int t7 attribute_unused = ((has_topright ? SRC(8,-1) : SRC(7,-1)) \
+ const int t7 av_unused = ((has_topright ? SRC(8,-1) : SRC(7,-1)) \
+ 2*SRC(7,-1) + SRC(6,-1) + 2) >> 2
#define PTR(x) \
h->pred8x8[VERT_PRED8x8 ]= ff_pred8x8_vertical_c;
h->pred8x8[HOR_PRED8x8 ]= ff_pred8x8_horizontal_c;
h->pred8x8[PLANE_PRED8x8 ]= ff_pred8x8_plane_c;
- h->pred8x8[LEFT_DC_PRED8x8]= pred8x8_left_dc_c;
- h->pred8x8[TOP_DC_PRED8x8 ]= pred8x8_top_dc_c;
+ h->pred8x8[LEFT_DC_PRED8x8]= ff_pred8x8_left_dc_c;
+ h->pred8x8[TOP_DC_PRED8x8 ]= ff_pred8x8_top_dc_c;
h->pred8x8[DC_128_PRED8x8 ]= ff_pred8x8_128_dc_c;
h->pred16x16[DC_PRED8x8 ]= ff_pred16x16_dc_c;
h->pred16x16[VERT_PRED8x8 ]= ff_pred16x16_vertical_c;
h->pred16x16[HOR_PRED8x8 ]= ff_pred16x16_horizontal_c;
h->pred16x16[PLANE_PRED8x8 ]= ff_pred16x16_plane_c;
- h->pred16x16[LEFT_DC_PRED8x8]= pred16x16_left_dc_c;
- h->pred16x16[TOP_DC_PRED8x8 ]= pred16x16_top_dc_c;
+ h->pred16x16[LEFT_DC_PRED8x8]= ff_pred16x16_left_dc_c;
+ h->pred16x16[TOP_DC_PRED8x8 ]= ff_pred16x16_top_dc_c;
h->pred16x16[DC_128_PRED8x8 ]= ff_pred16x16_128_dc_c;
}
static void free_tables(H264Context *h){
+ int i;
av_freep(&h->intra4x4_pred_mode);
av_freep(&h->chroma_pred_mode_table);
av_freep(&h->cbp_table);
av_freep(&h->mb2b8_xy);
av_freep(&h->s.obmc_scratchpad);
+
+ 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);
}
static void init_dequant8_coeff_table(H264Context *h){
return 0;
}
-static inline void backup_mb_border(H264Context *h, uint8_t *src_y, uint8_t *src_cb, uint8_t *src_cr, int linesize, int uvlinesize){
+static inline void backup_mb_border(H264Context *h, uint8_t *src_y, uint8_t *src_cb, uint8_t *src_cr, int linesize, int uvlinesize, int simple){
MpegEncContext * const s = &h->s;
int i;
*(uint64_t*)(h->top_borders[0][s->mb_x]+0)= *(uint64_t*)(src_y + 16*linesize);
*(uint64_t*)(h->top_borders[0][s->mb_x]+8)= *(uint64_t*)(src_y +8+16*linesize);
- if(!(s->flags&CODEC_FLAG_GRAY)){
+ if(simple || !(s->flags&CODEC_FLAG_GRAY)){
h->left_border[17 ]= h->top_borders[0][s->mb_x][16+7];
h->left_border[17+9]= h->top_borders[0][s->mb_x][24+7];
for(i=1; i<9; i++){
}
}
-static 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){
+static 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 simple){
MpegEncContext * const s = &h->s;
int temp8, i;
uint64_t temp64;
}
}
- if(!(s->flags&CODEC_FLAG_GRAY)){
+ if(simple || !(s->flags&CODEC_FLAG_GRAY)){
if(deblock_left){
for(i = !deblock_top; i<9; i++){
XCHG(h->left_border[i+17 ], src_cb[i*uvlinesize], temp8, xchg);
} else {
if(IS_INTRA(mb_type)){
if(h->deblocking_filter && (simple || !FRAME_MBAFF))
- xchg_mb_border(h, dest_y, dest_cb, dest_cr, linesize, uvlinesize, 1);
+ xchg_mb_border(h, dest_y, dest_cb, dest_cr, linesize, uvlinesize, 1, simple);
if(simple || !(s->flags&CODEC_FLAG_GRAY)){
h->pred8x8[ h->chroma_pred_mode ](dest_cb, uvlinesize);
svq3_luma_dc_dequant_idct_c(h->mb, s->qscale);
}
if(h->deblocking_filter && (simple || !FRAME_MBAFF))
- xchg_mb_border(h, dest_y, dest_cb, dest_cr, linesize, uvlinesize, 0);
+ xchg_mb_border(h, dest_y, dest_cb, dest_cr, linesize, uvlinesize, 0, simple);
}else if(is_h264){
hl_motion(h, dest_y, dest_cb, dest_cr,
s->me.qpel_put, s->dsp.put_h264_chroma_pixels_tab,
filter_mb(h, mb_x, mb_y+1, dest_y, dest_cb, dest_cr, linesize, uvlinesize);
} else {
tprintf(h->s.avctx, "call filter_mb\n");
- backup_mb_border(h, dest_y, dest_cb, dest_cr, linesize, uvlinesize);
+ backup_mb_border(h, dest_y, dest_cb, dest_cr, linesize, uvlinesize, simple);
fill_caches(h, mb_type, 1); //FIXME don't fill stuff which isn't used by filter_mb
filter_mb_fast(h, mb_x, mb_y, dest_y, dest_cb, dest_cr, linesize, uvlinesize);
}
av_log(h->s.avctx, AV_LOG_ERROR, "pps_id out of range\n");
return -1;
}
- h->pps= h->pps_buffer[pps_id];
- if(h->pps.slice_group_count == 0){
+ if(!h->pps_buffers[pps_id]) {
av_log(h->s.avctx, AV_LOG_ERROR, "non existing PPS referenced\n");
return -1;
}
+ h->pps= *h->pps_buffers[pps_id];
- h->sps= h->sps_buffer[ h->pps.sps_id ];
- if(h->sps.log2_max_frame_num == 0){
+ if(!h->sps_buffers[h->pps.sps_id]) {
av_log(h->s.avctx, AV_LOG_ERROR, "non existing SPS referenced\n");
return -1;
}
+ h->sps = *h->sps_buffers[h->pps.sps_id];
if(h->dequant_coeff_pps != pps_id){
h->dequant_coeff_pps = pps_id;
if(IS_INTRA_PCM(mb_type)){
unsigned int x, y;
- // we assume these blocks are very rare so we dont optimize it
+ // We assume these blocks are very rare so we do not optimize it.
align_get_bits(&s->gb);
// The pixels are stored in the same order as levels in h->mb array.
const uint8_t *ptr;
unsigned int x, y;
- // We assume these blocks are very rare so we dont optimize it.
+ // We assume these blocks are very rare so we do not optimize it.
// FIXME The two following lines get the bitstream position in the cabac
// decode, I think it should be done by a function in cabac.h (or cabac.c).
ptr= h->cabac.bytestream;
int mb_xy, mb_type;
int qp, qp0, qp1, qpc, qpc0, qpc1, qp_thresh;
- if(mb_x==0 || mb_y==0 || !s->dsp.h264_loop_filter_strength) {
+ mb_xy = mb_x + mb_y*s->mb_stride;
+
+ if(mb_x==0 || mb_y==0 || !s->dsp.h264_loop_filter_strength ||
+ (h->deblocking_filter == 2 && (h->slice_table[mb_xy] != h->slice_table[h->top_mb_xy] ||
+ h->slice_table[mb_xy] != h->slice_table[mb_xy - 1]))) {
filter_mb(h, mb_x, mb_y, img_y, img_cb, img_cr, linesize, uvlinesize);
return;
}
assert(!FRAME_MBAFF);
- mb_xy = mb_x + mb_y*s->mb_stride;
mb_type = s->current_picture.mb_type[mb_xy];
qp = s->current_picture.qscale_table[mb_xy];
qp0 = s->current_picture.qscale_table[mb_xy-1];
}
}
+/**
+ * Returns and optionally allocates SPS / PPS structures in the supplied array 'vec'
+ */
+static void *
+alloc_parameter_set(H264Context *h, void **vec, const unsigned int id, const unsigned int max,
+ const size_t size, const char *name)
+{
+ if(id>=max) {
+ av_log(h->s.avctx, AV_LOG_ERROR, "%s_id (%d) out of range\n", name, id);
+ return NULL;
+ }
+
+ if(!vec[id]) {
+ vec[id] = av_mallocz(size);
+ if(vec[id] == NULL)
+ av_log(h->s.avctx, AV_LOG_ERROR, "cannot allocate memory for %s\n", name);
+ }
+ return vec[id];
+}
+
static inline int decode_seq_parameter_set(H264Context *h){
MpegEncContext * const s = &h->s;
int profile_idc, level_idc;
level_idc= get_bits(&s->gb, 8);
sps_id= get_ue_golomb(&s->gb);
- if (sps_id >= MAX_SPS_COUNT){
- // ok it has gone out of hand, someone is sending us bad stuff.
- av_log(h->s.avctx, AV_LOG_ERROR, "illegal sps_id (%d)\n", sps_id);
+ sps = alloc_parameter_set(h, (void **)h->sps_buffers, sps_id, MAX_SPS_COUNT, sizeof(SPS), "sps");
+ if(sps == NULL)
return -1;
- }
- sps= &h->sps_buffer[ sps_id ];
sps->profile_idc= profile_idc;
sps->level_idc= level_idc;
unsigned int tmp, pps_id= get_ue_golomb(&s->gb);
PPS *pps;
- if(pps_id>=MAX_PPS_COUNT){
- av_log(h->s.avctx, AV_LOG_ERROR, "pps_id out of range\n");
+ pps = alloc_parameter_set(h, (void **)h->pps_buffers, pps_id, MAX_PPS_COUNT, sizeof(PPS), "pps");
+ if(pps == NULL)
return -1;
- }
- pps = &h->pps_buffer[pps_id];
tmp= get_ue_golomb(&s->gb);
- if(tmp>=MAX_SPS_COUNT){
+ if(tmp>=MAX_SPS_COUNT || h->sps_buffers[tmp] == NULL){
av_log(h->s.avctx, AV_LOG_ERROR, "sps_id out of range\n");
return -1;
}
if(get_bits_count(&s->gb) < bit_length){
pps->transform_8x8_mode= get_bits1(&s->gb);
- decode_scaling_matrices(h, &h->sps_buffer[pps->sps_id], pps, 0, pps->scaling_matrix4, pps->scaling_matrix8);
+ decode_scaling_matrices(h, h->sps_buffers[pps->sps_id], pps, 0, pps->scaling_matrix4, pps->scaling_matrix8);
get_se_golomb(&s->gb); //second_chroma_qp_index_offset
}
buf_index += consumed;
- if( (s->hurry_up == 1 && h->nal_ref_idc == 0) //FIXME dont discard SEI id
+ if( (s->hurry_up == 1 && h->nal_ref_idc == 0) //FIXME do not discard SEI id
||(avctx->skip_frame >= AVDISCARD_NONREF && h->nal_ref_idc == 0))
continue;
return pos;
}else{
- if(pos==0) pos=1; //avoid infinite loops (i doubt thats needed but ...)
+ if(pos==0) pos=1; //avoid infinite loops (i doubt that is needed but ...)
if(pos+10>buf_size) pos=buf_size; // oops ;)
return pos;
START_TIMER
j= get_ue_golomb(&gb);
if(j != i){
- printf("missmatch! at %d (%d should be %d) bits:%6X\n", i, j, i, s);
+ printf("mismatch! at %d (%d should be %d) bits:%6X\n", i, j, i, s);
// return -1;
}
STOP_TIMER("get_ue_golomb");
START_TIMER
j= get_se_golomb(&gb);
if(j != i - COUNT/2){
- printf("missmatch! at %d (%d should be %d) bits:%6X\n", i, j, i, s);
+ printf("mismatch! at %d (%d should be %d) bits:%6X\n", i, j, i, s);
// return -1;
}
STOP_TIMER("get_se_golomb");
}
if(memcmp(bitstream, out, COUNT)){
- printf("missmatch\n");
+ printf("mismatch\n");
return -1;
}
}