]> git.sesse.net Git - vlc/blobdiff - modules/codec/omxil/utils.c
mediacodec: fix comparison between signed and unsigned warning
[vlc] / modules / codec / omxil / utils.c
index eec75afe80de2f08d5a1e79a4fdf60b01a2b570d..7f20c5854538d15ecda6607e598415339f6f8ed8 100644 (file)
 
 #include "omxil.h"
 #include "qcom.h"
+#include "../../video_chroma/copy.h"
 
 /*****************************************************************************
  * Events utility functions
  *****************************************************************************/
-OMX_ERRORTYPE PostOmxEvent(decoder_t *p_dec, OMX_EVENTTYPE event,
+void InitOmxEventQueue(OmxEventQueue *queue)
+{
+    queue->pp_last_event = &queue->p_events;
+    vlc_mutex_init(&queue->mutex);
+    vlc_cond_init(&queue->cond);
+}
+
+void DeinitOmxEventQueue(OmxEventQueue *queue)
+{
+    vlc_mutex_destroy(&queue->mutex);
+    vlc_cond_destroy(&queue->cond);
+}
+
+OMX_ERRORTYPE PostOmxEvent(OmxEventQueue *queue, OMX_EVENTTYPE event,
     OMX_U32 data_1, OMX_U32 data_2, OMX_PTR event_data)
 {
-    decoder_sys_t *p_sys = p_dec->p_sys;
     OmxEvent *p_event;
 
     p_event = malloc(sizeof(OmxEvent));
@@ -55,33 +68,32 @@ OMX_ERRORTYPE PostOmxEvent(decoder_t *p_dec, OMX_EVENTTYPE event,
     p_event->event_data = event_data;
     p_event->next = 0;
 
-    vlc_mutex_lock(&p_sys->mutex);
-    *p_sys->pp_last_event = p_event;
-    p_sys->pp_last_event = &p_event->next;
-    vlc_cond_signal(&p_sys->cond);
-    vlc_mutex_unlock(&p_sys->mutex);
+    vlc_mutex_lock(&queue->mutex);
+    *queue->pp_last_event = p_event;
+    queue->pp_last_event = &p_event->next;
+    vlc_cond_signal(&queue->cond);
+    vlc_mutex_unlock(&queue->mutex);
     return OMX_ErrorNone;
 }
 
-OMX_ERRORTYPE WaitForOmxEvent(decoder_t *p_dec, OMX_EVENTTYPE *event,
+OMX_ERRORTYPE WaitForOmxEvent(OmxEventQueue *queue, OMX_EVENTTYPE *event,
     OMX_U32 *data_1, OMX_U32 *data_2, OMX_PTR *event_data)
 {
-    decoder_sys_t *p_sys = p_dec->p_sys;
     OmxEvent *p_event;
 
-    vlc_mutex_lock(&p_sys->mutex);
+    vlc_mutex_lock(&queue->mutex);
 
-    if(!p_sys->p_events)
-        vlc_cond_timedwait(&p_sys->cond, &p_sys->mutex, mdate()+CLOCK_FREQ);
+    if(!queue->p_events)
+        vlc_cond_timedwait(&queue->cond, &queue->mutex, mdate()+CLOCK_FREQ);
 
-    p_event = p_sys->p_events;
+    p_event = queue->p_events;
     if(p_event)
     {
-        p_sys->p_events = p_event->next;
-        if(!p_sys->p_events) p_sys->pp_last_event = &p_sys->p_events;
+        queue->p_events = p_event->next;
+        if(!queue->p_events) queue->pp_last_event = &queue->p_events;
     }
 
-    vlc_mutex_unlock(&p_sys->mutex);
+    vlc_mutex_unlock(&queue->mutex);
 
     if(p_event)
     {
@@ -96,7 +108,7 @@ OMX_ERRORTYPE WaitForOmxEvent(decoder_t *p_dec, OMX_EVENTTYPE *event,
     return OMX_ErrorTimeout;
 }
 
-OMX_ERRORTYPE WaitForSpecificOmxEvent(decoder_t *p_dec,
+OMX_ERRORTYPE WaitForSpecificOmxEvent(OmxEventQueue *queue,
     OMX_EVENTTYPE specific_event, OMX_U32 *data_1, OMX_U32 *data_2,
     OMX_PTR *event_data)
 {
@@ -106,7 +118,7 @@ OMX_ERRORTYPE WaitForSpecificOmxEvent(decoder_t *p_dec,
 
     while(1)
     {
-        status = WaitForOmxEvent(p_dec, &event, data_1, data_2, event_data);
+        status = WaitForOmxEvent(queue, &event, data_1, data_2, event_data);
         if(status != OMX_ErrorNone) return status;
 
         if(event == specific_event) break;
@@ -116,12 +128,83 @@ OMX_ERRORTYPE WaitForSpecificOmxEvent(decoder_t *p_dec,
     return OMX_ErrorNone;
 }
 
+void PrintOmxEvent(vlc_object_t *p_this, OMX_EVENTTYPE event, OMX_U32 data_1,
+    OMX_U32 data_2, OMX_PTR event_data)
+{
+    switch (event)
+    {
+    case OMX_EventCmdComplete:
+        switch ((OMX_STATETYPE)data_1)
+        {
+        case OMX_CommandStateSet:
+            msg_Dbg( p_this, "OmxEventHandler (%s, %s, %s)", EventToString(event),
+                     CommandToString(data_1), StateToString(data_2) );
+            break;
+
+        default:
+            msg_Dbg( p_this, "OmxEventHandler (%s, %s, %u)", EventToString(event),
+                     CommandToString(data_1), (unsigned int)data_2 );
+            break;
+        }
+        break;
+
+    case OMX_EventError:
+        msg_Dbg( p_this, "OmxEventHandler (%s, %s, %u, %s)", EventToString(event),
+                 ErrorToString((OMX_ERRORTYPE)data_1), (unsigned int)data_2,
+                 (const char *)event_data);
+        break;
+
+    default:
+        msg_Dbg( p_this, "OmxEventHandler (%s, %u, %u)", EventToString(event),
+                 (unsigned int)data_1, (unsigned int)data_2 );
+        break;
+    }
+}
+
 /*****************************************************************************
  * Picture utility functions
  *****************************************************************************/
+void ArchitectureSpecificCopyHooks( decoder_t *p_dec, int i_color_format,
+                                    int i_slice_height, int i_src_stride,
+                                    ArchitectureSpecificCopyData *p_architecture_specific )
+{
+    (void)i_slice_height;
+
+#ifdef CAN_COMPILE_SSE2
+    if( i_color_format == OMX_COLOR_FormatYUV420SemiPlanar && vlc_CPU_SSE2() )
+    {
+        copy_cache_t *p_surface_cache = malloc( sizeof(copy_cache_t) );
+        if( !p_surface_cache || CopyInitCache( p_surface_cache, i_src_stride ) )
+        {
+            free( p_surface_cache );
+            return;
+        }
+        p_architecture_specific->data = p_surface_cache;
+        p_dec->fmt_out.i_codec = VLC_CODEC_YV12;
+    }
+#endif
+}
+
+void ArchitectureSpecificCopyHooksDestroy( int i_color_format,
+                                           ArchitectureSpecificCopyData *p_architecture_specific )
+{
+    if (!p_architecture_specific->data)
+        return;
+#ifdef CAN_COMPILE_SSE2
+    if( i_color_format == OMX_COLOR_FormatYUV420SemiPlanar && vlc_CPU_SSE2() )
+    {
+        copy_cache_t *p_surface_cache = (copy_cache_t*)p_architecture_specific->data;
+        CopyCleanCache(p_surface_cache);
+    }
+#endif
+    free(p_architecture_specific->data);
+    p_architecture_specific->data = NULL;
+}
+
 void CopyOmxPicture( int i_color_format, picture_t *p_pic,
                      int i_slice_height,
-                     int i_src_stride, uint8_t *p_src, int i_chroma_div )
+                     int i_src_stride, uint8_t *p_src, int i_chroma_div,
+                     ArchitectureSpecificCopyData *p_architecture_specific )
 {
     uint8_t *p_dst;
     int i_dst_stride;
@@ -131,6 +214,17 @@ void CopyOmxPicture( int i_color_format, picture_t *p_pic,
         qcom_convert(p_src, p_pic);
         return;
     }
+#ifdef CAN_COMPILE_SSE2
+    if( i_color_format == OMX_COLOR_FormatYUV420SemiPlanar
+        && vlc_CPU_SSE2() && p_architecture_specific->data )
+    {
+        copy_cache_t *p_surface_cache = (copy_cache_t*)p_architecture_specific->data;
+        uint8_t *ppi_src_pointers[2] = { p_src, p_src + i_src_stride * i_slice_height };
+        size_t pi_src_strides[2] = { i_src_stride, i_src_stride };
+        CopyFromNv12( p_pic, ppi_src_pointers, pi_src_strides, i_src_stride, i_slice_height, p_surface_cache );
+        return;
+    }
+#endif
 
     for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
     {
@@ -182,6 +276,35 @@ void CopyVlcPicture( decoder_t *p_dec, OMX_BUFFERHEADERTYPE *p_header,
     }
 }
 
+int IgnoreOmxDecoderPadding(const char *name)
+{
+    // The list of decoders that signal padding properly is not necessary,
+    // since that is the default, but keep it here for reference. (This is
+    // only relevant for manufacturers that are known to have decoders with
+    // this kind of bug.)
+/*
+    static const char *padding_decoders[] = {
+        "OMX.SEC.AVC.Decoder",
+        "OMX.SEC.wmv7.dec",
+        "OMX.SEC.wmv8.dec",
+        NULL
+    };
+*/
+    static const char *nopadding_decoders[] = {
+        "OMX.SEC.avc.dec",
+        "OMX.SEC.avcdec",
+        "OMX.SEC.MPEG4.Decoder",
+        "OMX.SEC.mpeg4.dec",
+        "OMX.SEC.vc1.dec",
+        NULL
+    };
+    for (const char **ptr = nopadding_decoders; *ptr; ptr++) {
+        if (!strcmp(*ptr, name))
+            return 1;
+    }
+    return 0;
+}
+
 /*****************************************************************************
  * Logging utility functions
  *****************************************************************************/
@@ -272,10 +395,11 @@ static const struct
 {
     { VLC_CODEC_MPGV, OMX_VIDEO_CodingMPEG2, "video_decoder.mpeg2" },
     { VLC_CODEC_MP4V, OMX_VIDEO_CodingMPEG4, "video_decoder.mpeg4" },
+    { VLC_CODEC_HEVC, OMX_VIDEO_CodingAutoDetect, "video_decoder.hevc" },
     { VLC_CODEC_H264, OMX_VIDEO_CodingAVC,   "video_decoder.avc"   },
     { VLC_CODEC_H263, OMX_VIDEO_CodingH263,  "video_decoder.h263"  },
-    { VLC_CODEC_WMV1, OMX_VIDEO_CodingWMV,   "video_decoder.wmv  },
-    { VLC_CODEC_WMV2, OMX_VIDEO_CodingWMV,   "video_decoder.wmv  },
+    { VLC_CODEC_WMV1, OMX_VIDEO_CodingWMV,   "video_decoder.wmv1"  },
+    { VLC_CODEC_WMV2, OMX_VIDEO_CodingWMV,   "video_decoder.wmv2"  },
     { VLC_CODEC_WMV3, OMX_VIDEO_CodingWMV,   "video_decoder.wmv"   },
     { VLC_CODEC_VC1,  OMX_VIDEO_CodingWMV,   "video_decoder.wmv"   },
     { VLC_CODEC_MJPG, OMX_VIDEO_CodingMJPEG, "video_decoder.jpeg"  },
@@ -284,6 +408,8 @@ static const struct
     { VLC_CODEC_RV20, OMX_VIDEO_CodingRV,    "video_decoder.rv"    },
     { VLC_CODEC_RV30, OMX_VIDEO_CodingRV,    "video_decoder.rv"    },
     { VLC_CODEC_RV40, OMX_VIDEO_CodingRV,    "video_decoder.rv"    },
+    { VLC_CODEC_VP8,  OMX_VIDEO_CodingAutoDetect, "video_decoder.vp8" },
+    { VLC_CODEC_VP9,  OMX_VIDEO_CodingAutoDetect, "video_decoder.vp9" },
     { 0, 0, 0 }
 };
 
@@ -295,17 +421,11 @@ static const struct
 
 } audio_format_table[] =
 {
-    { VLC_CODEC_AMR_NB, OMX_AUDIO_CodingAMR, "audio_decoder.amr" },
-    { VLC_CODEC_AMR_WB, OMX_AUDIO_CodingAMR, "audio_decoder.amr" },
+    { VLC_CODEC_AMR_NB, OMX_AUDIO_CodingAMR, "audio_decoder.amrnb" },
+    { VLC_CODEC_AMR_WB, OMX_AUDIO_CodingAMR, "audio_decoder.amrwb" },
     { VLC_CODEC_MP4A,   OMX_AUDIO_CodingAAC, "audio_decoder.aac" },
     { VLC_CODEC_S16N,   OMX_AUDIO_CodingPCM, "audio_decoder.pcm" },
     { VLC_CODEC_MP3,    OMX_AUDIO_CodingMP3, "audio_decoder.mp3" },
-    { VLC_CODEC_MPGA,   OMX_AUDIO_CodingMP3, "audio_decoder.mp3" },
-    { VLC_CODEC_VORBIS, OMX_AUDIO_CodingVORBIS, "audio_decoder.vorbis" },
-    { VLC_CODEC_WMA1,   OMX_AUDIO_CodingWMA, "audio_decoder.wma" },
-    { VLC_CODEC_WMA2,   OMX_AUDIO_CodingWMA, "audio_decoder.wma" },
-    { VLC_CODEC_WMAP,   OMX_AUDIO_CodingWMA, "audio_decoder.wma" },
-    { VLC_CODEC_WMAL,   OMX_AUDIO_CodingWMA, "audio_decoder.wma" },
     { 0, 0, 0 }
 };
 
@@ -340,8 +460,8 @@ static const struct
 
 } audio_enc_format_table[] =
 {
-    { VLC_CODEC_AMR_NB, OMX_AUDIO_CodingAMR, "audio_encoder.amr" },
-    { VLC_CODEC_AMR_WB, OMX_AUDIO_CodingAMR, "audio_encoder.amr" },
+    { VLC_CODEC_AMR_NB, OMX_AUDIO_CodingAMR, "audio_encoder.amrnb" },
+    { VLC_CODEC_AMR_WB, OMX_AUDIO_CodingAMR, "audio_encoder.amrwb" },
     { VLC_CODEC_MP4A,   OMX_AUDIO_CodingAAC, "audio_encoder.aac" },
     { VLC_CODEC_S16N,   OMX_AUDIO_CodingPCM, "audio_encoder.pcm" },
     { 0, 0, 0 }
@@ -361,8 +481,9 @@ static const struct
     { VLC_CODEC_I420, OMX_COLOR_FormatYUV420PackedPlanar, 3, 1, 2 },
     { VLC_CODEC_NV12, OMX_COLOR_FormatYUV420SemiPlanar, 3, 1, 1 },
     { VLC_CODEC_NV21, OMX_QCOM_COLOR_FormatYVU420SemiPlanar, 3, 1, 1 },
-    { VLC_CODEC_NV12, OMX_TI_COLOR_FormatYUV420PackedSemiPlanar, 3, 1, 2 },
+    { VLC_CODEC_NV12, OMX_TI_COLOR_FormatYUV420PackedSemiPlanar, 3, 1, 1 },
     { VLC_CODEC_NV12, QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka, 3, 1, 1 },
+    { VLC_CODEC_NV12, OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar32m, 3, 1, 1 },
     { VLC_CODEC_YUYV, OMX_COLOR_FormatYCbYCr, 4, 2, 0 },
     { VLC_CODEC_YVYU, OMX_COLOR_FormatYCrYCb, 4, 2, 0 },
     { VLC_CODEC_UYVY, OMX_COLOR_FormatCbYCrY, 4, 2, 0 },
@@ -600,8 +721,8 @@ unsigned int GetAudioParamSize(OMX_INDEXTYPE index)
 
 OMX_ERRORTYPE SetAudioParameters(OMX_HANDLETYPE handle,
     OmxFormatParam *param, OMX_U32 i_port, OMX_AUDIO_CODINGTYPE encoding,
-    uint8_t i_channels, unsigned int i_samplerate, unsigned int i_bitrate,
-    unsigned int i_bps, unsigned int i_blocksize)
+    vlc_fourcc_t i_codec, uint8_t i_channels, unsigned int i_samplerate,
+    unsigned int i_bitrate, unsigned int i_bps, unsigned int i_blocksize)
 {
     OMX_INDEXTYPE index;
 
@@ -634,9 +755,12 @@ OMX_ERRORTYPE SetAudioParameters(OMX_HANDLETYPE handle,
         OMX_INIT_STRUCTURE(param->amr);
         param->amr.nChannels = i_channels;
         param->amr.nBitRate = i_bitrate;
-        param->amr.eAMRBandMode = OMX_AUDIO_AMRBandModeUnused;
+        if (i_codec == VLC_CODEC_AMR_WB)
+            param->amr.eAMRBandMode = OMX_AUDIO_AMRBandModeWB0;
+        else
+            param->amr.eAMRBandMode = OMX_AUDIO_AMRBandModeNB0;
         param->amr.eAMRDTXMode = OMX_AUDIO_AMRDTXModeOff;
-        param->amr.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatConformance;
+        param->amr.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
         break;
     case OMX_AUDIO_CodingG723:
         OMX_INIT_STRUCTURE(param->g723);
@@ -667,8 +791,8 @@ OMX_ERRORTYPE SetAudioParameters(OMX_HANDLETYPE handle,
         param->aac.nAACtools = OMX_AUDIO_AACToolAll;
         param->aac.nAACERtools = OMX_AUDIO_AACERAll;
         param->aac.eAACProfile = OMX_AUDIO_AACObjectLC;
-        param->aac.eAACStreamFormat = OMX_AUDIO_AACStreamFormatRAW;
-        param->aac.eChannelMode = i_channels ?
+        param->aac.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF;
+        param->aac.eChannelMode = i_channels > 1 ?
             OMX_AUDIO_ChannelModeStereo : OMX_AUDIO_ChannelModeMono;
         break;
     case OMX_AUDIO_CodingMP3:
@@ -676,7 +800,7 @@ OMX_ERRORTYPE SetAudioParameters(OMX_HANDLETYPE handle,
         param->mp3.nChannels = i_channels;
         param->mp3.nSampleRate = i_samplerate;
         param->mp3.nBitRate = i_bitrate;
-        param->mp3.eChannelMode = i_channels ?
+        param->mp3.eChannelMode = i_channels > 1 ?
             OMX_AUDIO_ChannelModeStereo : OMX_AUDIO_ChannelModeMono;
         param->mp3.eFormat = OMX_AUDIO_MP3StreamFormatMP1Layer3;
         break;
@@ -811,7 +935,7 @@ OMX_ERRORTYPE GetAudioParameters(OMX_HANDLETYPE handle,
 }
 
 /*****************************************************************************
- * PrintOmx: print component summary 
+ * PrintOmx: print component summary
  *****************************************************************************/
 void PrintOmx(decoder_t *p_dec, OMX_HANDLETYPE omx_handle, OMX_U32 i_port)
 {
@@ -922,3 +1046,62 @@ void PrintOmx(decoder_t *p_dec, OMX_HANDLETYPE omx_handle, OMX_U32 i_port)
         }
     }
 }
+
+static const struct
+{
+    OMX_VIDEO_AVCPROFILETYPE omx_profile;
+    size_t                   profile_idc;
+} omx_to_profile_idc[] =
+{
+    { OMX_VIDEO_AVCProfileBaseline,  66 },
+    { OMX_VIDEO_AVCProfileMain,      77 },
+    { OMX_VIDEO_AVCProfileExtended,  88 },
+    { OMX_VIDEO_AVCProfileHigh,     100 },
+    { OMX_VIDEO_AVCProfileHigh10,   110 },
+    { OMX_VIDEO_AVCProfileHigh422,  122 },
+    { OMX_VIDEO_AVCProfileHigh444,  244 },
+};
+
+size_t convert_omx_to_profile_idc(OMX_VIDEO_AVCPROFILETYPE profile_type)
+{
+    size_t array_length = sizeof(omx_to_profile_idc)/sizeof(omx_to_profile_idc[0]);
+    for (size_t i = 0; i < array_length; ++i) {
+        if (omx_to_profile_idc[i].omx_profile == profile_type)
+            return omx_to_profile_idc[i].profile_idc;
+    }
+    return 0;
+}
+
+static const struct
+{
+    OMX_VIDEO_AVCLEVELTYPE omx_level;
+    size_t                 level_idc;
+} omx_to_level_idc[] =
+{
+    { OMX_VIDEO_AVCLevel1,  10 },
+    { OMX_VIDEO_AVCLevel1b,  9 },
+    { OMX_VIDEO_AVCLevel11, 11 },
+    { OMX_VIDEO_AVCLevel12, 12 },
+    { OMX_VIDEO_AVCLevel13, 13 },
+    { OMX_VIDEO_AVCLevel2,  20 },
+    { OMX_VIDEO_AVCLevel21, 21 },
+    { OMX_VIDEO_AVCLevel22, 22 },
+    { OMX_VIDEO_AVCLevel3,  30 },
+    { OMX_VIDEO_AVCLevel31, 31 },
+    { OMX_VIDEO_AVCLevel32, 32 },
+    { OMX_VIDEO_AVCLevel4,  40 },
+    { OMX_VIDEO_AVCLevel41, 41 },
+    { OMX_VIDEO_AVCLevel42, 42 },
+    { OMX_VIDEO_AVCLevel5,  50 },
+    { OMX_VIDEO_AVCLevel51, 51 },
+};
+
+size_t convert_omx_to_level_idc(OMX_VIDEO_AVCLEVELTYPE level_type)
+{
+    size_t array_length = sizeof(omx_to_level_idc)/sizeof(omx_to_level_idc[0]);
+    for (size_t i = 0; i < array_length; ++i) {
+        if (omx_to_level_idc[i].omx_level == level_type)
+            return omx_to_level_idc[i].level_idc;
+    }
+    return 0;
+}