diff options
author | Vaibhav Deshu Venkatesh <vdeshuve@codeaurora.org> | 2017-07-27 18:19:13 -0700 |
---|---|---|
committer | Vaibhav Deshu Venkatesh <vdeshuve@codeaurora.org> | 2017-08-18 12:11:40 -0700 |
commit | ff86043037b4b58b16f3515a1536e3289a4709dd (patch) | |
tree | 0a7a63150a336c22363a02ef3754953c42cb15e2 /mm-video-v4l2 | |
parent | de6a3125066053967d448ad73ca95d4b9fe957fb (diff) | |
download | media-ff86043037b4b58b16f3515a1536e3289a4709dd.tar.gz |
mm-video-v4l2: Publish supported profile/level correctly
Get supported profile/level from driver and publish them
correctly to client from OMX.
CRs-Fixed: 2054346
Change-Id: I56c8d1631445e02dd0330d664802d044cce4a26e
Diffstat (limited to 'mm-video-v4l2')
-rw-r--r-- | mm-video-v4l2/vidc/common/inc/vidc_common.h | 66 | ||||
-rw-r--r-- | mm-video-v4l2/vidc/common/src/vidc_common.cpp | 227 | ||||
-rw-r--r-- | mm-video-v4l2/vidc/vdec/inc/omx_vdec.h | 1 | ||||
-rw-r--r-- | mm-video-v4l2/vidc/vdec/src/omx_vdec_v4l2.cpp | 182 | ||||
-rw-r--r-- | mm-video-v4l2/vidc/venc/inc/omx_swvenc_mpeg4.h | 3 | ||||
-rw-r--r-- | mm-video-v4l2/vidc/venc/inc/omx_video_base.h | 3 | ||||
-rw-r--r-- | mm-video-v4l2/vidc/venc/inc/omx_video_encoder.h | 1 | ||||
-rw-r--r-- | mm-video-v4l2/vidc/venc/inc/video_encoder_device_v4l2.h | 2 | ||||
-rw-r--r-- | mm-video-v4l2/vidc/venc/src/omx_video_base.cpp | 83 | ||||
-rw-r--r-- | mm-video-v4l2/vidc/venc/src/omx_video_encoder.cpp | 5 | ||||
-rw-r--r-- | mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp | 288 |
11 files changed, 552 insertions, 309 deletions
diff --git a/mm-video-v4l2/vidc/common/inc/vidc_common.h b/mm-video-v4l2/vidc/common/inc/vidc_common.h new file mode 100644 index 00000000..012b246d --- /dev/null +++ b/mm-video-v4l2/vidc/common/inc/vidc_common.h @@ -0,0 +1,66 @@ +/*-------------------------------------------------------------------------- +Copyright (c) 2017, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------*/ +#include <unordered_map> + +using pl_map = std::unordered_map<int, int>; +using codec_map = std::unordered_map<int, pl_map *>; + +class profile_level_converter { + static pl_map profile_avc_omx_to_v4l2; + static pl_map profile_hevc_omx_to_v4l2; + static pl_map profile_mpeg2_omx_to_v4l2; + static pl_map level_avc_omx_to_v4l2; + static pl_map level_hevc_omx_to_v4l2; + static pl_map level_vp8_omx_to_v4l2; + static pl_map level_mpeg2_omx_to_v4l2; + static pl_map profile_avc_v4l2_to_omx; + static pl_map profile_hevc_v4l2_to_omx; + static pl_map profile_mpeg2_v4l2_to_omx; + static pl_map level_avc_v4l2_to_omx; + static pl_map level_hevc_v4l2_to_omx; + static pl_map level_vp8_v4l2_to_omx; + static pl_map level_mpeg2_v4l2_to_omx; + + static codec_map profile_omx_to_v4l2_map; + static codec_map profile_v4l2_to_omx_map; + static codec_map level_omx_to_v4l2_map; + static codec_map level_v4l2_to_omx_map; + + //Constructor that initializes and performs the mapping + profile_level_converter() = delete; + static bool find_item(pl_map *map, int key, int *value); + static bool find_map(codec_map map, int key, pl_map **value_map); + + public: + static void init(); + static bool convert_v4l2_profile_to_omx(int codec, int v4l2_profile, int *omx_profile); + static bool convert_omx_profile_to_v4l2(int codec, int omx_profile, int *v4l2_profile); + static bool convert_v4l2_level_to_omx(int codec, int v4l2_level, int *omx_level); + static bool convert_omx_level_to_v4l2(int codec, int omx_level, int *v4l2_level); +}; diff --git a/mm-video-v4l2/vidc/common/src/vidc_common.cpp b/mm-video-v4l2/vidc/common/src/vidc_common.cpp index 931e7c53..6336ef38 100644 --- a/mm-video-v4l2/vidc/common/src/vidc_common.cpp +++ b/mm-video-v4l2/vidc/common/src/vidc_common.cpp @@ -30,5 +30,232 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <utils/Log.h> #include "vidc_debug.h" +#include "vidc_common.h" +#include "OMX_Core.h" +#include "OMX_QCOMExtns.h" +#include "OMX_VideoExt.h" +#include "OMX_IndexExt.h" +#include <linux/videodev2.h> int debug_level = PRIO_ERROR; + + +pl_map profile_level_converter::profile_avc_omx_to_v4l2 ({ + {QOMX_VIDEO_AVCProfileConstrainedBaseline, + V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE}, + {QOMX_VIDEO_AVCProfileBaseline, + V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE}, + {QOMX_VIDEO_AVCProfileMain, + V4L2_MPEG_VIDEO_H264_PROFILE_MAIN}, + {QOMX_VIDEO_AVCProfileConstrainedHigh, + V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH}, + {QOMX_VIDEO_AVCProfileHigh, + V4L2_MPEG_VIDEO_H264_PROFILE_HIGH} + }); + +pl_map profile_level_converter::profile_avc_v4l2_to_omx ({}); + +pl_map profile_level_converter::profile_hevc_omx_to_v4l2 ({ + {OMX_VIDEO_HEVCProfileMain, + V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN}, + {OMX_VIDEO_HEVCProfileMain10, + V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN10}, + }); + +pl_map profile_level_converter::profile_hevc_v4l2_to_omx ({}); + +pl_map profile_level_converter::profile_mpeg2_omx_to_v4l2 ({ + {OMX_VIDEO_MPEG2ProfileSimple, + V4L2_MPEG_VIDC_VIDEO_MPEG2_PROFILE_SIMPLE}, + {OMX_VIDEO_MPEG2ProfileMain, + V4L2_MPEG_VIDC_VIDEO_MPEG2_PROFILE_MAIN}, + }); + +pl_map profile_level_converter::profile_mpeg2_v4l2_to_omx ({}); + +pl_map profile_level_converter::level_avc_omx_to_v4l2 ({ + {OMX_VIDEO_AVCLevel1, V4L2_MPEG_VIDEO_H264_LEVEL_1_0}, + {OMX_VIDEO_AVCLevel11, V4L2_MPEG_VIDEO_H264_LEVEL_1_1}, + {OMX_VIDEO_AVCLevel12, V4L2_MPEG_VIDEO_H264_LEVEL_1_2}, + {OMX_VIDEO_AVCLevel13, V4L2_MPEG_VIDEO_H264_LEVEL_1_3}, + {OMX_VIDEO_AVCLevel1b, V4L2_MPEG_VIDEO_H264_LEVEL_1B}, + {OMX_VIDEO_AVCLevel2, V4L2_MPEG_VIDEO_H264_LEVEL_2_0}, + {OMX_VIDEO_AVCLevel21, V4L2_MPEG_VIDEO_H264_LEVEL_2_1}, + {OMX_VIDEO_AVCLevel22, V4L2_MPEG_VIDEO_H264_LEVEL_2_2}, + {OMX_VIDEO_AVCLevel3, V4L2_MPEG_VIDEO_H264_LEVEL_3_0}, + {OMX_VIDEO_AVCLevel31, V4L2_MPEG_VIDEO_H264_LEVEL_3_1}, + {OMX_VIDEO_AVCLevel32, V4L2_MPEG_VIDEO_H264_LEVEL_3_2}, + {OMX_VIDEO_AVCLevel4, V4L2_MPEG_VIDEO_H264_LEVEL_4_0}, + {OMX_VIDEO_AVCLevel41, V4L2_MPEG_VIDEO_H264_LEVEL_4_1}, + {OMX_VIDEO_AVCLevel42, V4L2_MPEG_VIDEO_H264_LEVEL_4_2}, + {OMX_VIDEO_AVCLevel5, V4L2_MPEG_VIDEO_H264_LEVEL_5_0}, + {OMX_VIDEO_AVCLevel51, V4L2_MPEG_VIDEO_H264_LEVEL_5_1}, + {OMX_VIDEO_AVCLevel52, V4L2_MPEG_VIDEO_H264_LEVEL_5_2}, + }); + +pl_map profile_level_converter::level_avc_v4l2_to_omx ({}); + +pl_map profile_level_converter::level_hevc_omx_to_v4l2 ({ + {OMX_VIDEO_HEVCMainTierLevel1, V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_1}, + {OMX_VIDEO_HEVCMainTierLevel2, V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_2}, + {OMX_VIDEO_HEVCMainTierLevel21, V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_2_1}, + {OMX_VIDEO_HEVCMainTierLevel3, V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_3}, + {OMX_VIDEO_HEVCMainTierLevel31, V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_3_1}, + {OMX_VIDEO_HEVCMainTierLevel4, V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_4}, + {OMX_VIDEO_HEVCMainTierLevel41, V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_4_1}, + {OMX_VIDEO_HEVCMainTierLevel5, V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_5}, + {OMX_VIDEO_HEVCMainTierLevel51, V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_5_1}, + {OMX_VIDEO_HEVCMainTierLevel52, V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_5_2}, + {OMX_VIDEO_HEVCMainTierLevel6, V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_6}, + {OMX_VIDEO_HEVCMainTierLevel61, V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_6_1}, + {OMX_VIDEO_HEVCMainTierLevel62, V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_6_2}, + {OMX_VIDEO_HEVCHighTierLevel1, V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_1}, + {OMX_VIDEO_HEVCHighTierLevel2, V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_2}, + {OMX_VIDEO_HEVCHighTierLevel21, V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_2_1}, + {OMX_VIDEO_HEVCHighTierLevel3, V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_3}, + {OMX_VIDEO_HEVCHighTierLevel31, V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_3_1}, + {OMX_VIDEO_HEVCHighTierLevel4, V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_4}, + {OMX_VIDEO_HEVCHighTierLevel41, V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_4_1}, + {OMX_VIDEO_HEVCHighTierLevel5, V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_5}, + {OMX_VIDEO_HEVCHighTierLevel51, V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_5_1}, + {OMX_VIDEO_HEVCHighTierLevel52, V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_5_2}, + {OMX_VIDEO_HEVCHighTierLevel6, V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_6}, + {OMX_VIDEO_HEVCHighTierLevel61, V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_6_1}, + {OMX_VIDEO_HEVCHighTierLevel62, V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_6_2}, + }); + +pl_map profile_level_converter::level_hevc_v4l2_to_omx ({}); + +pl_map profile_level_converter::level_vp8_omx_to_v4l2 ({ + {OMX_VIDEO_VP8Level_Version0, V4L2_MPEG_VIDC_VIDEO_VP8_VERSION_0}, + {OMX_VIDEO_VP8Level_Version1, V4L2_MPEG_VIDC_VIDEO_VP8_VERSION_1}, + {OMX_VIDEO_VP8Level_Version2, V4L2_MPEG_VIDC_VIDEO_VP8_VERSION_2}, + {OMX_VIDEO_VP8Level_Version3, V4L2_MPEG_VIDC_VIDEO_VP8_VERSION_3}, + }); + +pl_map profile_level_converter::level_vp8_v4l2_to_omx ({}); + +pl_map profile_level_converter::level_mpeg2_omx_to_v4l2 ({ + {OMX_VIDEO_MPEG2LevelLL, V4L2_MPEG_VIDC_VIDEO_MPEG2_LEVEL_0}, + {OMX_VIDEO_MPEG2LevelML, V4L2_MPEG_VIDC_VIDEO_MPEG2_LEVEL_1}, + {OMX_VIDEO_MPEG2LevelHL, V4L2_MPEG_VIDC_VIDEO_MPEG2_LEVEL_2}, + }); + +pl_map profile_level_converter::level_mpeg2_v4l2_to_omx ({}); + +codec_map profile_level_converter::profile_omx_to_v4l2_map ({ + {V4L2_PIX_FMT_H264, &profile_avc_omx_to_v4l2}, + {V4L2_PIX_FMT_HEVC, &profile_hevc_omx_to_v4l2}, + {V4L2_PIX_FMT_MPEG2, &profile_mpeg2_omx_to_v4l2}, + }); + +codec_map profile_level_converter::profile_v4l2_to_omx_map ({ + {V4L2_PIX_FMT_H264, &profile_avc_v4l2_to_omx}, + {V4L2_PIX_FMT_HEVC, &profile_hevc_v4l2_to_omx}, + {V4L2_PIX_FMT_MPEG2, &profile_mpeg2_v4l2_to_omx}, + }); + +codec_map profile_level_converter::level_omx_to_v4l2_map ({ + {V4L2_PIX_FMT_H264, &level_avc_omx_to_v4l2}, + {V4L2_PIX_FMT_HEVC, &level_hevc_omx_to_v4l2}, + {V4L2_PIX_FMT_MPEG2, &level_mpeg2_omx_to_v4l2}, + {V4L2_PIX_FMT_VP8, &level_vp8_omx_to_v4l2}, + /* VP9 uses same levels */ + {V4L2_PIX_FMT_VP9, &level_vp8_omx_to_v4l2}, + }); + +codec_map profile_level_converter::level_v4l2_to_omx_map ({ + {V4L2_PIX_FMT_H264, &level_avc_v4l2_to_omx}, + {V4L2_PIX_FMT_HEVC, &level_hevc_v4l2_to_omx}, + {V4L2_PIX_FMT_MPEG2, &level_mpeg2_v4l2_to_omx}, + {V4L2_PIX_FMT_VP8, &level_vp8_v4l2_to_omx}, + /* VP9 uses same levels */ + {V4L2_PIX_FMT_VP9, &level_vp8_v4l2_to_omx}, + }); + +void reverse_map(pl_map source_map, pl_map &dest_map) +{ + pl_map::iterator it; + + for(it = source_map.begin(); it != source_map.end(); it++) { + dest_map[it->second] = it->first; + } + return; +} + +void profile_level_converter::init() +{ + reverse_map(profile_avc_omx_to_v4l2, profile_avc_v4l2_to_omx); + reverse_map(profile_hevc_omx_to_v4l2, profile_hevc_v4l2_to_omx); + reverse_map(profile_mpeg2_omx_to_v4l2, profile_mpeg2_v4l2_to_omx); + reverse_map(level_avc_omx_to_v4l2, level_avc_v4l2_to_omx); + reverse_map(level_hevc_omx_to_v4l2, level_hevc_v4l2_to_omx); + reverse_map(level_vp8_omx_to_v4l2, level_vp8_v4l2_to_omx); + reverse_map(level_mpeg2_omx_to_v4l2, level_mpeg2_v4l2_to_omx); +} + +bool profile_level_converter::find_map(codec_map map, int key, pl_map **value_map) +{ + codec_map::iterator map_it; + + map_it = map.find (key); + if (map_it == map.end()) { + DEBUG_PRINT_ERROR(" Invalid codec : %d Cannot find map for this codec", key); + return false; + } + *value_map = map_it->second; + return true; +} + +bool profile_level_converter::find_item(pl_map *map, int key, int *value) +{ + pl_map::iterator it; + + it = map->find (key); + if (it == map->end()) { + DEBUG_PRINT_ERROR(" Invalid key : %d Cannot find key in map ", key); + return false; + } + *value = it->second; + return true; +} + +bool profile_level_converter::convert_v4l2_profile_to_omx(int codec, int v4l2_profile, int *omx_profile) +{ + pl_map *profile_map; + + if (!find_map(profile_v4l2_to_omx_map, codec, &profile_map)) + return false; + + return find_item(profile_map, v4l2_profile, omx_profile); +} + +bool profile_level_converter::convert_omx_profile_to_v4l2(int codec, int omx_profile, int *v4l2_profile) +{ + pl_map *profile_map; + + if (!find_map(profile_omx_to_v4l2_map, codec, &profile_map)) + return false; + + return find_item(profile_map, omx_profile, v4l2_profile); +} + +bool profile_level_converter::convert_v4l2_level_to_omx(int codec, int v4l2_level, int *omx_level) +{ + pl_map *level_map; + + if (!find_map(level_v4l2_to_omx_map, codec, &level_map)) + return false; + + return find_item(level_map, v4l2_level, omx_level); +} + +bool profile_level_converter::convert_omx_level_to_v4l2(int codec, int omx_level, int *v4l2_level) +{ + pl_map *level_map; + + if (!find_map(level_omx_to_v4l2_map, codec, &level_map)) + return false; + + return find_item(level_map, omx_level, v4l2_level); +} diff --git a/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h b/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h index a0fe4633..fe29239d 100644 --- a/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h +++ b/mm-video-v4l2/vidc/vdec/inc/omx_vdec.h @@ -1346,6 +1346,7 @@ class omx_vdec: public qc_omx_component void convert_hdr_info_to_metadata(HDRStaticInfo& hdr_info, ColorMetaData &color_mdata); void get_preferred_color_aspects(ColorAspects& preferredColorAspects); void get_preferred_hdr_info(HDRStaticInfo& preferredHDRInfo); + bool vdec_query_cap(struct v4l2_queryctrl &cap); }; enum instance_state { diff --git a/mm-video-v4l2/vidc/vdec/src/omx_vdec_v4l2.cpp b/mm-video-v4l2/vidc/vdec/src/omx_vdec_v4l2.cpp index 797cc49c..c18fd93b 100644 --- a/mm-video-v4l2/vidc/vdec/src/omx_vdec_v4l2.cpp +++ b/mm-video-v4l2/vidc/vdec/src/omx_vdec_v4l2.cpp @@ -48,6 +48,7 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <unistd.h> #include <errno.h> #include "omx_vdec.h" +#include "vidc_common.h" #include <fcntl.h> #include <limits.h> #include <stdlib.h> @@ -864,6 +865,8 @@ omx_vdec::omx_vdec(): m_error_propogated(false), m_color_space = EXCEPT_BT2020; init_color_aspects_map(); + + profile_level_converter::init(); } static const int event_type[] = { @@ -3376,78 +3379,131 @@ bool omx_vdec::post_event(unsigned long p1, return bRet; } +bool inline omx_vdec::vdec_query_cap(struct v4l2_queryctrl &cap) { + + if (ioctl(drv_ctx.video_driver_fd, VIDIOC_QUERYCTRL, &cap)) { + DEBUG_PRINT_ERROR("Query caps for id = %u failed\n", cap.id); + return false; + } + return true; +} + OMX_ERRORTYPE omx_vdec::get_supported_profile_level(OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType) { OMX_ERRORTYPE eRet = OMX_ErrorNone; + struct v4l2_queryctrl profile_cap, level_cap; + int v4l2_profile; + int avc_profiles[5] = { QOMX_VIDEO_AVCProfileConstrainedBaseline, + QOMX_VIDEO_AVCProfileBaseline, + QOMX_VIDEO_AVCProfileMain, + QOMX_VIDEO_AVCProfileConstrainedHigh, + QOMX_VIDEO_AVCProfileHigh }; + int hevc_profiles[2] = { OMX_VIDEO_HEVCProfileMain, + OMX_VIDEO_HEVCProfileMain10 }; + int mpeg2_profiles[2] = { OMX_VIDEO_MPEG2ProfileSimple, + OMX_VIDEO_MPEG2ProfileMain}; + if (!profileLevelType) return OMX_ErrorBadParameter; - if (profileLevelType->nPortIndex == 0) { - if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.avc",OMX_MAX_STRINGNAME_SIZE)) { - profileLevelType->eLevel = OMX_VIDEO_AVCLevel51; - if (profileLevelType->nProfileIndex == 0) { - profileLevelType->eProfile = OMX_VIDEO_AVCProfileBaseline; - } else if (profileLevelType->nProfileIndex == 1) { - profileLevelType->eProfile = OMX_VIDEO_AVCProfileMain; - } else if (profileLevelType->nProfileIndex == 2) { - profileLevelType->eProfile = OMX_VIDEO_AVCProfileHigh; - } else if (profileLevelType->nProfileIndex == 3) { - profileLevelType->eProfile = QOMX_VIDEO_AVCProfileConstrainedBaseline; - } else if (profileLevelType->nProfileIndex == 4) { - profileLevelType->eProfile = QOMX_VIDEO_AVCProfileConstrainedHigh; - } else { - DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u", - (unsigned int)profileLevelType->nProfileIndex); - eRet = OMX_ErrorNoMore; - } - } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mvc", OMX_MAX_STRINGNAME_SIZE)) { - if (profileLevelType->nProfileIndex == 0) { - profileLevelType->eProfile = QOMX_VIDEO_MVCProfileStereoHigh; - profileLevelType->eLevel = QOMX_VIDEO_MVCLevel51; - } else { - DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u", - (unsigned int)profileLevelType->nProfileIndex); - eRet = OMX_ErrorNoMore; - } - } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.hevc", OMX_MAX_STRINGNAME_SIZE)) { - if (profileLevelType->nProfileIndex == 0) { - profileLevelType->eProfile = OMX_VIDEO_HEVCProfileMain; - profileLevelType->eLevel = OMX_VIDEO_HEVCMainTierLevel51; - } else if (profileLevelType->nProfileIndex == 1) { - profileLevelType->eProfile = OMX_VIDEO_HEVCProfileMain10; - profileLevelType->eLevel = OMX_VIDEO_HEVCMainTierLevel51; - } else if (profileLevelType->nProfileIndex == 2) { - profileLevelType->eProfile = OMX_VIDEO_HEVCProfileMain10HDR10; - profileLevelType->eLevel = OMX_VIDEO_HEVCMainTierLevel51; - } else { - DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u", - (unsigned int)profileLevelType->nProfileIndex); - eRet = OMX_ErrorNoMore; - } - } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp8",OMX_MAX_STRINGNAME_SIZE) || - !strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.vp9",OMX_MAX_STRINGNAME_SIZE)) { - eRet = OMX_ErrorNoMore; - } else if (!strncmp(drv_ctx.kind, "OMX.qcom.video.decoder.mpeg2",OMX_MAX_STRINGNAME_SIZE)) { - if (profileLevelType->nProfileIndex == 0) { - profileLevelType->eProfile = OMX_VIDEO_MPEG2ProfileSimple; - profileLevelType->eLevel = OMX_VIDEO_MPEG2LevelHL; - } else if (profileLevelType->nProfileIndex == 1) { - profileLevelType->eProfile = OMX_VIDEO_MPEG2ProfileMain; - profileLevelType->eLevel = OMX_VIDEO_MPEG2LevelHL; - } else { - DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u", - (unsigned int)profileLevelType->nProfileIndex); - eRet = OMX_ErrorNoMore; - } + memset(&level_cap, 0, sizeof(struct v4l2_queryctrl)); + memset(&profile_cap, 0, sizeof(struct v4l2_queryctrl)); + + if (output_capability == V4L2_PIX_FMT_H264) { + level_cap.id = V4L2_CID_MPEG_VIDEO_H264_LEVEL; + profile_cap.id = V4L2_CID_MPEG_VIDEO_H264_PROFILE; + } else if (output_capability == V4L2_PIX_FMT_VP8 || + output_capability == V4L2_PIX_FMT_VP9) { + level_cap.id = V4L2_CID_MPEG_VIDC_VIDEO_VP8_PROFILE_LEVEL; + } else if (output_capability == V4L2_PIX_FMT_HEVC) { + level_cap.id = V4L2_CID_MPEG_VIDC_VIDEO_HEVC_TIER_LEVEL; + profile_cap.id = V4L2_CID_MPEG_VIDC_VIDEO_HEVC_PROFILE; + } else if (output_capability == V4L2_PIX_FMT_MPEG2) { + level_cap.id = V4L2_CID_MPEG_VIDC_VIDEO_MPEG2_LEVEL; + profile_cap.id = V4L2_CID_MPEG_VIDC_VIDEO_MPEG2_PROFILE; + } else { + DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported Invalid codec"); + return OMX_ErrorInvalidComponent; + } + + if (profile_cap.id) { + if(!vdec_query_cap(profile_cap)) { + DEBUG_PRINT_ERROR("Getting capabilities for profile failed"); + return OMX_ErrorHardware; + } + } + + if (level_cap.id) { + if(!vdec_query_cap(level_cap)) { + DEBUG_PRINT_ERROR("Getting capabilities for level failed"); + return OMX_ErrorHardware; + } + } + + /* Get the corresponding omx level from v4l2 level */ + if (!profile_level_converter::convert_v4l2_level_to_omx(output_capability, level_cap.maximum, (int *)&profileLevelType->eLevel)) { + DEBUG_PRINT_ERROR("Invalid level, cannot find corresponding v4l2 level : %d ", level_cap.maximum); + return OMX_ErrorHardware; + } + + /* For given profile index get corresponding profile that needs to be supported */ + if (profileLevelType->nPortIndex != OMX_CORE_INPUT_PORT_INDEX) { + DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported should be queried on Input port only %u", (unsigned int)profileLevelType->nPortIndex); + return OMX_ErrorBadPortIndex; + } + + if (output_capability == V4L2_PIX_FMT_H264) { + if (profileLevelType->nProfileIndex < (sizeof(avc_profiles)/sizeof(int))) { + profileLevelType->eProfile = avc_profiles[profileLevelType->nProfileIndex]; } else { - DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported ret NoMore for codec: %s", drv_ctx.kind); - eRet = OMX_ErrorNoMore; + DEBUG_PRINT_LOW("AVC: get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u", + (unsigned int)profileLevelType->nProfileIndex); + return OMX_ErrorNoMore; + } + } else if (output_capability == V4L2_PIX_FMT_VP8 || + output_capability == V4L2_PIX_FMT_VP9) { + if (profileLevelType->nProfileIndex == 0) { + profileLevelType->eProfile = OMX_VIDEO_VP8ProfileMain; + } else { + DEBUG_PRINT_LOW("VP8: get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u", + (unsigned int)profileLevelType->nProfileIndex); + return OMX_ErrorNoMore; + } + /* Driver has no notion of VP8 profile. Only one profile is supported. Return this */ + return OMX_ErrorNone; + } else if (output_capability == V4L2_PIX_FMT_HEVC) { + if (profileLevelType->nProfileIndex < (sizeof(hevc_profiles)/sizeof(int))) { + profileLevelType->eProfile = hevc_profiles[profileLevelType->nProfileIndex]; + } else { + DEBUG_PRINT_LOW("HEVC: get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u", + (unsigned int)profileLevelType->nProfileIndex); + return OMX_ErrorNoMore; + } + } else if (output_capability == V4L2_PIX_FMT_MPEG2) { + if (profileLevelType->nProfileIndex < (sizeof(mpeg2_profiles)/sizeof(int))) { + profileLevelType->eProfile = mpeg2_profiles[profileLevelType->nProfileIndex]; + } else { + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u", + (unsigned int)profileLevelType->nProfileIndex); + return OMX_ErrorNoMore; } - } else { - DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported should be queries on Input port only %u", - (unsigned int)profileLevelType->nPortIndex); - eRet = OMX_ErrorBadPortIndex; } + + /* Check if the profile is supported by driver or not */ + /* During query caps of profile driver sends a mask of */ + /* of all v4l2 profiles supported(in the flags field) */ + if (!profile_level_converter::convert_omx_profile_to_v4l2(output_capability, profileLevelType->eProfile, &v4l2_profile)) { + DEBUG_PRINT_ERROR("Invalid profile, cannot find corresponding omx profile"); + return OMX_ErrorHardware; + } + + if(!((profile_cap.flags >> v4l2_profile) & 0x1)) { + DEBUG_PRINT_ERROR("%s: Invalid index corresponding profile not supported : %d ",__FUNCTION__, profileLevelType->eProfile); + eRet = OMX_ErrorNoMore; + } + + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported for Input port returned Profile:%u, Level:%u", + (unsigned int)profileLevelType->eProfile, (unsigned int)profileLevelType->eLevel); return eRet; } diff --git a/mm-video-v4l2/vidc/venc/inc/omx_swvenc_mpeg4.h b/mm-video-v4l2/vidc/venc/inc/omx_swvenc_mpeg4.h index 8c68ce3d..f3f72b61 100644 --- a/mm-video-v4l2/vidc/venc/inc/omx_swvenc_mpeg4.h +++ b/mm-video-v4l2/vidc/venc/inc/omx_swvenc_mpeg4.h @@ -141,6 +141,9 @@ class omx_venc: public omx_video OMX_VIDEO_ANDROID_TEMPORALLAYERINGPATTERNTYPE */*SupportedPattern*/) { return false; } + OMX_ERRORTYPE dev_get_supported_profile_level(OMX_VIDEO_PARAM_PROFILELEVELTYPE */*profileLevelType*/) { + return OMX_ErrorNone; + } bool dev_is_video_session_supported(OMX_U32 width, OMX_U32 height); bool dev_color_align(OMX_BUFFERHEADERTYPE *buffer, OMX_U32 width, OMX_U32 height); diff --git a/mm-video-v4l2/vidc/venc/inc/omx_video_base.h b/mm-video-v4l2/vidc/venc/inc/omx_video_base.h index 12fcdf0c..d8981254 100644 --- a/mm-video-v4l2/vidc/venc/inc/omx_video_base.h +++ b/mm-video-v4l2/vidc/venc/inc/omx_video_base.h @@ -292,6 +292,7 @@ class omx_video: public qc_omx_component virtual bool dev_buffer_ready_to_queue(OMX_BUFFERHEADERTYPE *buffer) = 0; virtual bool dev_get_temporal_layer_caps(OMX_U32 * /*nMaxLayers*/, OMX_U32 * /*nMaxBLayers*/, OMX_VIDEO_ANDROID_TEMPORALLAYERINGPATTERNTYPE */*SupportedPattern*/) = 0; + virtual OMX_ERRORTYPE dev_get_supported_profile_level(OMX_VIDEO_PARAM_PROFILELEVELTYPE *) = 0; #ifdef _ANDROID_ICS_ void omx_release_meta_buffer(OMX_BUFFERHEADERTYPE *buffer); #endif @@ -583,7 +584,7 @@ class omx_video: public qc_omx_component unsigned long p2, unsigned long id ); - OMX_ERRORTYPE get_supported_profile_level(OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType); + inline void omx_report_error () { if (m_pCallbacks.EventHandler && !m_error_propogated && m_state != OMX_StateLoaded) { m_error_propogated = true; diff --git a/mm-video-v4l2/vidc/venc/inc/omx_video_encoder.h b/mm-video-v4l2/vidc/venc/inc/omx_video_encoder.h index 7419c005..1b8f462d 100644 --- a/mm-video-v4l2/vidc/venc/inc/omx_video_encoder.h +++ b/mm-video-v4l2/vidc/venc/inc/omx_video_encoder.h @@ -85,6 +85,7 @@ class omx_venc: public omx_video bool dev_get_batch_size(OMX_U32 *); bool dev_get_temporal_layer_caps(OMX_U32 * /*nMaxLayers*/, OMX_U32 * /*nMaxBLayers*/, OMX_VIDEO_ANDROID_TEMPORALLAYERINGPATTERNTYPE */*SupportedPattern*/); + OMX_ERRORTYPE dev_get_supported_profile_level(OMX_VIDEO_PARAM_PROFILELEVELTYPE *); bool dev_is_video_session_supported(OMX_U32 width, OMX_U32 height); bool dev_color_align(OMX_BUFFERHEADERTYPE *buffer, OMX_U32 width, OMX_U32 height); diff --git a/mm-video-v4l2/vidc/venc/inc/video_encoder_device_v4l2.h b/mm-video-v4l2/vidc/venc/inc/video_encoder_device_v4l2.h index e2f0ab54..165c0a82 100644 --- a/mm-video-v4l2/vidc/venc/inc/video_encoder_device_v4l2.h +++ b/mm-video-v4l2/vidc/venc/inc/video_encoder_device_v4l2.h @@ -45,6 +45,7 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "omx_video_common.h" #include "omx_video_base.h" #include "omx_video_encoder.h" +#include "vidc_common.h" #include <linux/videodev2.h> #include <media/msm_vidc.h> #include <poll.h> @@ -337,6 +338,7 @@ class venc_dev bool venc_get_batch_size(OMX_U32 *size); bool venc_get_temporal_layer_caps(OMX_U32 * /*nMaxLayers*/, OMX_U32 * /*nMaxBLayers*/, OMX_VIDEO_ANDROID_TEMPORALLAYERINGPATTERNTYPE */*SupportedPattern*/); + OMX_ERRORTYPE venc_get_supported_profile_level(OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType); bool venc_check_for_hybrid_hp(OMX_VIDEO_ANDROID_TEMPORALLAYERINGPATTERNTYPE ePattern); bool venc_check_for_hierp(OMX_VIDEO_ANDROID_TEMPORALLAYERINGPATTERNTYPE ePattern); int venc_find_hier_type(OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE &temporalSettings); diff --git a/mm-video-v4l2/vidc/venc/src/omx_video_base.cpp b/mm-video-v4l2/vidc/venc/src/omx_video_base.cpp index a14fb60f..06a75161 100644 --- a/mm-video-v4l2/vidc/venc/src/omx_video_base.cpp +++ b/mm-video-v4l2/vidc/venc/src/omx_video_base.cpp @@ -1656,7 +1656,7 @@ OMX_ERRORTYPE omx_video::get_parameter(OMX_IN OMX_HANDLETYPE hComp, VALIDATE_OMX_PARAM_DATA(paramData, OMX_VIDEO_PARAM_PROFILELEVELTYPE); OMX_VIDEO_PARAM_PROFILELEVELTYPE* pParam = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)paramData; DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported"); - eRet = get_supported_profile_level(pParam); + eRet = dev_get_supported_profile_level(pParam); if (eRet && eRet != OMX_ErrorNoMore) DEBUG_PRINT_ERROR("Invalid entry returned from get_supported_profile_level %u, %u", (unsigned int)pParam->eProfile, (unsigned int)pParam->eLevel); @@ -4635,87 +4635,6 @@ void omx_video::complete_pending_buffer_done_cbs() } } -OMX_ERRORTYPE omx_video::get_supported_profile_level(OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType) -{ - OMX_ERRORTYPE eRet = OMX_ErrorNone; - if (!profileLevelType) - return OMX_ErrorBadParameter; - - if (profileLevelType->nPortIndex == 1) { - if (m_sOutPortDef.format.video.eCompressionFormat == OMX_VIDEO_CodingAVC) { - if (profileLevelType->nProfileIndex == 0) { - profileLevelType->eProfile = OMX_VIDEO_AVCProfileBaseline; - profileLevelType->eLevel = OMX_VIDEO_AVCLevel52; - } else if (profileLevelType->nProfileIndex == 1) { - profileLevelType->eProfile = OMX_VIDEO_AVCProfileMain; - profileLevelType->eLevel = OMX_VIDEO_AVCLevel52; - } else if (profileLevelType->nProfileIndex == 2) { - profileLevelType->eProfile = OMX_VIDEO_AVCProfileHigh; - profileLevelType->eLevel = OMX_VIDEO_AVCLevel52; - } else if (profileLevelType->nProfileIndex == 3) { - profileLevelType->eProfile = QOMX_VIDEO_AVCProfileConstrainedBaseline; - profileLevelType->eLevel = OMX_VIDEO_AVCLevel52; - } else if (profileLevelType->nProfileIndex == 4) { - profileLevelType->eProfile = QOMX_VIDEO_AVCProfileConstrainedHigh; - profileLevelType->eLevel = OMX_VIDEO_AVCLevel52; - } else { - DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u", - (unsigned int)profileLevelType->nProfileIndex); - eRet = OMX_ErrorNoMore; - } - } else if (m_sOutPortDef.format.video.eCompressionFormat == OMX_VIDEO_CodingH263) { - if (profileLevelType->nProfileIndex == 0) { - profileLevelType->eProfile = OMX_VIDEO_H263ProfileBaseline; - profileLevelType->eLevel = OMX_VIDEO_H263Level70; - } else { - DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u", (unsigned int)profileLevelType->nProfileIndex); - eRet = OMX_ErrorNoMore; - } - } else if (m_sOutPortDef.format.video.eCompressionFormat == OMX_VIDEO_CodingMPEG4) { - if (profileLevelType->nProfileIndex == 0) { - profileLevelType->eProfile = OMX_VIDEO_MPEG4ProfileSimple; - profileLevelType->eLevel = OMX_VIDEO_MPEG4Level5; - } else if (profileLevelType->nProfileIndex == 1) { - profileLevelType->eProfile = OMX_VIDEO_MPEG4ProfileAdvancedSimple; - profileLevelType->eLevel = OMX_VIDEO_MPEG4Level5; - } else { - DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u", (unsigned int)profileLevelType->nProfileIndex); - eRet = OMX_ErrorNoMore; - } - } else if (m_sOutPortDef.format.video.eCompressionFormat == OMX_VIDEO_CodingVP8) { - if (profileLevelType->nProfileIndex == 0) { - profileLevelType->eProfile = OMX_VIDEO_VP8ProfileMain; - profileLevelType->eLevel = OMX_VIDEO_VP8Level_Version0; - } else if (profileLevelType->nProfileIndex == 1) { - profileLevelType->eProfile = OMX_VIDEO_VP8ProfileMain; - profileLevelType->eLevel = OMX_VIDEO_VP8Level_Version1; - } else { - DEBUG_PRINT_LOW("VP8: get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u", - (unsigned int)profileLevelType->nProfileIndex); - eRet = OMX_ErrorNoMore; - } - } else if (m_sOutPortDef.format.video.eCompressionFormat == OMX_VIDEO_CodingHEVC) { - if (profileLevelType->nProfileIndex == 0) { - profileLevelType->eProfile = OMX_VIDEO_HEVCProfileMain; - profileLevelType->eLevel = OMX_VIDEO_HEVCMainTierLevel51; - } else { - DEBUG_PRINT_LOW("HEVC: get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u", - (unsigned int)profileLevelType->nProfileIndex); - eRet = OMX_ErrorNoMore; - } - } else { - DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported ret NoMore"); - eRet = OMX_ErrorNoMore; - } - } else { - DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported should be queried on Input port only %u", (unsigned int)profileLevelType->nPortIndex); - eRet = OMX_ErrorBadPortIndex; - } - DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported for Input port returned Profile:%u, Level:%u", - (unsigned int)profileLevelType->eProfile, (unsigned int)profileLevelType->eLevel); - return eRet; -} - #ifdef USE_ION int omx_video::alloc_map_ion_memory(int size, struct ion_allocation_data *alloc_data, diff --git a/mm-video-v4l2/vidc/venc/src/omx_video_encoder.cpp b/mm-video-v4l2/vidc/venc/src/omx_video_encoder.cpp index 74be593c..659aa880 100644 --- a/mm-video-v4l2/vidc/venc/src/omx_video_encoder.cpp +++ b/mm-video-v4l2/vidc/venc/src/omx_video_encoder.cpp @@ -2199,6 +2199,11 @@ bool omx_venc::dev_get_temporal_layer_caps(OMX_U32 *nMaxLayers, return handle->venc_get_temporal_layer_caps(nMaxLayers, nMaxBLayers, eSupportedPattern); } +OMX_ERRORTYPE omx_venc::dev_get_supported_profile_level(OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType) +{ + return handle->venc_get_supported_profile_level(profileLevelType); +} + bool omx_venc::dev_loaded_start() { return handle->venc_loaded_start(); diff --git a/mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp b/mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp index 635c89b8..5f5ccfe6 100644 --- a/mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp +++ b/mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp @@ -200,6 +200,8 @@ venc_dev::venc_dev(class omx_venc *venc_class) strlcpy(m_debug.log_loc, property_value, PROPERTY_VALUE_MAX); mUseAVTimerTimestamps = false; + + profile_level_converter::init(); } venc_dev::~venc_dev() @@ -983,6 +985,112 @@ int venc_dev::venc_set_format(int format) return rc; } +OMX_ERRORTYPE venc_dev::venc_get_supported_profile_level(OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevelType) +{ + OMX_ERRORTYPE eRet = OMX_ErrorNone; + struct v4l2_queryctrl profile_cap, level_cap; + int v4l2_profile; + int avc_profiles[5] = { QOMX_VIDEO_AVCProfileConstrainedBaseline, + QOMX_VIDEO_AVCProfileBaseline, + QOMX_VIDEO_AVCProfileMain, + QOMX_VIDEO_AVCProfileConstrainedHigh, + QOMX_VIDEO_AVCProfileHigh }; + int hevc_profiles[2] = { OMX_VIDEO_HEVCProfileMain, + OMX_VIDEO_HEVCProfileMain10 }; + + if (!profileLevelType) + return OMX_ErrorBadParameter; + + memset(&level_cap, 0, sizeof(struct v4l2_queryctrl)); + memset(&profile_cap, 0, sizeof(struct v4l2_queryctrl)); + + if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264) { + level_cap.id = V4L2_CID_MPEG_VIDEO_H264_LEVEL; + profile_cap.id = V4L2_CID_MPEG_VIDEO_H264_PROFILE; + } else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_VP8) { + level_cap.id = V4L2_CID_MPEG_VIDC_VIDEO_VP8_PROFILE_LEVEL; + } else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC) { + level_cap.id = V4L2_CID_MPEG_VIDC_VIDEO_HEVC_TIER_LEVEL; + profile_cap.id = V4L2_CID_MPEG_VIDC_VIDEO_HEVC_PROFILE; + } else { + DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported Invalid codec"); + return OMX_ErrorInvalidComponent; + } + + if (profile_cap.id) { + if(!venc_query_cap(profile_cap)) { + DEBUG_PRINT_ERROR("Getting capabilities for profile failed"); + return OMX_ErrorHardware; + } + } + + if (level_cap.id) { + if(!venc_query_cap(level_cap)) { + DEBUG_PRINT_ERROR("Getting capabilities for level failed"); + return OMX_ErrorHardware; + } + } + + /* Get the corresponding omx level from v4l2 level */ + if (!profile_level_converter::convert_v4l2_level_to_omx(m_sVenc_cfg.codectype, level_cap.maximum, (int *)&profileLevelType->eLevel)) { + DEBUG_PRINT_ERROR("Invalid level, cannot find corresponding v4l2 level : %d ", level_cap.maximum); + return OMX_ErrorHardware; + } + + /* For given profile index get corresponding profile that needs to be supported */ + if (profileLevelType->nPortIndex != 1) { + DEBUG_PRINT_ERROR("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported should be queried on output port only %u", + (unsigned int)profileLevelType->nPortIndex); + return OMX_ErrorBadPortIndex; + } + + if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264) { + if (profileLevelType->nProfileIndex < (sizeof(avc_profiles)/sizeof(int))) { + profileLevelType->eProfile = avc_profiles[profileLevelType->nProfileIndex]; + } else { + DEBUG_PRINT_LOW("AVC: get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u", + (unsigned int)profileLevelType->nProfileIndex); + return OMX_ErrorNoMore; + } + } else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_VP8) { + if (profileLevelType->nProfileIndex == 0) { + profileLevelType->eProfile = OMX_VIDEO_VP8ProfileMain; + } else { + DEBUG_PRINT_LOW("VP8: get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u", + (unsigned int)profileLevelType->nProfileIndex); + return OMX_ErrorNoMore; + } + /* Driver has no notion of VP8 profile and there is only one profile supported. Hence return here */ + return OMX_ErrorNone; + } else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC) { + if (profileLevelType->nProfileIndex < (sizeof(hevc_profiles)/sizeof(int))) { + profileLevelType->eProfile = hevc_profiles[profileLevelType->nProfileIndex]; + } else { + DEBUG_PRINT_LOW("HEVC: get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported nProfileIndex ret NoMore %u", + (unsigned int)profileLevelType->nProfileIndex); + return OMX_ErrorNoMore; + } + } + + /* Check if the profile is supported by driver or not */ + /* During query caps of profile driver sends a mask of */ + /* of all v4l2 profiles supported(in the flags field) */ + if (!profile_level_converter::convert_omx_profile_to_v4l2(m_sVenc_cfg.codectype, profileLevelType->eProfile, &v4l2_profile)) { + DEBUG_PRINT_ERROR("Invalid profile, cannot find corresponding omx profile"); + return OMX_ErrorHardware; + } + + DEBUG_PRINT_INFO("v4l2 profile : %d flags : %d ", v4l2_profile, profile_cap.flags); + if(!((profile_cap.flags >> v4l2_profile) & 0x1)) { + DEBUG_PRINT_ERROR("%s: Invalid index corresponding profile not supported : %d ",__FUNCTION__, profileLevelType->eProfile); + eRet = OMX_ErrorNoMore; + } + + DEBUG_PRINT_LOW("get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported for Input port returned Profile:%u, Level:%u", + (unsigned int)profileLevelType->eProfile, (unsigned int)profileLevelType->eLevel); + return eRet; +} + OMX_ERRORTYPE venc_dev::allocate_extradata(struct extradata_buffer_info *extradata_info, int flags) { if (extradata_info->allocated) { @@ -4598,39 +4706,22 @@ bool venc_dev::venc_set_profile(OMX_U32 eProfile) if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264) { control.id = V4L2_CID_MPEG_VIDEO_H264_PROFILE; - if (eProfile == OMX_VIDEO_AVCProfileBaseline) { - control.value = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE; - } else if(eProfile == QOMX_VIDEO_AVCProfileConstrainedBaseline) { - control.value = V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE; - } else if(eProfile == QOMX_VIDEO_AVCProfileConstrainedHigh) { - control.value = V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH; - } else if (eProfile == OMX_VIDEO_AVCProfileMain) { - control.value = V4L2_MPEG_VIDEO_H264_PROFILE_MAIN; - } else if (eProfile == OMX_VIDEO_AVCProfileHigh) { - control.value = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH; - } else { - DEBUG_PRINT_LOW("ERROR: Unsupported H.264 profile = %d", eProfile); - return false; - } } else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_VP8) { //In driver VP8 profile is hardcoded. No need to set anything from here return true; } else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC) { control.id = V4L2_CID_MPEG_VIDC_VIDEO_HEVC_PROFILE; - if (eProfile == OMX_VIDEO_HEVCProfileMain) { - control.value = V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN; - } else if(eProfile == OMX_VIDEO_HEVCProfileMain10) { - control.value = V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN10; - } else { - DEBUG_PRINT_ERROR("ERROR: Unsupported HEVC profile = %d", - eProfile); - return false; - } } else { DEBUG_PRINT_ERROR("Wrong CODEC"); return false; } + if (!profile_level_converter::convert_omx_profile_to_v4l2(m_sVenc_cfg.codectype, eProfile, &control.value)) { + DEBUG_PRINT_ERROR("Cannot find v4l2 profile for OMX profile : %d Codec : %lu ", + eProfile, m_sVenc_cfg.codectype); + return false; + } + DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value); rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control); @@ -4638,11 +4729,9 @@ bool venc_dev::venc_set_profile(OMX_U32 eProfile) DEBUG_PRINT_ERROR("Failed to set control, id %#x, value %d", control.id, control.value); return false; } - DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value); codec_profile.profile = control.value; - return true; } @@ -4656,64 +4745,7 @@ bool venc_dev::venc_set_level(OMX_U32 eLevel) if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264) { control.id = V4L2_CID_MPEG_VIDEO_H264_LEVEL; - switch(eLevel) { - case OMX_VIDEO_AVCLevel1: - control.value = V4L2_MPEG_VIDEO_H264_LEVEL_1_0; - break; - case OMX_VIDEO_AVCLevel1b: - control.value = V4L2_MPEG_VIDEO_H264_LEVEL_1B; - break; - case OMX_VIDEO_AVCLevel11: - control.value = V4L2_MPEG_VIDEO_H264_LEVEL_1_1; - break; - case OMX_VIDEO_AVCLevel12: - control.value = V4L2_MPEG_VIDEO_H264_LEVEL_1_2; - break; - case OMX_VIDEO_AVCLevel13: - control.value = V4L2_MPEG_VIDEO_H264_LEVEL_1_3; - break; - case OMX_VIDEO_AVCLevel2: - control.value = V4L2_MPEG_VIDEO_H264_LEVEL_2_0; - break; - case OMX_VIDEO_AVCLevel21: - control.value = V4L2_MPEG_VIDEO_H264_LEVEL_2_1; - break; - case OMX_VIDEO_AVCLevel22: - control.value = V4L2_MPEG_VIDEO_H264_LEVEL_2_2; - break; - case OMX_VIDEO_AVCLevel3: - control.value = V4L2_MPEG_VIDEO_H264_LEVEL_3_0; - break; - case OMX_VIDEO_AVCLevel31: - control.value = V4L2_MPEG_VIDEO_H264_LEVEL_3_1; - break; - case OMX_VIDEO_AVCLevel32: - control.value = V4L2_MPEG_VIDEO_H264_LEVEL_3_2; - break; - case OMX_VIDEO_AVCLevel4: - control.value = V4L2_MPEG_VIDEO_H264_LEVEL_4_0; - break; - case OMX_VIDEO_AVCLevel41: - control.value = V4L2_MPEG_VIDEO_H264_LEVEL_4_1; - break; - case OMX_VIDEO_AVCLevel42: - control.value = V4L2_MPEG_VIDEO_H264_LEVEL_4_2; - break; - case OMX_VIDEO_AVCLevel5: - control.value = V4L2_MPEG_VIDEO_H264_LEVEL_5_0; - break; - case OMX_VIDEO_AVCLevel51: - control.value = V4L2_MPEG_VIDEO_H264_LEVEL_5_1; - break; - case OMX_VIDEO_AVCLevel52: - control.value = V4L2_MPEG_VIDEO_H264_LEVEL_5_2; - break; - case OMX_VIDEO_AVCLevelMax: - case OMX_VIDEO_LEVEL_UNKNOWN: - default: //Set max level possible as default so that invalid levels are non-fatal - control.value = V4L2_MPEG_VIDEO_H264_LEVEL_UNKNOWN; - break; - } + control.value = V4L2_MPEG_VIDEO_H264_LEVEL_UNKNOWN; } else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_VP8) { control.id = V4L2_CID_MPEG_VIDC_VIDEO_VP8_PROFILE_LEVEL; switch (eLevel) { @@ -4737,93 +4769,23 @@ bool venc_dev::venc_set_level(OMX_U32 eLevel) } } else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC) { control.id = V4L2_CID_MPEG_VIDC_VIDEO_HEVC_TIER_LEVEL; - switch (eLevel) { - case OMX_VIDEO_HEVCMainTierLevel1: - control.value = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_1; - break; - case OMX_VIDEO_HEVCHighTierLevel1: - control.value = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_1; - break; - case OMX_VIDEO_HEVCMainTierLevel2: - control.value = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_2; - break; - case OMX_VIDEO_HEVCHighTierLevel2: - control.value = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_2; - break; - case OMX_VIDEO_HEVCMainTierLevel21: - control.value = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_2_1; - break; - case OMX_VIDEO_HEVCHighTierLevel21: - control.value = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_2_1; - break; - case OMX_VIDEO_HEVCMainTierLevel3: - control.value = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_3; - break; - case OMX_VIDEO_HEVCHighTierLevel3: - control.value = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_3; - break; - case OMX_VIDEO_HEVCMainTierLevel31: - control.value = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_3_1; - break; - case OMX_VIDEO_HEVCHighTierLevel31: - control.value = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_3_1; - break; - case OMX_VIDEO_HEVCMainTierLevel4: - control.value = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_4; - break; - case OMX_VIDEO_HEVCHighTierLevel4: - control.value = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_4; - break; - case OMX_VIDEO_HEVCMainTierLevel41: - control.value = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_4_1; - break; - case OMX_VIDEO_HEVCHighTierLevel41: - control.value = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_4_1; - break; - case OMX_VIDEO_HEVCMainTierLevel5: - control.value = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_5; - break; - case OMX_VIDEO_HEVCHighTierLevel5: - control.value = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_5; - break; - case OMX_VIDEO_HEVCMainTierLevel51: - control.value = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_5_1; - break; - case OMX_VIDEO_HEVCHighTierLevel51: - control.value = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_5_1; - break; - case OMX_VIDEO_HEVCMainTierLevel52: - control.value = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_5_2; - break; - case OMX_VIDEO_HEVCHighTierLevel52: - control.value = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_5_2; - break; - case OMX_VIDEO_HEVCMainTierLevel6: - control.value = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_6; - break; - case OMX_VIDEO_HEVCHighTierLevel6: - control.value = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_6; - break; - case OMX_VIDEO_HEVCMainTierLevel61: - control.value = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_6_1; - break; - case OMX_VIDEO_HEVCHighTierLevel61: - control.value = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_6_1; - break; - case OMX_VIDEO_HEVCLevelMax: - case OMX_VIDEO_LEVEL_UNKNOWN: - default: //Set max level possible as default so that invalid levels are non-fatal - control.value = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_UNKNOWN; - break; - } + control.value = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_UNKNOWN; } else { DEBUG_PRINT_ERROR("Wrong CODEC"); return false; } + /* If OMX_VIDEO_LEVEL_*/ + if (eLevel != OMX_VIDEO_LEVEL_UNKNOWN) { + if (!profile_level_converter::convert_omx_level_to_v4l2(m_sVenc_cfg.codectype, eLevel, &control.value)) { + DEBUG_PRINT_ERROR(" Cannot find v4l2 level for OMX level : %d Codec : %lu ", + eLevel, m_sVenc_cfg.codectype); + return false; + } + } + DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value); rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control); - if (rc) { DEBUG_PRINT_ERROR("Failed to set control, id %#x, value %d", control.id, control.value); return false; |