[vlc-devel] [PATCH 09/11] mediacodec: rework pf_get_output

Thomas Guillem thomas at gllm.fr
Wed Aug 26 18:10:06 CEST 2015


Rename it to pf_process_output. The output buffer is now dequeued/parsed
outside of the pf callback.
---
 modules/codec/omxil/mediacodec.c | 226 +++++++++++++++++----------------------
 1 file changed, 99 insertions(+), 127 deletions(-)

diff --git a/modules/codec/omxil/mediacodec.c b/modules/codec/omxil/mediacodec.c
index 5f63f38..1cb210a 100644
--- a/modules/codec/omxil/mediacodec.c
+++ b/modules/codec/omxil/mediacodec.c
@@ -78,7 +78,7 @@ typedef void (*dec_on_flush_cb)(decoder_t *);
  * Callback called when DecodeCommon try to get an output buffer (pic or block).
  * It returns -1 in case of error, or the number of output buffer returned.
  */
-typedef int (*dec_get_output_cb)(decoder_t *, picture_t **, block_t **, bool *, mtime_t);
+typedef int (*dec_process_output_cb)(decoder_t *, mc_api_out *, picture_t **, block_t **);
 
 struct decoder_sys_t
 {
@@ -102,9 +102,9 @@ struct decoder_sys_t
     int64_t i_preroll_end;
 
     /* Specific Audio/Video callbacks */
-    dec_on_new_block_cb pf_on_new_block;
-    dec_get_output_cb   pf_get_output;
+    dec_on_new_block_cb     pf_on_new_block;
     dec_on_flush_cb         pf_on_flush;
+    dec_process_output_cb   pf_process_output;
 
     union
     {
@@ -139,13 +139,13 @@ static int  OpenDecoderNdk(vlc_object_t *);
 static void CloseDecoder(vlc_object_t *);
 
 static int Video_OnNewBlock(decoder_t *, block_t *, int *);
-static int Video_GetOutput(decoder_t *, picture_t **, block_t **, bool *, mtime_t);
 static void Video_OnFlush(decoder_t *);
+static int Video_ProcessOutput(decoder_t *, mc_api_out *, picture_t **, block_t **);
 static picture_t *DecodeVideo(decoder_t *, block_t **);
 
 static int Audio_OnNewBlock(decoder_t *, block_t *, int *);
-static int Audio_GetOutput(decoder_t *, picture_t **, block_t **, bool *, mtime_t);
 static void Audio_OnFlush(decoder_t *);
+static int Audio_ProcessOutput(decoder_t *, mc_api_out *, picture_t **, block_t **);
 static block_t *DecodeAudio(decoder_t *, block_t **);
 
 static void InvalidateAllPictures(decoder_t *);
@@ -558,7 +558,7 @@ static int OpenDecoder(vlc_object_t *p_this, pf_MediaCodecApi_init pf_init)
     {
         p_sys->pf_on_new_block = Video_OnNewBlock;
         p_sys->pf_on_flush = Video_OnFlush;
-        p_sys->pf_get_output = Video_GetOutput;
+        p_sys->pf_process_output = Video_ProcessOutput;
         p_sys->u.video.i_width = p_dec->fmt_in.video.i_width;
         p_sys->u.video.i_height = p_dec->fmt_in.video.i_height;
 
@@ -598,8 +598,8 @@ static int OpenDecoder(vlc_object_t *p_this, pf_MediaCodecApi_init pf_init)
     else
     {
         p_sys->pf_on_new_block = Audio_OnNewBlock;
-        p_sys->pf_get_output = Audio_GetOutput;
         p_sys->pf_on_flush = Audio_OnFlush;
+        p_sys->pf_process_output = Audio_ProcessOutput;
         p_sys->u.audio.i_channels = p_dec->fmt_in.audio.i_channels;
 
         p_sys->psz_name = MediaCodec_GetName(VLC_OBJECT(p_dec), p_sys->mime, 0);
@@ -747,59 +747,28 @@ static int InsertInflightPicture(decoder_t *p_dec, picture_t *p_pic,
     return 0;
 }
 
-static int Video_GetOutput(decoder_t *p_dec, picture_t **pp_out_pic,
-                           block_t **pp_out_block, bool *p_abort,
-                           mtime_t i_timeout)
+static int Video_ProcessOutput(decoder_t *p_dec, mc_api_out *p_out,
+                               picture_t **pp_out_pic, block_t **pp_out_block)
 {
     decoder_sys_t *p_sys = p_dec->p_sys;
-    mc_api_out out;
-    picture_t *p_pic = NULL;
-    int i_ret = 0, i_index;
 
     assert(pp_out_pic && !pp_out_block);
 
-    /* FIXME: A new picture shouldn't be created each time.  If
-     * decoder_NewPicture fails because the decoder is flushing/exiting,
-     * GetVideoOutput will either fail (or crash in function of devices), or
-     * never return an output buffer. Indeed, if the Decoder is flushing,
-     * MediaCodec can be stalled since the input is waiting for the output or
-     * vice-versa. Therefore, call decoder_NewPicture before GetVideoOutput as
-     * a safeguard. */
-
-    if (p_sys->b_has_format)
+    if (p_out->type == MC_OUT_TYPE_BUF)
     {
+        picture_t *p_pic = NULL;
+
         if (p_sys->b_update_format)
         {
             p_sys->b_update_format = false;
             if (decoder_UpdateVideoFormat(p_dec) != 0)
             {
                 msg_Err(p_dec, "decoder_UpdateVideoFormat failed");
+                p_sys->api->release_out(p_sys->api, p_out->u.buf.i_index, false);
                 return -1;
             }
         }
-        p_pic = decoder_NewPicture(p_dec);
-        if (!p_pic) {
-            msg_Warn(p_dec, "NewPicture failed");
-            /* abort current Decode call */
-            *p_abort = true;
-            return 0;
-        }
-    }
-
-    i_index = p_sys->api->dequeue_out(p_sys->api, i_timeout);
-    if (i_index >= 0 || i_index == MC_API_INFO_OUTPUT_FORMAT_CHANGED
-     || i_index == MC_API_INFO_OUTPUT_BUFFERS_CHANGED)
-        i_ret = p_sys->api->get_out(p_sys->api, i_index, &out);
-    else if (i_index == MC_API_INFO_TRYAGAIN)
-        i_ret = 0;
-    else
-        i_ret = -1;
 
-    if (i_ret != 1)
-        goto end;
-
-    if (out.type == MC_OUT_TYPE_BUF)
-    {
         /* If the oldest input block had no PTS, the timestamp of
          * the frame returned by MediaCodec might be wrong so we
          * overwrite it with the corresponding dts. Call FifoGet
@@ -809,18 +778,20 @@ static int Video_GetOutput(decoder_t *p_dec, picture_t **pp_out_pic,
 
         if (!p_sys->b_has_format) {
             msg_Warn(p_dec, "Buffers returned before output format is set, dropping frame");
-            i_ret = p_sys->api->release_out(p_sys->api, out.u.buf.i_index, false);
-            goto end;
+            return p_sys->api->release_out(p_sys->api, p_out->u.buf.i_index, false);
         }
 
-        if (out.u.buf.i_ts <= p_sys->i_preroll_end)
-        {
-            i_ret = p_sys->api->release_out(p_sys->api, out.u.buf.i_index, false);
-            goto end;
+        if (p_out->u.buf.i_ts <= p_sys->i_preroll_end)
+            return p_sys->api->release_out(p_sys->api, p_out->u.buf.i_index, false);
+
+        p_pic = decoder_NewPicture(p_dec);
+        if (!p_pic) {
+            msg_Warn(p_dec, "NewPicture failed");
+            return p_sys->api->release_out(p_sys->api, p_out->u.buf.i_index, false);
         }
 
         if (forced_ts == VLC_TS_INVALID)
-            p_pic->date = out.u.buf.i_ts;
+            p_pic->date = p_out->u.buf.i_ts;
         else
             p_pic->date = forced_ts;
 
@@ -830,11 +801,11 @@ static int Video_GetOutput(decoder_t *p_dec, picture_t **pp_out_pic,
             p_picsys->pf_lock_pic = NULL;
             p_picsys->pf_unlock_pic = UnlockPicture;
             p_picsys->priv.hw.p_dec = p_dec;
-            p_picsys->priv.hw.i_index = out.u.buf.i_index;
+            p_picsys->priv.hw.i_index = p_out->u.buf.i_index;
             p_picsys->priv.hw.b_valid = true;
 
             vlc_mutex_lock(get_android_opaque_mutex());
-            InsertInflightPicture(p_dec, p_pic, out.u.buf.i_index);
+            InsertInflightPicture(p_dec, p_pic, p_out->u.buf.i_index);
             vlc_mutex_unlock(get_android_opaque_mutex());
         } else {
             unsigned int chroma_div;
@@ -844,16 +815,21 @@ static int Video_GetOutput(decoder_t *p_dec, picture_t **pp_out_pic,
                               NULL, NULL, &chroma_div);
             CopyOmxPicture(p_sys->u.video.i_pixel_format, p_pic,
                            p_sys->u.video.i_slice_height, p_sys->u.video.i_stride,
-                           (uint8_t *)out.u.buf.p_ptr, chroma_div,
+                           (uint8_t *)p_out->u.buf.p_ptr, chroma_div,
                            &p_sys->u.video.ascd);
 
-            if (p_sys->api->release_out(p_sys->api, out.u.buf.i_index, false))
-                i_ret = -1;
+            if (p_sys->api->release_out(p_sys->api, p_out->u.buf.i_index, false))
+            {
+                picture_Release(p_pic);
+                return -1;
+            }
         }
-        i_ret = 1;
+        assert(!(*pp_out_pic));
+        *pp_out_pic = p_pic;
+        return 1;
     } else {
-        assert(out.type == MC_OUT_TYPE_CONF);
-        p_sys->u.video.i_pixel_format = out.u.conf.video.pixel_format;
+        assert(p_out->type == MC_OUT_TYPE_CONF);
+        p_sys->u.video.i_pixel_format = p_out->u.conf.video.pixel_format;
         ArchitectureSpecificCopyHooksDestroy(p_sys->u.video.i_pixel_format,
                                              &p_sys->u.video.ascd);
 
@@ -862,56 +838,46 @@ static int Video_GetOutput(decoder_t *p_dec, picture_t **pp_out_pic,
             if (!GetVlcChromaFormat(p_sys->u.video.i_pixel_format,
                                     &p_dec->fmt_out.i_codec, &name)) {
                 msg_Err(p_dec, "color-format not recognized");
-                i_ret = -1;
-                goto end;
+                return -1;
             }
         }
 
         msg_Err(p_dec, "output: %d %s, %dx%d stride %d %d, crop %d %d %d %d",
-                p_sys->u.video.i_pixel_format, name, out.u.conf.video.width, out.u.conf.video.height,
-                out.u.conf.video.stride, out.u.conf.video.slice_height,
-                out.u.conf.video.crop_left, out.u.conf.video.crop_top,
-                out.u.conf.video.crop_right, out.u.conf.video.crop_bottom);
+                p_sys->u.video.i_pixel_format, name, p_out->u.conf.video.width, p_out->u.conf.video.height,
+                p_out->u.conf.video.stride, p_out->u.conf.video.slice_height,
+                p_out->u.conf.video.crop_left, p_out->u.conf.video.crop_top,
+                p_out->u.conf.video.crop_right, p_out->u.conf.video.crop_bottom);
 
-        p_dec->fmt_out.video.i_width = out.u.conf.video.crop_right + 1 - out.u.conf.video.crop_left;
-        p_dec->fmt_out.video.i_height = out.u.conf.video.crop_bottom + 1 - out.u.conf.video.crop_top;
+        p_dec->fmt_out.video.i_width = p_out->u.conf.video.crop_right + 1 - p_out->u.conf.video.crop_left;
+        p_dec->fmt_out.video.i_height = p_out->u.conf.video.crop_bottom + 1 - p_out->u.conf.video.crop_top;
         if (p_dec->fmt_out.video.i_width <= 1
             || p_dec->fmt_out.video.i_height <= 1) {
-            p_dec->fmt_out.video.i_width = out.u.conf.video.width;
-            p_dec->fmt_out.video.i_height = out.u.conf.video.height;
+            p_dec->fmt_out.video.i_width = p_out->u.conf.video.width;
+            p_dec->fmt_out.video.i_height = p_out->u.conf.video.height;
         }
         p_dec->fmt_out.video.i_visible_width = p_dec->fmt_out.video.i_width;
         p_dec->fmt_out.video.i_visible_height = p_dec->fmt_out.video.i_height;
 
-        p_sys->u.video.i_stride = out.u.conf.video.stride;
-        p_sys->u.video.i_slice_height = out.u.conf.video.slice_height;
+        p_sys->u.video.i_stride = p_out->u.conf.video.stride;
+        p_sys->u.video.i_slice_height = p_out->u.conf.video.slice_height;
         if (p_sys->u.video.i_stride <= 0)
-            p_sys->u.video.i_stride = out.u.conf.video.width;
+            p_sys->u.video.i_stride = p_out->u.conf.video.width;
         if (p_sys->u.video.i_slice_height <= 0)
-            p_sys->u.video.i_slice_height = out.u.conf.video.height;
+            p_sys->u.video.i_slice_height = p_out->u.conf.video.height;
 
-        ArchitectureSpecificCopyHooks(p_dec, out.u.conf.video.pixel_format,
-                                      out.u.conf.video.slice_height,
+        ArchitectureSpecificCopyHooks(p_dec, p_out->u.conf.video.pixel_format,
+                                      p_out->u.conf.video.slice_height,
                                       p_sys->u.video.i_stride, &p_sys->u.video.ascd);
         if (p_sys->u.video.i_pixel_format == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar)
-            p_sys->u.video.i_slice_height -= out.u.conf.video.crop_top/2;
+            p_sys->u.video.i_slice_height -= p_out->u.conf.video.crop_top/2;
         if (IgnoreOmxDecoderPadding(p_sys->psz_name)) {
             p_sys->u.video.i_slice_height = 0;
             p_sys->u.video.i_stride = p_dec->fmt_out.video.i_width;
         }
         p_sys->b_update_format = true;
         p_sys->b_has_format = true;
-        i_ret = 0;
-    }
-end:
-    if (p_pic)
-    {
-        if (i_ret == 1)
-            *pp_out_pic = p_pic;
-        else
-            picture_Release(p_pic);
+        return 0;
     }
-    return i_ret;
 }
 
 /* samples will be in the following order: FL FR FC LFE BL BR BC SL SR */
@@ -922,64 +888,47 @@ uint32_t pi_audio_order_src[] =
     AOUT_CHAN_MIDDLELEFT, AOUT_CHAN_MIDDLERIGHT,
 };
 
-static int Audio_GetOutput(decoder_t *p_dec, picture_t **pp_out_pic,
-                           block_t **pp_out_block, bool *p_abort,
-                           mtime_t i_timeout)
+static int Audio_ProcessOutput(decoder_t *p_dec, mc_api_out *p_out,
+                               picture_t **pp_out_pic, block_t **pp_out_block)
 {
     decoder_sys_t *p_sys = p_dec->p_sys;
-    mc_api_out out;
-    int i_ret, i_index;
-    (void) p_abort;
 
     assert(!pp_out_pic && pp_out_block);
 
-
-    i_index = p_sys->api->dequeue_out(p_sys->api, i_timeout);
-    if (i_index >= 0 || i_index == MC_API_INFO_OUTPUT_FORMAT_CHANGED
-     || i_index == MC_API_INFO_OUTPUT_BUFFERS_CHANGED)
-        i_ret = p_sys->api->get_out(p_sys->api, i_index, &out);
-    else if (i_index == MC_API_INFO_TRYAGAIN)
-        i_ret = 0;
-    else
-        i_ret = -1;
-
-    if (i_ret != 1)
-        return i_ret;
-
-    if (out.type == MC_OUT_TYPE_BUF)
+    if (p_out->type == MC_OUT_TYPE_BUF)
     {
         block_t *p_block = NULL;
         if (!p_sys->b_has_format) {
             msg_Warn(p_dec, "Buffers returned before output format is set, dropping frame");
-            return p_sys->api->release_out(p_sys->api, out.u.buf.i_index, false);
+            return p_sys->api->release_out(p_sys->api, p_out->u.buf.i_index, false);
         }
 
-        p_block = block_Alloc(out.u.buf.i_size);
+        p_block = block_Alloc(p_out->u.buf.i_size);
         if (!p_block)
             return -1;
-        p_block->i_nb_samples = out.u.buf.i_size
+        p_block->i_nb_samples = p_out->u.buf.i_size
                               / p_dec->fmt_out.audio.i_bytes_per_frame;
 
         if (p_sys->u.audio.b_extract)
         {
             aout_ChannelExtract(p_block->p_buffer,
                                 p_dec->fmt_out.audio.i_channels,
-                                out.u.buf.p_ptr, p_sys->u.audio.i_channels,
+                                p_out->u.buf.p_ptr, p_sys->u.audio.i_channels,
                                 p_block->i_nb_samples, p_sys->u.audio.pi_extraction,
                                 p_dec->fmt_out.audio.i_bitspersample);
         }
         else
-            memcpy(p_block->p_buffer, out.u.buf.p_ptr, out.u.buf.i_size);
+            memcpy(p_block->p_buffer, p_out->u.buf.p_ptr, p_out->u.buf.i_size);
 
-        if (out.u.buf.i_ts != 0 && out.u.buf.i_ts != date_Get(&p_sys->u.audio.i_end_date))
-            date_Set(&p_sys->u.audio.i_end_date, out.u.buf.i_ts);
+        if (p_out->u.buf.i_ts != 0 && p_out->u.buf.i_ts != date_Get(&p_sys->u.audio.i_end_date))
+            date_Set(&p_sys->u.audio.i_end_date, p_out->u.buf.i_ts);
 
         p_block->i_pts = date_Get(&p_sys->u.audio.i_end_date);
         p_block->i_length = date_Increment(&p_sys->u.audio.i_end_date,
                                            p_block->i_nb_samples)
                           - p_block->i_pts;
 
-        if (p_sys->api->release_out(p_sys->api, out.u.buf.i_index, false))
+        if (p_sys->api->release_out(p_sys->api, p_out->u.buf.i_index, false))
         {
             block_Release(p_block);
             return -1;
@@ -990,29 +939,29 @@ static int Audio_GetOutput(decoder_t *p_dec, picture_t **pp_out_pic,
         uint32_t i_layout_dst;
         int      i_channels_dst;
 
-        assert(out.type == MC_OUT_TYPE_CONF);
+        assert(p_out->type == MC_OUT_TYPE_CONF);
 
-        if (out.u.conf.audio.channel_count <= 0
-         || out.u.conf.audio.channel_count > 8
-         || out.u.conf.audio.sample_rate <= 0)
+        if (p_out->u.conf.audio.channel_count <= 0
+         || p_out->u.conf.audio.channel_count > 8
+         || p_out->u.conf.audio.sample_rate <= 0)
         {
             msg_Warn( p_dec, "invalid audio properties channels count %d, sample rate %d",
-                      out.u.conf.audio.channel_count,
-                      out.u.conf.audio.sample_rate);
+                      p_out->u.conf.audio.channel_count,
+                      p_out->u.conf.audio.sample_rate);
             return -1;
         }
 
         msg_Err(p_dec, "output: channel_count: %d, channel_mask: 0x%X, rate: %d",
-                out.u.conf.audio.channel_count, out.u.conf.audio.channel_mask,
-                out.u.conf.audio.sample_rate);
+                p_out->u.conf.audio.channel_count, p_out->u.conf.audio.channel_mask,
+                p_out->u.conf.audio.sample_rate);
 
         p_dec->fmt_out.i_codec = VLC_CODEC_S16N;
         p_dec->fmt_out.audio.i_format = p_dec->fmt_out.i_codec;
 
-        p_dec->fmt_out.audio.i_rate = out.u.conf.audio.sample_rate;
-        date_Init(&p_sys->u.audio.i_end_date, out.u.conf.audio.sample_rate, 1 );
+        p_dec->fmt_out.audio.i_rate = p_out->u.conf.audio.sample_rate;
+        date_Init(&p_sys->u.audio.i_end_date, p_out->u.conf.audio.sample_rate, 1 );
 
-        p_sys->u.audio.i_channels = out.u.conf.audio.channel_count;
+        p_sys->u.audio.i_channels = p_out->u.conf.audio.channel_count;
         p_sys->u.audio.b_extract =
             aout_CheckChannelExtraction(p_sys->u.audio.pi_extraction,
                                         &i_layout_dst, &i_channels_dst,
@@ -1089,6 +1038,29 @@ static int DecodeFlush(decoder_t *p_dec)
     return VLC_SUCCESS;
 }
 
+static int GetAndProcessOutput(decoder_t *p_dec, picture_t **pp_out_pic,
+                               block_t **pp_out_block, mtime_t i_timeout)
+{
+    decoder_sys_t *p_sys = p_dec->p_sys;
+    struct mc_api_out out;
+    int i_index, i_ret;
+
+    i_index = p_sys->api->dequeue_out(p_sys->api, i_timeout);
+    if (i_index >= 0 || i_index == MC_API_INFO_OUTPUT_FORMAT_CHANGED
+     || i_index == MC_API_INFO_OUTPUT_BUFFERS_CHANGED)
+        i_ret = p_sys->api->get_out(p_sys->api, i_index, &out);
+    else if (i_index == MC_API_INFO_TRYAGAIN)
+        i_ret = 0;
+    else
+        i_ret = -1;
+
+    if (i_ret != 1)
+        return i_ret;
+
+    return p_sys->pf_process_output(p_dec, &out, pp_out_pic,
+                                    pp_out_block);
+}
+
 /**
  * DecodeCommon called from DecodeVideo or DecodeAudio.
  * It returns -1 in case of error, 0 otherwise. The output buffer is returned
@@ -1199,8 +1171,8 @@ static int DecodeCommon(decoder_t *p_dec, block_t **pp_block,
 
         if (i_input_ret != -1 && p_sys->decoded && i_output_ret == 0)
         {
-            i_output_ret = p_sys->pf_get_output(p_dec, pp_out_pic, pp_out_block,
-                                                &b_abort, timeout);
+            i_output_ret = GetAndProcessOutput(p_dec, pp_out_pic, pp_out_block,
+                                               timeout);
 
             if (!p_sys->b_has_format && i_output_ret == 0 && i_input_ret == 0
              && ++i_attempts > 100)
-- 
2.1.4



More information about the vlc-devel mailing list