media: mfc: Fix the reference count pair.
authorJeonghee Kim <jhhhh.kim@samsung.com>
Thu, 8 Mar 2018 09:31:09 +0000 (18:31 +0900)
committerSunyoung Kang <sy0816.kang@samsung.com>
Tue, 29 May 2018 06:59:18 +0000 (15:59 +0900)
When decoding and display status,
the release information of the referenced buffers without display should not be updated.
It will be reused.

When decoding only status,
the release information of the referenced buffers(except for reused buffer)
should be left to update when displayed.
It is an already displayed buffer.

Change-Id: I37df2bfd9d6cd3defde26edf1f2ac46ebb42ae8e
Signed-off-by: Jeonghee Kim <jhhhh.kim@samsung.com>
drivers/media/platform/exynos/mfc/s5p_mfc_irq.c
drivers/media/platform/exynos/mfc/s5p_mfc_nal_q.c
drivers/media/platform/exynos/mfc/s5p_mfc_queue.c
drivers/media/platform/exynos/mfc/s5p_mfc_queue.h

index e6237215a735a1d7eb5fc1abfd9346f0ef81e0e7..4843b02b89083273dd06a4ab72692606bde10482 100644 (file)
@@ -508,10 +508,14 @@ static void mfc_handle_reuse_buffer(struct s5p_mfc_ctx *ctx)
        if (!released_flag)
                return;
 
-       /* reuse not referenced buf anymore */
+       /* Reuse not referenced buf anymore */
        for (i = 0; i < MFC_MAX_DPBS; i++)
                if (released_flag & (1 << i))
-                       s5p_mfc_move_reuse_buffer(ctx, i);
+                       if (s5p_mfc_move_reuse_buffer(ctx, i))
+                               released_flag &= ~(1 << i);
+
+       /* Not reused buffer should be released when there is a display frame */
+       dec->dynamic_used |= released_flag;
 }
 
 static void mfc_handle_frame_input(struct s5p_mfc_ctx *ctx, unsigned int err)
index 0124bf551fafdb96689261eb0a109a39bdbb53a9..821815e01ee63f6829903485ddc32301cc00a7b4 100644 (file)
@@ -1058,8 +1058,11 @@ static void mfc_nal_q_handle_reuse_buffer(struct s5p_mfc_ctx *ctx, DecoderOutput
 
        for (i = 0; i < MFC_MAX_DPBS; i++)
                if (released_flag & (1 << i))
-                       s5p_mfc_move_reuse_buffer(ctx, i);
+                       if (s5p_mfc_move_reuse_buffer(ctx, i))
+                               released_flag &= ~(1 << i);
 
+       /* Not reused buffer should be released when there is a display frame */
+       dec->dynamic_used |= released_flag;
 }
 
 static void mfc_nal_q_handle_ref_frame(struct s5p_mfc_ctx *ctx, DecoderOutputStr *pOutStr)
index 6acc904bda1944e7a578a2c8f6bbddb770c5d92a..9e701ca60d76c5abb6a03b360cf2a10c9a74a30b 100644 (file)
@@ -581,10 +581,33 @@ static void mfc_cleanup_batch_queue(struct s5p_mfc_ctx *ctx, struct s5p_mfc_buf_
        spin_unlock_irqrestore(&ctx->buf_queue_lock, flags);
 }
 
+struct s5p_mfc_buf *mfc_find_buf_index(spinlock_t *plock, struct s5p_mfc_buf_queue *queue,
+               int index)
+{
+       unsigned long flags;
+       struct s5p_mfc_buf *mfc_buf = NULL;
+       int buf_index;
+
+       spin_lock_irqsave(plock, flags);
+
+       mfc_debug(2, "Looking for index: %d\n", index);
+       list_for_each_entry(mfc_buf, &queue->head, list) {
+               buf_index = mfc_buf->vb.vb2_buf.index;
+
+               if (index == buf_index) {
+                       mfc_debug(2, "Found index: %d\n", buf_index);
+                       spin_unlock_irqrestore(plock, flags);
+                       return mfc_buf;
+               }
+       }
+
+       spin_unlock_irqrestore(plock, flags);
+       return NULL;
+}
+
 /*
- * Check released buffers are enqueued again.
- * s5p_mfc_dec.assigned_fd
- * s5p_mfc_dec.available_dpb
+ * Check released and enqueued buffers. (dst queue)
+ * Check and move reuse buffers. (ref -> dst queue)
  */
 static void mfc_check_ref_frame(spinlock_t *plock, struct s5p_mfc_buf_queue *dst_queue,
                struct s5p_mfc_buf_queue *ref_queue,
@@ -598,6 +621,7 @@ static void mfc_check_ref_frame(spinlock_t *plock, struct s5p_mfc_buf_queue *dst
 
        spin_lock_irqsave(plock, flags);
 
+       /* reuse buffers : error frame, decoding only frame (ref -> dst queue) */
        list_for_each_entry_safe(ref_mb, tmp_mb, &ref_queue->head, list) {
                index = ref_mb->vb.vb2_buf.index;
                if (index == ref_index) {
@@ -617,6 +641,7 @@ static void mfc_check_ref_frame(spinlock_t *plock, struct s5p_mfc_buf_queue *dst
                }
        }
 
+       /* released and enqueued buffers (dst queue) */
        if (!found) {
                list_for_each_entry_safe(ref_mb, tmp_mb, &dst_queue->head, list) {
                        index = ref_mb->vb.vb2_buf.index;
@@ -653,10 +678,17 @@ void s5p_mfc_handle_released_info(struct s5p_mfc_ctx *ctx,
                for (t = 0; t < MFC_MAX_DPBS; t++) {
                        if (released_flag & (1 << t)) {
                                if (dec->err_reuse_flag & (1 << t)) {
-                                       mfc_debug(2, "Released, but reuse. FD[%d] = %03d\n",
+                                       /* reuse buffer with error : do not update released info */
+                                       mfc_debug(2, "Released, but reuse(error frame). FD[%d] = %03d\n",
                                                        t, dec->assigned_fd[t]);
                                        dec->err_reuse_flag &= ~(1 << t);
+                               } else if ((t != index) &&
+                                               mfc_find_buf_index(&ctx->buf_queue_lock, &ctx->ref_buf_queue, t)) {
+                                       /* decoding only frame: do not update released info */
+                                       mfc_debug(2, "Released, but reuse(decoding only). FD[%d] = %03d\n",
+                                                       t, dec->assigned_fd[t]);
                                } else {
+                                       /* displayed and released frame */
                                        mfc_debug(2, "Release FD[%d] = %03d\n",
                                                        t, dec->assigned_fd[t]);
                                        refBuf->dpb[ncount].fd[0] = dec->assigned_fd[t];
@@ -673,7 +705,7 @@ void s5p_mfc_handle_released_info(struct s5p_mfc_ctx *ctx,
                refBuf->dpb[ncount].fd[0] = MFC_INFO_INIT_FD;
 }
 
-void s5p_mfc_move_reuse_buffer(struct s5p_mfc_ctx *ctx, int release_index)
+struct s5p_mfc_buf *s5p_mfc_move_reuse_buffer(struct s5p_mfc_ctx *ctx, int release_index)
 {
        struct s5p_mfc_dec *dec = ctx->dec_priv;
        struct s5p_mfc_buf_queue *dst_queue = &ctx->dst_buf_queue;
@@ -700,10 +732,14 @@ void s5p_mfc_move_reuse_buffer(struct s5p_mfc_ctx *ctx, int release_index)
 
                        clear_bit(index, &dec->available_dpb);
                        mfc_debug(2, "buffer[%d] is moved to dst queue for reuse\n", index);
+
+                       spin_unlock_irqrestore(plock, flags);
+                       return ref_mb;
                }
        }
 
        spin_unlock_irqrestore(plock, flags);
+       return NULL;
 }
 
 void s5p_mfc_cleanup_enc_src_queue(struct s5p_mfc_ctx *ctx)
index 3432f806e429f368e5e523f09ade7d78c977451b..ac7782e8bef187d62f79c4c4e04b09c5f7b5b2b3 100644 (file)
@@ -145,7 +145,7 @@ void s5p_mfc_cleanup_queue(spinlock_t *plock, struct s5p_mfc_buf_queue *queue);
 void s5p_mfc_handle_released_info(struct s5p_mfc_ctx *ctx,
                unsigned int released_flag, int index);
 
-void s5p_mfc_move_reuse_buffer(struct s5p_mfc_ctx *ctx, int release_index);
+struct s5p_mfc_buf *s5p_mfc_move_reuse_buffer(struct s5p_mfc_ctx *ctx, int release_index);
 
 void s5p_mfc_cleanup_enc_src_queue(struct s5p_mfc_ctx *ctx);
 void s5p_mfc_cleanup_enc_dst_queue(struct s5p_mfc_ctx *ctx);