static uint8_t *decode_nal(H264Context *h, 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;
return src;
}
- h->rbsp_buffer= av_fast_realloc(h->rbsp_buffer, &h->rbsp_buffer_size, length);
- dst= h->rbsp_buffer;
+ bufidx = h->nal_unit_type == NAL_DPC ? 1 : 0; // use second escape buffer for inter data
+ h->rbsp_buffer[bufidx]= av_fast_realloc(h->rbsp_buffer[bufidx], &h->rbsp_buffer_size[bufidx], length);
+ dst= h->rbsp_buffer[bufidx];
if (dst == NULL){
return NULL;
*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;
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);
}
return 0;
}
-static int decode_ref_pic_marking(H264Context *h){
+static int decode_ref_pic_marking(H264Context *h, GetBitContext *gb){
MpegEncContext * const s = &h->s;
int i;
if(h->nal_unit_type == NAL_IDR_SLICE){ //FIXME fields
- s->broken_link= get_bits1(&s->gb) -1;
- h->mmco[0].long_index= get_bits1(&s->gb) - 1; // current_long_term_idx
+ s->broken_link= get_bits1(gb) -1;
+ h->mmco[0].long_index= get_bits1(gb) - 1; // current_long_term_idx
if(h->mmco[0].long_index == -1)
h->mmco_index= 0;
else{
h->mmco_index= 1;
}
}else{
- if(get_bits1(&s->gb)){ // adaptive_ref_pic_marking_mode_flag
+ if(get_bits1(gb)){ // adaptive_ref_pic_marking_mode_flag
for(i= 0; i<MAX_MMCO_COUNT; i++) {
- MMCOOpcode opcode= get_ue_golomb(&s->gb);;
+ MMCOOpcode opcode= get_ue_golomb(gb);
h->mmco[i].opcode= opcode;
if(opcode==MMCO_SHORT2UNUSED || opcode==MMCO_SHORT2LONG){
- h->mmco[i].short_frame_num= (h->frame_num - get_ue_golomb(&s->gb) - 1) & ((1<<h->sps.log2_max_frame_num)-1); //FIXME fields
+ h->mmco[i].short_frame_num= (h->frame_num - get_ue_golomb(gb) - 1) & ((1<<h->sps.log2_max_frame_num)-1); //FIXME fields
/* if(h->mmco[i].short_frame_num >= h->short_ref_count || h->short_ref[ h->mmco[i].short_frame_num ] == NULL){
av_log(s->avctx, AV_LOG_ERROR, "illegal short ref in memory management control operation %d\n", mmco);
return -1;
}*/
}
if(opcode==MMCO_SHORT2LONG || opcode==MMCO_LONG2UNUSED || opcode==MMCO_LONG || opcode==MMCO_SET_MAX_LONG){
- unsigned int long_index= get_ue_golomb(&s->gb);
+ unsigned int long_index= get_ue_golomb(gb);
if(/*h->mmco[i].long_index >= h->long_ref_count || h->long_ref[ h->mmco[i].long_index ] == NULL*/ long_index >= 16){
av_log(h->s.avctx, AV_LOG_ERROR, "illegal long ref in memory management control operation %d\n", opcode);
return -1;
return 0;
}
+
+/**
+ * initialize scan tables
+ */
+static void init_scan_tables(H264Context *h){
+ MpegEncContext * const s = &h->s;
+ int i;
+ if(s->dsp.h264_idct_add == ff_h264_idct_add_c){ //FIXME little ugly
+ memcpy(h->zigzag_scan, zigzag_scan, 16*sizeof(uint8_t));
+ memcpy(h-> field_scan, field_scan, 16*sizeof(uint8_t));
+ }else{
+ for(i=0; i<16; i++){
+#define T(x) (x>>2) | ((x<<2) & 0xF)
+ h->zigzag_scan[i] = T(zigzag_scan[i]);
+ h-> field_scan[i] = T( field_scan[i]);
+#undef T
+ }
+ }
+ if(s->dsp.h264_idct8_add == ff_h264_idct8_add_c){
+ memcpy(h->zigzag_scan8x8, zigzag_scan8x8, 64*sizeof(uint8_t));
+ memcpy(h->zigzag_scan8x8_cavlc, zigzag_scan8x8_cavlc, 64*sizeof(uint8_t));
+ memcpy(h->field_scan8x8, field_scan8x8, 64*sizeof(uint8_t));
+ memcpy(h->field_scan8x8_cavlc, field_scan8x8_cavlc, 64*sizeof(uint8_t));
+ }else{
+ for(i=0; i<64; i++){
+#define T(x) (x>>3) | ((x&7)<<3)
+ h->zigzag_scan8x8[i] = T(zigzag_scan8x8[i]);
+ h->zigzag_scan8x8_cavlc[i] = T(zigzag_scan8x8_cavlc[i]);
+ h->field_scan8x8[i] = T(field_scan8x8[i]);
+ h->field_scan8x8_cavlc[i] = T(field_scan8x8_cavlc[i]);
+#undef T
+ }
+ }
+ if(h->sps.transform_bypass){ //FIXME same ugly
+ h->zigzag_scan_q0 = zigzag_scan;
+ h->zigzag_scan8x8_q0 = zigzag_scan8x8;
+ h->zigzag_scan8x8_cavlc_q0 = zigzag_scan8x8_cavlc;
+ h->field_scan_q0 = field_scan;
+ h->field_scan8x8_q0 = field_scan8x8;
+ h->field_scan8x8_cavlc_q0 = field_scan8x8_cavlc;
+ }else{
+ h->zigzag_scan_q0 = h->zigzag_scan;
+ h->zigzag_scan8x8_q0 = h->zigzag_scan8x8;
+ h->zigzag_scan8x8_cavlc_q0 = h->zigzag_scan8x8_cavlc;
+ h->field_scan_q0 = h->field_scan;
+ h->field_scan8x8_q0 = h->field_scan8x8;
+ h->field_scan8x8_cavlc_q0 = h->field_scan8x8_cavlc;
+ }
+}
/**
* decodes a slice header.
* this will allso call MPV_common_init() and frame_start() as needed
if (MPV_common_init(s) < 0)
return -1;
- if(s->dsp.h264_idct_add == ff_h264_idct_add_c){ //FIXME little ugly
- memcpy(h->zigzag_scan, zigzag_scan, 16*sizeof(uint8_t));
- memcpy(h-> field_scan, field_scan, 16*sizeof(uint8_t));
- }else{
- int i;
- for(i=0; i<16; i++){
-#define T(x) (x>>2) | ((x<<2) & 0xF)
- h->zigzag_scan[i] = T(zigzag_scan[i]);
- h-> field_scan[i] = T( field_scan[i]);
-#undef T
- }
- }
- if(s->dsp.h264_idct8_add == ff_h264_idct8_add_c){
- memcpy(h->zigzag_scan8x8, zigzag_scan8x8, 64*sizeof(uint8_t));
- memcpy(h->zigzag_scan8x8_cavlc, zigzag_scan8x8_cavlc, 64*sizeof(uint8_t));
- memcpy(h->field_scan8x8, field_scan8x8, 64*sizeof(uint8_t));
- memcpy(h->field_scan8x8_cavlc, field_scan8x8_cavlc, 64*sizeof(uint8_t));
- }else{
- int i;
- for(i=0; i<64; i++){
-#define T(x) (x>>3) | ((x&7)<<3)
- h->zigzag_scan8x8[i] = T(zigzag_scan8x8[i]);
- h->zigzag_scan8x8_cavlc[i] = T(zigzag_scan8x8_cavlc[i]);
- h->field_scan8x8[i] = T(field_scan8x8[i]);
- h->field_scan8x8_cavlc[i] = T(field_scan8x8_cavlc[i]);
-#undef T
- }
- }
- if(h->sps.transform_bypass){ //FIXME same ugly
- h->zigzag_scan_q0 = zigzag_scan;
- h->zigzag_scan8x8_q0 = zigzag_scan8x8;
- h->zigzag_scan8x8_cavlc_q0 = zigzag_scan8x8_cavlc;
- h->field_scan_q0 = field_scan;
- h->field_scan8x8_q0 = field_scan8x8;
- h->field_scan8x8_cavlc_q0 = field_scan8x8_cavlc;
- }else{
- h->zigzag_scan_q0 = h->zigzag_scan;
- h->zigzag_scan8x8_q0 = h->zigzag_scan8x8;
- h->zigzag_scan8x8_cavlc_q0 = h->zigzag_scan8x8_cavlc;
- h->field_scan_q0 = h->field_scan;
- h->field_scan8x8_q0 = h->field_scan8x8;
- h->field_scan8x8_cavlc_q0 = h->field_scan8x8_cavlc;
- }
-
+ init_scan_tables(h);
alloc_tables(h);
s->avctx->width = s->width;
h->use_weight = 0;
if(s->current_picture.reference)
- decode_ref_pic_marking(h);
+ decode_ref_pic_marking(h, &s->gb);
if(FRAME_MBAFF)
fill_mbaff_ref_list(h);
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;
eos = get_cabac_terminate( &h->cabac );
if( ret < 0 || h->cabac.bytestream > h->cabac.bytestream_end + 2) {
- av_log(h->s.avctx, AV_LOG_ERROR, "error while decoding MB %d %d, bytestream (%d)\n", s->mb_x, s->mb_y, h->cabac.bytestream_end - h->cabac.bytestream);
+ av_log(h->s.avctx, AV_LOG_ERROR, "error while decoding MB %d %d, bytestream (%td)\n", s->mb_x, s->mb_y, h->cabac.bytestream_end - h->cabac.bytestream);
ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x, s->mb_y, (AC_ERROR|DC_ERROR|MV_ERROR)&part_mask);
return -1;
}
uint8_t *ptr;
int i, nalsize = 0;
- if(h->is_avc) {
- if(buf_index >= buf_size) break;
- nalsize = 0;
- for(i = 0; i < h->nal_length_size; i++)
- nalsize = (nalsize << 8) | buf[buf_index++];
- if(nalsize <= 1 || (nalsize+buf_index > buf_size)){
- if(nalsize == 1){
- buf_index++;
- continue;
- }else{
- av_log(h->s.avctx, AV_LOG_ERROR, "AVC: nal size %d\n", nalsize);
- break;
+ if(h->is_avc) {
+ if(buf_index >= buf_size) break;
+ nalsize = 0;
+ for(i = 0; i < h->nal_length_size; i++)
+ nalsize = (nalsize << 8) | buf[buf_index++];
+ if(nalsize <= 1 || (nalsize+buf_index > buf_size)){
+ if(nalsize == 1){
+ buf_index++;
+ continue;
+ }else{
+ av_log(h->s.avctx, AV_LOG_ERROR, "AVC: nal size %d\n", nalsize);
+ break;
+ }
+ }
+ } else {
+ // start code prefix search
+ for(; buf_index + 3 < buf_size; buf_index++){
+ // This should always succeed in the first iteration.
+ if(buf[buf_index] == 0 && buf[buf_index+1] == 0 && buf[buf_index+2] == 1)
+ break;
}
- }
- } else {
- // start code prefix search
- for(; buf_index + 3 < buf_size; buf_index++){
- // This should always succeed in the first iteration.
- if(buf[buf_index] == 0 && buf[buf_index+1] == 0 && buf[buf_index+2] == 1)
- break;
- }
- if(buf_index+3 >= buf_size) break;
+ if(buf_index+3 >= buf_size) break;
- buf_index+=3;
- }
+ buf_index+=3;
+ }
ptr= decode_nal(h, buf + buf_index, &dst_length, &consumed, h->is_avc ? nalsize : buf_size - buf_index);
if (ptr==NULL || dst_length < 0){
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;
}
}
H264Context *h = avctx->priv_data;
MpegEncContext *s = &h->s;
- av_freep(&h->rbsp_buffer);
+ av_freep(&h->rbsp_buffer[0]);
+ av_freep(&h->rbsp_buffer[1]);
free_tables(h); //FIXME cleanup init stuff perhaps
MPV_common_end(s);