[vlc-devel] [PATCH 09/14] mmal/codec: Do not use local buffer pool in opaque mode

Julian Scheel julian at jusst.de
Wed Jun 3 09:50:34 CEST 2015


When running in opaque mode the codec must be used together with the mmal
vout. In this case each picture contains a mmal_buffer_header within the
picture_sys_t. That buffer header can be used instead of locally allocated
headers with the advantage of reducing complexity and avoiding possibly
error-prone mangling of buffer headers. Furthermore it is a prerequisite to
enable zero_copy mode on the ports.

Signed-off-by: Julian Scheel <julian at jusst.de>
---
 modules/hw/mmal/codec.c | 122 ++++++++++++++++++++++++++++++------------------
 1 file changed, 77 insertions(+), 45 deletions(-)

diff --git a/modules/hw/mmal/codec.c b/modules/hw/mmal/codec.c
index 7f20a17..e89b81d 100644
--- a/modules/hw/mmal/codec.c
+++ b/modules/hw/mmal/codec.c
@@ -68,7 +68,7 @@ struct decoder_sys_t {
     MMAL_PORT_T *input;
     MMAL_POOL_T *input_pool;
     MMAL_PORT_T *output;
-    MMAL_POOL_T *output_pool;
+    MMAL_POOL_T *output_pool; /* only used for non-opaque mode */
     MMAL_ES_FORMAT_T *output_format;
     MMAL_QUEUE_T *decoded_pictures;
     vlc_mutex_t mutex;
@@ -78,6 +78,7 @@ struct decoder_sys_t {
 
     /* statistics */
     int output_in_transit;
+    atomic_bool started;
 };
 
 /* Utilities */
@@ -262,10 +263,12 @@ static void CloseDecoder(decoder_t *dec)
         picture_t *pic = (picture_t *)buffer->user_data;
         picture_Release(pic);
 
-        buffer->user_data = NULL;
-        buffer->alloc_size = 0;
-        buffer->data = NULL;
-        mmal_buffer_header_release(buffer);
+        if (sys->output_pool) {
+            buffer->user_data = NULL;
+            buffer->alloc_size = 0;
+            buffer->data = NULL;
+            mmal_buffer_header_release(buffer);
+        }
     }
 
     if (sys->decoded_pictures)
@@ -290,7 +293,7 @@ static int change_output_format(decoder_t *dec)
     int pool_size;
     int ret = 0;
 
-    if (sys->output_pool) {
+    if (atomic_load(&sys->started)) {
         mmal_format_full_copy(sys->output->format, sys->output_format);
         status = mmal_port_format_commit(sys->output);
         if (status != MMAL_SUCCESS) {
@@ -340,9 +343,13 @@ port_reset:
         goto out;
     }
 
-    if (!sys->output_pool) {
-        sys->output_pool = mmal_pool_create(pool_size, 0);
-        msg_Dbg(dec, "Created output pool with %d pictures", sys->output_pool->headers_num);
+    if (!atomic_load(&sys->started)) {
+        if (!sys->opaque) {
+            sys->output_pool = mmal_port_pool_create(sys->output, pool_size, 0);
+            msg_Dbg(dec, "Created output pool with %d pictures", sys->output_pool->headers_num);
+        }
+
+        atomic_store(&sys->started, true);
 
         /* we need one picture from vout for each buffer header on the output
          * port */
@@ -407,10 +414,14 @@ static int send_output_buffer(decoder_t *dec)
     if (!sys->output->is_enabled)
         return VLC_EGENERIC;
 
-    buffer = mmal_queue_get(sys->output_pool->queue);
-    if (!buffer) {
-        msg_Warn(dec, "Failed to get new buffer");
-        return VLC_EGENERIC;
+    /* If local output pool is allocated, use it - this is only the case for
+     * non-opaque modes */
+    if (sys->output_pool) {
+        buffer = mmal_queue_get(sys->output_pool->queue);
+        if (!buffer) {
+            msg_Warn(dec, "Failed to get new buffer");
+            return VLC_EGENERIC;
+        }
     }
 
     picture = decoder_NewPicture(dec);
@@ -424,27 +435,29 @@ static int send_output_buffer(decoder_t *dec)
     for (int i = 0; i < picture->i_planes; i++)
         buffer_size += picture->p[i].i_lines * picture->p[i].i_pitch;
 
-    mmal_buffer_header_reset(buffer);
-    buffer->user_data = picture;
-    buffer->cmd = 0;
-    buffer->alloc_size = sys->output->buffer_size;
-
-    if (sys->opaque) {
-        if (p_sys->buffer == NULL) {
-            msg_Err(dec, "Retrieved picture without opaque handle");
-            ret = VLC_EGENERIC;
-            goto err;
-        }
-        buffer->data = p_sys->buffer->data;
-    } else {
+    if (sys->output_pool) {
+        mmal_buffer_header_reset(buffer);
+        buffer->user_data = picture;
+        buffer->alloc_size = sys->output->buffer_size;
         if (buffer_size < sys->output->buffer_size) {
             msg_Err(dec, "Retrieved picture with too small data block (%d < %d)",
                     buffer_size, sys->output->buffer_size);
             ret = VLC_EGENERIC;
             goto err;
         }
-        buffer->data = picture->p[0].p_pixels;
+
+        if (!sys->opaque)
+            buffer->data = picture->p[0].p_pixels;
+    } else {
+        buffer = p_sys->buffer;
+        if (!buffer) {
+            msg_Warn(dec, "Picture has no buffer attached");
+            picture_Release(picture);
+            return VLC_EGENERIC;
+        }
+        buffer->data = p_sys->buffer->data;
     }
+    buffer->cmd = 0;
 
     status = mmal_port_send_buffer(sys->output, buffer);
     if (status != MMAL_SUCCESS) {
@@ -460,27 +473,42 @@ static int send_output_buffer(decoder_t *dec)
 err:
     if (picture)
         picture_Release(picture);
-    buffer->data = NULL;
-    mmal_buffer_header_release(buffer);
+    if (sys->output_pool && buffer) {
+        buffer->data = NULL;
+        mmal_buffer_header_release(buffer);
+    }
     return ret;
 }
 
 static void fill_output_port(decoder_t *dec)
 {
     decoder_sys_t *sys = dec->p_sys;
-    /* allow at least 2 buffers in transit */
-    unsigned max_buffers_in_transit = __MAX(sys->output_pool->headers_num,
-            MIN_NUM_BUFFERS_IN_TRANSIT);
-    unsigned buffers_available = mmal_queue_length(sys->output_pool->queue);
-    unsigned buffers_to_send = max_buffers_in_transit - atomic_load(&sys->output_in_transit);
-    unsigned i;
+
+    unsigned max_buffers_in_transit = 0;
+    int buffers_available = 0;
+    int buffers_to_send = 0;
+    int i;
+
+    if (sys->output_pool) {
+        max_buffers_in_transit = __MAX(sys->output_pool->headers_num,
+                MIN_NUM_BUFFERS_IN_TRANSIT);
+        buffers_available = mmal_queue_length(sys->output_pool->queue);
+    } else {
+        max_buffers_in_transit = __MAX(sys->output->buffer_num, MIN_NUM_BUFFERS_IN_TRANSIT);
+        buffers_available = NUM_DECODER_BUFFER_HEADERS - atomic_load(&sys->output_in_transit) -
+            mmal_queue_length(sys->decoded_pictures);
+    }
+    buffers_to_send = max_buffers_in_transit - atomic_load(&sys->output_in_transit);
 
     if (buffers_to_send > buffers_available)
         buffers_to_send = buffers_available;
 
 #ifndef NDEBUG
-    msg_Dbg(dec, "Send %d buffers to output port (available: %d, in_transit: %d, buffer_num: %d)",
-                    buffers_to_send, buffers_available, atomic_load(&sys->output_in_transit),
+    msg_Dbg(dec, "Send %d buffers to output port (available: %d, "
+                    "in_transit: %d, decoded: %d, buffer_num: %d)",
+                    buffers_to_send, buffers_available,
+                    atomic_load(&sys->output_in_transit),
+                    mmal_queue_length(sys->decoded_pictures),
                     sys->output->buffer_num);
 #endif
     for (i = 0; i < buffers_to_send; ++i)
@@ -522,7 +550,7 @@ static picture_t *decode(decoder_t *dec, block_t **pblock)
     /*
      * Send output buffers
      */
-    if (sys->output_pool) {
+    if (atomic_load(&sys->started)) {
         buffer = mmal_queue_get(sys->decoded_pictures);
         if (buffer) {
             ret = (picture_t *)buffer->user_data;
@@ -530,9 +558,11 @@ static picture_t *decode(decoder_t *dec, block_t **pblock)
             ret->b_progressive = sys->b_progressive;
             ret->b_top_field_first = sys->b_top_field_first;
 
-            buffer->data = NULL;
-            mmal_buffer_header_reset(buffer);
-            mmal_buffer_header_release(buffer);
+            if (sys->output_pool) {
+                buffer->data = NULL;
+                mmal_buffer_header_reset(buffer);
+                mmal_buffer_header_release(buffer);
+            }
         }
 
         fill_output_port(dec);
@@ -648,10 +678,12 @@ static void output_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
         } else {
             picture = (picture_t *)buffer->user_data;
             picture_Release(picture);
-            buffer->user_data = NULL;
-            buffer->alloc_size = 0;
-            buffer->data = NULL;
-            mmal_buffer_header_release(buffer);
+            if (sys->output_pool) {
+                buffer->user_data = NULL;
+                buffer->alloc_size = 0;
+                buffer->data = NULL;
+                mmal_buffer_header_release(buffer);
+            }
         }
         atomic_fetch_sub(&sys->output_in_transit, 1);
     } else if (buffer->cmd == MMAL_EVENT_FORMAT_CHANGED) {
-- 
2.4.0





More information about the vlc-devel mailing list