nouveau/vdec: small fixes to h264 handling
authorMaarten Lankhorst <maarten.lankhorst@canonical.com>
Tue, 15 Apr 2014 15:35:31 +0000 (17:35 +0200)
committerMaarten Lankhorst <maarten.lankhorst@canonical.com>
Thu, 17 Apr 2014 08:30:39 +0000 (10:30 +0200)
nouveau_vp3_inter_sizes requires sliec_count as argument just
as the other places that call it from h264 code do. Hopefully
fixes something.

Fix the status_vp code to allow status == 0 too, when processing
hasn't started yet.

set h264->second_field correctly.

src/gallium/drivers/nouveau/nouveau_vp3_video.h
src/gallium/drivers/nouveau/nouveau_vp3_video_vp.c
src/gallium/drivers/nouveau/nv50/nv98_video_vp.c
src/gallium/drivers/nouveau/nvc0/nvc0_video_vp.c

index 88c14ec60ff67756304273778536d4e89af4af19..5c1af7104fc19b61d4195a6de3559dcc5a3a216b 100644 (file)
@@ -107,6 +107,7 @@ struct nouveau_vp3_decoder {
       unsigned field_pic_flag : 1;
       unsigned decoded_top : 1;
       unsigned decoded_bottom : 1;
+      unsigned decoded_first : 1;
    } refs[17];
    unsigned fence_seq, fw_sizes, last_frame_num, tmp_stride, ref_stride;
 
index 1130d100390685282213c916143e97da6d8a46af..1dcb99c1b525de37a73f9ee78a69629457678674 100644 (file)
@@ -169,19 +169,14 @@ struct h264_picparm_vp { // 700..a00
 static void
 nouveau_vp3_handle_references(struct nouveau_vp3_decoder *dec, struct nouveau_vp3_video_buffer *refs[16], unsigned seq, struct nouveau_vp3_video_buffer *target)
 {
-   unsigned h264 = u_reduce_video_profile(dec->base.profile) == PIPE_VIDEO_FORMAT_MPEG4_AVC;
-   unsigned i, idx, empty_spot = dec->base.max_references + 1;
+   unsigned i, idx, empty_spot = ~0;
+
    for (i = 0; i < dec->base.max_references; ++i) {
       if (!refs[i])
          continue;
 
       idx = refs[i]->valid_ref;
       //debug_printf("ref[%i] %p in slot %i\n", i, refs[i], idx);
-      assert(target != refs[i] ||
-             (h264 && empty_spot &&
-              (!dec->refs[idx].decoded_bottom || !dec->refs[idx].decoded_top)));
-      if (target == refs[i])
-         empty_spot = 0;
 
       if (dec->refs[idx].vidbuf != refs[i]) {
          debug_printf("%p is not a real ref\n", refs[i]);
@@ -192,26 +187,23 @@ nouveau_vp3_handle_references(struct nouveau_vp3_decoder *dec, struct nouveau_vp
       assert(dec->refs[idx].vidbuf == refs[i]);
       dec->refs[idx].last_used = seq;
    }
-   if (!empty_spot)
+
+   if (dec->refs[target->valid_ref].vidbuf == target) {
+      dec->refs[target->valid_ref].last_used = seq;
       return;
+   }
 
    /* Try to find a real empty spot first, there should be one..
     */
    for (i = 0; i < dec->base.max_references + 1; ++i) {
-      if (dec->refs[i].last_used < seq) {
-         if (!dec->refs[i].vidbuf) {
-            empty_spot = i;
-            break;
-         }
-         if (empty_spot < dec->base.max_references+1 &&
-             dec->refs[empty_spot].last_used < dec->refs[i].last_used)
-            continue;
+      if (dec->refs[i].last_used != seq) {
          empty_spot = i;
+         break;
       }
    }
    assert(empty_spot < dec->base.max_references+1);
    dec->refs[empty_spot].last_used = seq;
-//   debug_printf("Kicked %p to add %p to slot %i\n", dec->refs[empty_spot].vidbuf, target, i);
+//   debug_printf("Kicked %p to add %p to slot %i\n", dec->refs[empty_spot].vidbuf, target, empty_spot);
    dec->refs[empty_spot].vidbuf = target;
    dec->refs[empty_spot].decoded_bottom = dec->refs[empty_spot].decoded_top = 0;
    target->valid_ref = empty_spot;
@@ -335,7 +327,7 @@ nouveau_vp3_fill_picparm_h264_vp(struct nouveau_vp3_decoder *dec,
    h->ofs[0] = h->ofs[2] = 0;
    h->tmp_stride = dec->tmp_stride >> 8;
    assert(h->tmp_stride);
-   nouveau_vp3_inter_sizes(dec, 1, &ring, &h->bucket_size, &h->inter_ring_data_size);
+   nouveau_vp3_inter_sizes(dec, d->slice_count, &ring, &h->bucket_size, &h->inter_ring_data_size);
 
    h->u220 = 0;
    h->mb_adaptive_frame_field_flag = d->pps->sps->mb_adaptive_frame_field_flag;
@@ -345,7 +337,8 @@ nouveau_vp3_fill_picparm_h264_vp(struct nouveau_vp3_decoder *dec,
    h->is_reference = d->is_reference;
    h->interlace = d->field_pic_flag;
    h->bottom_field_flag = d->bottom_field_flag;
-   h->second_field = 0; // TODO: figure out when set..
+   h->second_field = 0; // set in nouveau_vp3_fill_picparm_h264_vp_refs
+
    h->log2_max_frame_num_minus4 = d->pps->sps->log2_max_frame_num_minus4;
    h->chroma_format_idc = 1;
 
@@ -360,7 +353,6 @@ nouveau_vp3_fill_picparm_h264_vp(struct nouveau_vp3_decoder *dec,
    h->u34_3030 = h->u34_3131 = 0;
    h->field_order_cnt[0] = d->field_order_cnt[0];
    h->field_order_cnt[1] = d->field_order_cnt[1];
-   memset(h->refs, 0, sizeof(h->refs));
    memcpy(h->m4x4, d->pps->ScalingList4x4, sizeof(h->m4x4));
    memcpy(h->m8x8, d->pps->ScalingList8x8, sizeof(h->m8x8));
    h->u220 = 0;
@@ -370,6 +362,7 @@ nouveau_vp3_fill_picparm_h264_vp(struct nouveau_vp3_decoder *dec,
       refs[j] = (struct nouveau_vp3_video_buffer *)d->ref[i];
       h->refs[j].fifo_idx = j + 1;
       h->refs[j].tmp_idx = refs[j]->valid_ref;
+      assert(dec->refs[refs[j]->valid_ref].vidbuf == refs[j]);
       h->refs[j].field_order_cnt[0] = d->field_order_cnt_list[i][0];
       h->refs[j].field_order_cnt[1] = d->field_order_cnt_list[i][1];
       h->refs[j].frame_idx = d->frame_num_list[i];
@@ -411,6 +404,12 @@ nouveau_vp3_fill_picparm_h264_vp_refs(struct nouveau_vp3_decoder *dec,
    assert(dec->refs[target->valid_ref].vidbuf == target);
 //    debug_printf("Target: %p\n", target);
 
+   if (!dec->refs[target->valid_ref].decoded_top &&
+       !dec->refs[target->valid_ref].decoded_bottom)
+      dec->refs[target->valid_ref].decoded_first = d->bottom_field_flag;
+   else if (dec->refs[target->valid_ref].decoded_first != d->bottom_field_flag)
+      h->second_field = 1;
+
    h->tmp_idx = target->valid_ref;
    dec->refs[target->valid_ref].field_pic_flag = d->field_pic_flag;
    if (!d->field_pic_flag || d->bottom_field_flag)
index 9b756ea73f56085dbf69160affd48d207b7e6b11..9cdb40ba025c7adc8fec7a1cb54c1be6ff1bc190 100644 (file)
@@ -39,7 +39,7 @@ static void dump_comm_vp(struct nouveau_vp3_decoder *dec, struct comm *comm, u32
                debug_printf("parse_endpos[%i] = { @ %08x}\n", i, comm->parse_endpos[i]);
 #endif
        debug_printf("mb_y = %u\n", comm->mb_y[idx]);
-       if (comm->status_vp[idx] == 1)
+       if (comm->status_vp[idx] <= 1)
                return;
 
        if ((comm->pvp_stage & 0xff) != 0xff) {
@@ -112,7 +112,7 @@ nv98_decoder_vp(struct nouveau_vp3_decoder *dec, union pipe_desc desc,
       else
          pic_addr[i] = null_addr;
    }
-   if (!is_ref)
+   if (!is_ref && (dec->refs[target->valid_ref].decoded_top && dec->refs[target->valid_ref].decoded_bottom))
       nv98_decoder_kick_ref(dec, target);
 
    nouveau_pushbuf_space(push, 8 + 3 * (codec != PIPE_VIDEO_FORMAT_MPEG12) +
index 0d152b9624f989f0f08161d807946600fa252d59..07170a0e4c376b83f7aedbfdb43fb5a7e92456ab 100644 (file)
@@ -39,7 +39,7 @@ static void dump_comm_vp(struct nouveau_vp3_decoder *dec, struct comm *comm, u32
                debug_printf("parse_endpos[%i] = { @ %08x}\n", i, comm->parse_endpos[i]);
 #endif
        debug_printf("mb_y = %u\n", comm->mb_y[idx]);
-       if (comm->status_vp[idx] == 1)
+       if (comm->status_vp[idx] <= 1)
                return;
 
        if ((comm->pvp_stage & 0xff) != 0xff) {
@@ -112,7 +112,7 @@ nvc0_decoder_vp(struct nouveau_vp3_decoder *dec, union pipe_desc desc,
       else
          pic_addr[i] = null_addr;
    }
-   if (!is_ref)
+   if (!is_ref && (dec->refs[target->valid_ref].decoded_top && dec->refs[target->valid_ref].decoded_bottom))
       nvc0_decoder_kick_ref(dec, target);
 
    nouveau_pushbuf_space(push, 8 + 3 * (codec != PIPE_VIDEO_FORMAT_MPEG12) +