nouveau: rework reference frame handling
authorMaarten Lankhorst <maarten.lankhorst@canonical.com>
Wed, 10 Sep 2014 11:20:53 +0000 (13:20 +0200)
committerIlia Mirkin <imirkin@alum.mit.edu>
Fri, 12 Sep 2014 03:18:05 +0000 (23:18 -0400)
Fixes a regression from "nouveau/vdec: small fixes to h264 handling"

New picking order for frames:
 1. Vidbuf pointer matches.
 2. Take the first kicked ref.
 3. If that fails, take a ref that has a different last_used.

Signed-off-by: Maarten Lankhorst <maarten.lankhorst@canonical.com>
Cc: "10.2 10.3" <mesa-stable@lists.freedesktop.org>
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 06d7046995baac33b9cb3f6eeabf74411f2a2b2b..edbc82b8dc8b5e811765986199dfbe0c0fb21a20 100644 (file)
@@ -196,11 +196,15 @@ nouveau_vp3_handle_references(struct nouveau_vp3_decoder *dec, struct nouveau_vp
    /* 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 == target) {
          empty_spot = i;
          break;
-      }
+      } else if (!dec->refs[i].last_used) {
+         empty_spot = i;
+      } else if (empty_spot == ~0U && dec->refs[i].last_used != seq)
+         empty_spot = i;
    }
+
    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, empty_spot);
@@ -463,14 +467,45 @@ void nouveau_vp3_vp_caps(struct nouveau_vp3_decoder *dec, union pipe_desc desc,
    case PIPE_VIDEO_FORMAT_MPEG12:
       *caps = nouveau_vp3_fill_picparm_mpeg12_vp(dec, desc.mpeg12, refs, is_ref, vp);
       nouveau_vp3_handle_references(dec, refs, dec->fence_seq, target);
+      switch (desc.mpeg12->picture_structure) {
+      case PIPE_MPEG12_PICTURE_STRUCTURE_FIELD_TOP:
+         dec->refs[target->valid_ref].decoded_top = 1;
+         break;
+      case PIPE_MPEG12_PICTURE_STRUCTURE_FIELD_BOTTOM:
+         dec->refs[target->valid_ref].decoded_bottom = 1;
+         break;
+      default:
+         dec->refs[target->valid_ref].decoded_top = 1;
+         dec->refs[target->valid_ref].decoded_bottom = 1;
+         break;
+      }
       return;
    case PIPE_VIDEO_FORMAT_MPEG4:
       *caps = nouveau_vp3_fill_picparm_mpeg4_vp(dec, desc.mpeg4, refs, is_ref, vp);
       nouveau_vp3_handle_references(dec, refs, dec->fence_seq, target);
+      // XXX: Correct?
+      if (!desc.mpeg4->interlaced) {
+         dec->refs[target->valid_ref].decoded_top = 1;
+         dec->refs[target->valid_ref].decoded_bottom = 1;
+      } else if (desc.mpeg4->top_field_first) {
+         if (!dec->refs[target->valid_ref].decoded_top)
+            dec->refs[target->valid_ref].decoded_top = 1;
+         else
+            dec->refs[target->valid_ref].decoded_bottom = 1;
+      } else {
+         if (!dec->refs[target->valid_ref].decoded_bottom)
+            dec->refs[target->valid_ref].decoded_bottom = 1;
+         else
+            dec->refs[target->valid_ref].decoded_top = 1;
+      }
       return;
    case PIPE_VIDEO_FORMAT_VC1: {
       *caps = nouveau_vp3_fill_picparm_vc1_vp(dec, desc.vc1, refs, is_ref, vp);
       nouveau_vp3_handle_references(dec, refs, dec->fence_seq, target);
+      if (desc.vc1->frame_coding_mode == 3)
+         debug_printf("Field-Interlaced possibly incorrectly handled\n");
+      dec->refs[target->valid_ref].decoded_top = 1;
+      dec->refs[target->valid_ref].decoded_bottom = 1;
       return;
    }
    case PIPE_VIDEO_FORMAT_MPEG4_AVC: {
index 9cdb40ba025c7adc8fec7a1cb54c1be6ff1bc190..e74abe286af081f80c41f8655a89f0b454cdf69e 100644 (file)
@@ -59,7 +59,6 @@ static void dump_comm_vp(struct nouveau_vp3_decoder *dec, struct comm *comm, u32
 static void
 nv98_decoder_kick_ref(struct nouveau_vp3_decoder *dec, struct nouveau_vp3_video_buffer *target)
 {
-   dec->refs[target->valid_ref].vidbuf = NULL;
    dec->refs[target->valid_ref].last_used = 0;
 //   debug_printf("Unreffed %p\n", target);
 }
index 07170a0e4c376b83f7aedbfdb43fb5a7e92456ab..33c73750d8ba32f744afa54231c2ceb85a16da49 100644 (file)
@@ -59,7 +59,6 @@ static void dump_comm_vp(struct nouveau_vp3_decoder *dec, struct comm *comm, u32
 static void
 nvc0_decoder_kick_ref(struct nouveau_vp3_decoder *dec, struct nouveau_vp3_video_buffer *target)
 {
-   dec->refs[target->valid_ref].vidbuf = NULL;
    dec->refs[target->valid_ref].last_used = 0;
 //   debug_printf("Unreffed %p\n", target);
 }