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_MBAFF || FIELD_PICTURE);
+ const int pic_height = 16*s->mb_height >> MB_FIELD;
if(!pic->data[0]) //FIXME this is unacceptable, some senseable error concealment must be done for missing reference frames
return;
if(ENABLE_GRAY && s->flags&CODEC_FLAG_GRAY) return;
- if(MB_MBAFF || FIELD_PICTURE){
+ if(MB_FIELD){
// chroma offset when predicting from a field of opposite parity
- my += 2 * ((s->mb_y & 1) - (h->ref_cache[list][scan8[n]] & 1));
+ my += 2 * ((s->mb_y & 1) - (pic->reference - 1));
emu |= (my>>3) < 0 || (my>>3) + 8 >= (pic_height>>1);
}
src_cb= pic->data[1] + (mx>>3) + (my>>3)*h->mb_uvlinesize;
dest_cb += x_offset + y_offset*h->mb_uvlinesize;
dest_cr += x_offset + y_offset*h->mb_uvlinesize;
x_offset += 8*s->mb_x;
- y_offset += 8*(s->mb_y >> (MB_MBAFF || FIELD_PICTURE));
+ y_offset += 8*(s->mb_y >> MB_FIELD);
if(list0){
Picture *ref= &h->ref_list[0][ h->ref_cache[0][ scan8[n] ] ];
dest_cb += x_offset + y_offset*h->mb_uvlinesize;
dest_cr += x_offset + y_offset*h->mb_uvlinesize;
x_offset += 8*s->mb_x;
- y_offset += 8*(s->mb_y >> (MB_MBAFF || FIELD_PICTURE));
+ y_offset += 8*(s->mb_y >> MB_FIELD);
if(list0 && list1){
/* don't optimize for luma-only case, since B-frames usually
else hl_decode_mb_simple(h);
}
-static void pic_as_field(Picture *pic, const int bottom){
+static void pic_as_field(Picture *pic, const int parity){
int i;
for (i = 0; i < 4; ++i) {
- if (bottom)
+ if (parity == PICT_BOTTOM_FIELD)
pic->data[i] += pic->linesize[i];
+ pic->reference = parity;
pic->linesize[i] *= 2;
}
}
if (match) {
*dest = *src;
- pic_as_field(dest, parity == PICT_BOTTOM_FIELD);
+ pic_as_field(dest, parity);
dest->pic_id *= 2;
dest->pic_id += id_add;
}
const unsigned int abs_diff_pic_num= get_ue_golomb(&s->gb) + 1;
int frame_num;
- if(abs_diff_pic_num >= h->max_pic_num){
+ if(abs_diff_pic_num > h->max_pic_num){
av_log(h->s.avctx, AV_LOG_ERROR, "abs_diff_pic_num overflow\n");
return -1;
}
}
h->ref_list[list][index]= *ref;
if (FIELD_PICTURE){
- int bot = pic_structure == PICT_BOTTOM_FIELD;
- pic_as_field(&h->ref_list[list][index], bot);
+ pic_as_field(&h->ref_list[list][index], pic_structure);
}
}
}else{
field[0] = *frame;
for(j=0; j<3; j++)
field[0].linesize[j] <<= 1;
+ field[0].reference = PICT_TOP_FIELD;
field[1] = field[0];
for(j=0; j<3; j++)
field[1].data[j] += frame->linesize[j];
+ field[1].reference = PICT_BOTTOM_FIELD;
h->luma_weight[list][16+2*i] = h->luma_weight[list][16+2*i+1] = h->luma_weight[list][i];
h->luma_offset[list][16+2*i] = h->luma_offset[list][16+2*i+1] = h->luma_offset[list][i];
idr(h);
if(h->s.current_picture_ptr)
h->s.current_picture_ptr->reference= 0;
+ h->s.first_field= 0;
}
/**
dst->s.current_picture = src->s.current_picture;
dst->s.linesize = src->s.linesize;
dst->s.uvlinesize = src->s.uvlinesize;
+ dst->s.first_field = src->s.first_field;
dst->prev_poc_msb = src->prev_poc_msb;
dst->prev_poc_lsb = src->prev_poc_lsb;
*/
static int decode_slice_header(H264Context *h, H264Context *h0){
MpegEncContext * const s = &h->s;
+ MpegEncContext * const s0 = &h0->s;
unsigned int first_mb_in_slice;
unsigned int pps_id;
int num_ref_idx_active_override_flag;
static const uint8_t slice_type_map[5]= {P_TYPE, B_TYPE, I_TYPE, SP_TYPE, SI_TYPE};
unsigned int slice_type, tmp, i;
int default_ref_list_done = 0;
+ int last_pic_structure;
s->dropable= h->nal_ref_idc == 0;
if((s->flags2 & CODEC_FLAG2_CHUNKS) && first_mb_in_slice == 0){
h0->current_slice = 0;
- s->current_picture_ptr= NULL;
+ if (!s0->first_field)
+ s->current_picture_ptr= NULL;
}
slice_type= get_ue_golomb(&s->gb);
return -1; // we cant (re-)initialize context during parallel decoding
if (MPV_common_init(s) < 0)
return -1;
+ s->first_field = 0;
init_scan_tables(h);
alloc_tables(h);
h->mb_mbaff = 0;
h->mb_aff_frame = 0;
+ last_pic_structure = s0->picture_structure;
if(h->sps.frame_mbs_only_flag){
s->picture_structure= PICT_FRAME;
}else{
if(get_bits1(&s->gb)) { //field_pic_flag
s->picture_structure= PICT_TOP_FIELD + get_bits1(&s->gb); //bottom_field_flag
- av_log(h->s.avctx, AV_LOG_ERROR, "PAFF interlacing is not implemented\n");
} else {
s->picture_structure= PICT_FRAME;
h->mb_aff_frame = h->sps.mb_aff;
}
if(h0->current_slice == 0){
- if(frame_start(h) < 0)
+ /* See if we have a decoded first field looking for a pair... */
+ if (s0->first_field) {
+ assert(s0->current_picture_ptr);
+ assert(s0->current_picture_ptr->data[0]);
+ assert(s0->current_picture_ptr->reference != DELAYED_PIC_REF);
+
+ /* figure out if we have a complementary field pair */
+ if (!FIELD_PICTURE || s->picture_structure == last_pic_structure) {
+ /*
+ * Previous field is unmatched. Don't display it, but let it
+ * remain for reference if marked as such.
+ */
+ s0->current_picture_ptr = NULL;
+ s0->first_field = FIELD_PICTURE;
+
+ } else {
+ if (h->nal_ref_idc &&
+ s0->current_picture_ptr->reference &&
+ s0->current_picture_ptr->frame_num != h->frame_num) {
+ /*
+ * This and previous field were reference, but had
+ * different frame_nums. Consider this field first in
+ * pair. Throw away previous field except for reference
+ * purposes.
+ */
+ s0->first_field = 1;
+ s0->current_picture_ptr = NULL;
+
+ } else {
+ /* Second field in complementary pair */
+ s0->first_field = 0;
+ }
+ }
+
+ } else {
+ /* Frame or first field in a potentially complementary pair */
+ assert(!s0->current_picture_ptr);
+ s0->first_field = FIELD_PICTURE;
+ }
+
+ if((!FIELD_PICTURE || s0->first_field) && frame_start(h) < 0) {
+ s0->first_field = 0;
return -1;
+ }
}
if(h != h0)
clone_slice(h, h0);
if(h->slice_type == P_TYPE || h->slice_type == SP_TYPE || h->slice_type == B_TYPE){
if(h->slice_type == B_TYPE){
h->direct_spatial_mv_pred= get_bits1(&s->gb);
- if(h->sps.mb_aff && h->direct_spatial_mv_pred)
- av_log(h->s.avctx, AV_LOG_ERROR, "MBAFF + spatial direct mode is not implemented\n");
+ if(FIELD_OR_MBAFF_PICTURE && h->direct_spatial_mv_pred)
+ av_log(h->s.avctx, AV_LOG_ERROR, "Interlaced pictures + spatial direct mode is not implemented\n");
}
num_ref_idx_active_override_flag= get_bits1(&s->gb);
(h->slice_type == B_TYPE), edges, step, mask_edge0, mask_edge1 );
}
if( IS_INTRA(s->current_picture.mb_type[mb_xy-1]) )
- bSv[0][0] = FIELD_PICTURE ? 0x0003000300030003ULL : 0x0004000400040004ULL;
+ bSv[0][0] = 0x0004000400040004ULL;
if( IS_INTRA(s->current_picture.mb_type[h->top_mb_xy]) )
- bSv[1][0] = 0x0004000400040004ULL;
+ bSv[1][0] = FIELD_PICTURE ? 0x0003000300030003ULL : 0x0004000400040004ULL;
#define FILTER(hv,dir,edge)\
if(bSv[dir][edge]) {\
hx = h->thread_context[context_count - 1];
s->mb_x = hx->s.mb_x;
s->mb_y = hx->s.mb_y;
+ s->dropable = hx->s.dropable;
+ s->picture_structure = hx->s.picture_structure;
for(i = 1; i < context_count; i++)
h->s.error_count += h->thread_context[i]->s.error_count;
}
#endif
if(!(s->flags2 & CODEC_FLAG2_CHUNKS)){
h->current_slice = 0;
- s->current_picture_ptr= NULL;
+ if (!s->first_field)
+ s->current_picture_ptr= NULL;
}
for(;;){
h->prev_frame_num_offset= h->frame_num_offset;
h->prev_frame_num= h->frame_num;
- if(s->current_picture_ptr->reference & s->picture_structure){
+ if(!s->dropable) {
h->prev_poc_msb= h->poc_msb;
h->prev_poc_lsb= h->poc_lsb;
execute_ref_pic_marking(h, h->mmco, h->mmco_index);
}
- ff_er_frame_end(s);
+ /*
+ * FIXME: Error handling code does not seem to support interlaced
+ * when slices span multiple rows
+ * The ff_er_add_slice calls don't work right for bottom
+ * fields; they cause massive erroneous error concealing
+ * Error marking covers both fields (top and bottom).
+ * This causes a mismatched s->error_count
+ * and a bad error table. Further, the error count goes to
+ * INT_MAX when called for bottom field, because mb_y is
+ * past end by one (callers fault) and resync_mb_y != 0
+ * causes problems for the first MB line, too.
+ */
+ if (!FIELD_PICTURE)
+ ff_er_frame_end(s);
MPV_frame_end(s);
- //FIXME do something with unavailable reference frames
+ if (s->first_field) {
+ /* Wait for second field. */
+ *data_size = 0;
+
+ } else {
+ //FIXME do something with unavailable reference frames
#if 0 //decode order
- *data_size = sizeof(AVFrame);
+ *data_size = sizeof(AVFrame);
#else
- /* 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;
- }
-
- pics = 0;
- while(h->delayed_pic[pics]) pics++;
+ /* Sort B-frames into display order */
- assert(pics+1 < sizeof(h->delayed_pic) / sizeof(h->delayed_pic[0]));
+ 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;
+ }
- h->delayed_pic[pics++] = cur;
- if(cur->reference == 0)
- cur->reference = DELAYED_PIC_REF;
+ pics = 0;
+ while(h->delayed_pic[pics]) pics++;
- cross_idr = 0;
- for(i=0; h->delayed_pic[i]; i++)
- if(h->delayed_pic[i]->key_frame || h->delayed_pic[i]->poc==0)
- cross_idr = 1;
+ assert(pics+1 < sizeof(h->delayed_pic) / sizeof(h->delayed_pic[0]));
- out = h->delayed_pic[0];
- out_idx = 0;
- for(i=1; h->delayed_pic[i] && !h->delayed_pic[i]->key_frame; i++)
- if(h->delayed_pic[i]->poc < out->poc){
- out = h->delayed_pic[i];
- out_idx = i;
- }
+ h->delayed_pic[pics++] = cur;
+ if(cur->reference == 0)
+ cur->reference = DELAYED_PIC_REF;
- out_of_order = !cross_idr && prev && out->poc < prev->poc;
- if(h->sps.bitstream_restriction_flag && s->avctx->has_b_frames >= h->sps.num_reorder_frames)
- { }
- else if(prev && pics <= s->avctx->has_b_frames)
- out = prev;
- else if((out_of_order && pics-1 == s->avctx->has_b_frames && pics < 15)
- || (s->low_delay &&
- ((!cross_idr && prev && out->poc > prev->poc + 2)
- || cur->pict_type == B_TYPE)))
- {
- s->low_delay = 0;
- s->avctx->has_b_frames++;
- out = prev;
- }
- else if(out_of_order)
- out = prev;
+ cross_idr = 0;
+ for(i=0; h->delayed_pic[i]; i++)
+ if(h->delayed_pic[i]->key_frame || h->delayed_pic[i]->poc==0)
+ cross_idr = 1;
- if(out_of_order || pics > s->avctx->has_b_frames){
- for(i=out_idx; h->delayed_pic[i]; i++)
- h->delayed_pic[i] = h->delayed_pic[i+1];
- }
+ out = h->delayed_pic[0];
+ out_idx = 0;
+ for(i=1; h->delayed_pic[i] && !h->delayed_pic[i]->key_frame; i++)
+ if(h->delayed_pic[i]->poc < out->poc){
+ out = h->delayed_pic[i];
+ out_idx = i;
+ }
- if(prev == out)
- *data_size = 0;
- else
- *data_size = sizeof(AVFrame);
- if(prev && prev != out && prev->reference == DELAYED_PIC_REF)
- prev->reference = 0;
- h->delayed_output_pic = out;
+ out_of_order = !cross_idr && prev && out->poc < prev->poc;
+ if(h->sps.bitstream_restriction_flag && s->avctx->has_b_frames >= h->sps.num_reorder_frames)
+ { }
+ else if(prev && pics <= s->avctx->has_b_frames)
+ out = prev;
+ else if((out_of_order && pics-1 == s->avctx->has_b_frames && pics < 15)
+ || (s->low_delay &&
+ ((!cross_idr && prev && out->poc > prev->poc + 2)
+ || cur->pict_type == B_TYPE)))
+ {
+ s->low_delay = 0;
+ s->avctx->has_b_frames++;
+ out = prev;
+ }
+ else if(out_of_order)
+ out = prev;
+
+ if(out_of_order || pics > s->avctx->has_b_frames){
+ for(i=out_idx; h->delayed_pic[i]; i++)
+ h->delayed_pic[i] = h->delayed_pic[i+1];
+ }
+
+ if(prev == out)
+ *data_size = 0;
+ else
+ *data_size = sizeof(AVFrame);
+ if(prev && prev != out && prev->reference == DELAYED_PIC_REF)
+ prev->reference = 0;
+ h->delayed_output_pic = out;
#endif
- if(out)
- *pict= *(AVFrame*)out;
- else
- av_log(avctx, AV_LOG_DEBUG, "no picture\n");
+ if(out)
+ *pict= *(AVFrame*)out;
+ else
+ av_log(avctx, AV_LOG_DEBUG, "no picture\n");
+ }
}
assert(pict->data[0] || !*data_size);
/* we substract 1 because it is added on utils.c */
avctx->frame_number = s->picture_number - 1;
#endif
+ pict->interlaced_frame = FIELD_OR_MBAFF_PICTURE;
return get_consumed_bytes(s, buf_index, buf_size);
}
#if 0