summaryrefslogtreecommitdiff
path: root/mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp')
-rw-r--r--[-rwxr-xr-x]mm-video-v4l2/vidc/venc/src/video_encoder_device_v4l2.cpp1179
1 files changed, 1026 insertions, 153 deletions
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 976498f..89ca5eb 100755..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
@@ -1,5 +1,5 @@
/*--------------------------------------------------------------------------
-Copyright (c) 2010-2014, The Linux Foundation. All rights reserved.
+Copyright (c) 2010-2015, 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:
@@ -44,17 +44,24 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifdef _ANDROID_
#include <media/hardware/HardwareAPI.h>
#include <gralloc_priv.h>
+#include <qdMetaData.h>
#endif
#define ALIGN(x, to_align) ((((unsigned long) x) + (to_align - 1)) & ~(to_align - 1))
#define EXTRADATA_IDX(__num_planes) (__num_planes - 1)
-
+#define MAXDPB 16
+#define MIN(x,y) (((x) < (y)) ? (x) : (y))
+#define MAX(x,y) (((x) > (y)) ? (x) : (y))
+#define ROUND(__sz, __align) (((__sz) + ((__align>>1))) & (~(__align-1)))
+#define MAX_PROFILE_PARAMS 6
#define MPEG4_SP_START 0
#define MPEG4_ASP_START (MPEG4_SP_START + 10)
#define H263_BP_START 0
#define H264_BP_START 0
#define H264_HP_START (H264_BP_START + 17)
#define H264_MP_START (H264_BP_START + 34)
+#define HEVC_MAIN_START 0
+#define HEVC_MAIN10_START (HEVC_MAIN_START + 12)
#define POLL_TIMEOUT 1000
#define MAX_SUPPORTED_SLICES_PER_FRAME 28 /* Max supported slices with 32 output buffers */
@@ -62,106 +69,138 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define SZ_1M 0x100000
/* MPEG4 profile and level table*/
-static const unsigned int mpeg4_profile_level_table[][5]= {
- /*max mb per frame, max mb per sec, max bitrate, level, profile*/
- {99,1485,64000,OMX_VIDEO_MPEG4Level0,OMX_VIDEO_MPEG4ProfileSimple},
- {99,1485,64000,OMX_VIDEO_MPEG4Level1,OMX_VIDEO_MPEG4ProfileSimple},
- {396,5940,128000,OMX_VIDEO_MPEG4Level2,OMX_VIDEO_MPEG4ProfileSimple},
- {396,11880,384000,OMX_VIDEO_MPEG4Level3,OMX_VIDEO_MPEG4ProfileSimple},
- {1200,36000,4000000,OMX_VIDEO_MPEG4Level4a,OMX_VIDEO_MPEG4ProfileSimple},
- {1620,40500,8000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileSimple},
- {3600,108000,12000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileSimple},
- {32400,972000,20000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileSimple},
- {34560,1036800,20000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileSimple},
- {0,0,0,0,0},
-
- {99,1485,128000,OMX_VIDEO_MPEG4Level0,OMX_VIDEO_MPEG4ProfileAdvancedSimple},
- {99,1485,128000,OMX_VIDEO_MPEG4Level1,OMX_VIDEO_MPEG4ProfileAdvancedSimple},
- {396,5940,384000,OMX_VIDEO_MPEG4Level2,OMX_VIDEO_MPEG4ProfileAdvancedSimple},
- {396,11880,768000,OMX_VIDEO_MPEG4Level3,OMX_VIDEO_MPEG4ProfileAdvancedSimple},
- {792,23760,3000000,OMX_VIDEO_MPEG4Level4,OMX_VIDEO_MPEG4ProfileAdvancedSimple},
- {1620,48600,8000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileAdvancedSimple},
- {32400,972000,20000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileAdvancedSimple},
- {34560,1036800,20000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileAdvancedSimple},
- {0,0,0,0,0},
+static const unsigned int mpeg4_profile_level_table[][MAX_PROFILE_PARAMS]= {
+ /*max mb per frame, max mb per sec, max bitrate, level, profile, dpbmbs*/
+ {99,1485,64000,OMX_VIDEO_MPEG4Level0,OMX_VIDEO_MPEG4ProfileSimple,0},
+ {99,1485,64000,OMX_VIDEO_MPEG4Level1,OMX_VIDEO_MPEG4ProfileSimple,0},
+ {396,5940,128000,OMX_VIDEO_MPEG4Level2,OMX_VIDEO_MPEG4ProfileSimple,0},
+ {396,11880,384000,OMX_VIDEO_MPEG4Level3,OMX_VIDEO_MPEG4ProfileSimple,0},
+ {1200,36000,4000000,OMX_VIDEO_MPEG4Level4a,OMX_VIDEO_MPEG4ProfileSimple,0},
+ {1620,40500,8000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileSimple,0},
+ {3600,108000,12000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileSimple,0},
+ {32400,972000,20000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileSimple,0},
+ {34560,1036800,20000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileSimple,0},
+ {0,0,0,0,0,0},
+
+ {99,1485,128000,OMX_VIDEO_MPEG4Level0,OMX_VIDEO_MPEG4ProfileAdvancedSimple,0},
+ {99,1485,128000,OMX_VIDEO_MPEG4Level1,OMX_VIDEO_MPEG4ProfileAdvancedSimple,0},
+ {396,5940,384000,OMX_VIDEO_MPEG4Level2,OMX_VIDEO_MPEG4ProfileAdvancedSimple,0},
+ {396,11880,768000,OMX_VIDEO_MPEG4Level3,OMX_VIDEO_MPEG4ProfileAdvancedSimple,0},
+ {792,23760,3000000,OMX_VIDEO_MPEG4Level4,OMX_VIDEO_MPEG4ProfileAdvancedSimple,0},
+ {1620,48600,8000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileAdvancedSimple,0},
+ {32400,972000,20000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileAdvancedSimple,0},
+ {34560,1036800,20000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileAdvancedSimple,0},
+ {0,0,0,0,0,0},
};
/* H264 profile and level table*/
-static const unsigned int h264_profile_level_table[][5]= {
- /*max mb per frame, max mb per sec, max bitrate, level, profile*/
- {99,1485,64000,OMX_VIDEO_AVCLevel1,OMX_VIDEO_AVCProfileBaseline},
- {99,1485,128000,OMX_VIDEO_AVCLevel1b,OMX_VIDEO_AVCProfileBaseline},
- {396,3000,192000,OMX_VIDEO_AVCLevel11,OMX_VIDEO_AVCProfileBaseline},
- {396,6000,384000,OMX_VIDEO_AVCLevel12,OMX_VIDEO_AVCProfileBaseline},
- {396,11880,768000,OMX_VIDEO_AVCLevel13,OMX_VIDEO_AVCProfileBaseline},
- {396,11880,2000000,OMX_VIDEO_AVCLevel2,OMX_VIDEO_AVCProfileBaseline},
- {792,19800,4000000,OMX_VIDEO_AVCLevel21,OMX_VIDEO_AVCProfileBaseline},
- {1620,20250,4000000,OMX_VIDEO_AVCLevel22,OMX_VIDEO_AVCProfileBaseline},
- {1620,40500,10000000,OMX_VIDEO_AVCLevel3,OMX_VIDEO_AVCProfileBaseline},
- {3600,108000,14000000,OMX_VIDEO_AVCLevel31,OMX_VIDEO_AVCProfileBaseline},
- {5120,216000,20000000,OMX_VIDEO_AVCLevel32,OMX_VIDEO_AVCProfileBaseline},
- {8192,245760,20000000,OMX_VIDEO_AVCLevel4,OMX_VIDEO_AVCProfileBaseline},
- {8192,245760,50000000,OMX_VIDEO_AVCLevel41,OMX_VIDEO_AVCProfileBaseline},
- {8704,522240,50000000,OMX_VIDEO_AVCLevel42,OMX_VIDEO_AVCProfileBaseline},
- {22080,589824,135000000,OMX_VIDEO_AVCLevel5,OMX_VIDEO_AVCProfileBaseline},
- {36864,983040,240000000,OMX_VIDEO_AVCLevel51,OMX_VIDEO_AVCProfileBaseline},
- {36864,2073600,240000000,OMX_VIDEO_AVCLevel52,OMX_VIDEO_AVCProfileBaseline},
- {0,0,0,0,0},
-
- {99,1485,64000,OMX_VIDEO_AVCLevel1,OMX_VIDEO_AVCProfileHigh},
- {99,1485,160000,OMX_VIDEO_AVCLevel1b,OMX_VIDEO_AVCProfileHigh},
- {396,3000,240000,OMX_VIDEO_AVCLevel11,OMX_VIDEO_AVCProfileHigh},
- {396,6000,480000,OMX_VIDEO_AVCLevel12,OMX_VIDEO_AVCProfileHigh},
- {396,11880,960000,OMX_VIDEO_AVCLevel13,OMX_VIDEO_AVCProfileHigh},
- {396,11880,2500000,OMX_VIDEO_AVCLevel2,OMX_VIDEO_AVCProfileHigh},
- {792,19800,5000000,OMX_VIDEO_AVCLevel21,OMX_VIDEO_AVCProfileHigh},
- {1620,20250,5000000,OMX_VIDEO_AVCLevel22,OMX_VIDEO_AVCProfileHigh},
- {1620,40500,12500000,OMX_VIDEO_AVCLevel3,OMX_VIDEO_AVCProfileHigh},
- {3600,108000,17500000,OMX_VIDEO_AVCLevel31,OMX_VIDEO_AVCProfileHigh},
- {5120,216000,25000000,OMX_VIDEO_AVCLevel32,OMX_VIDEO_AVCProfileHigh},
- {8192,245760,25000000,OMX_VIDEO_AVCLevel4,OMX_VIDEO_AVCProfileHigh},
- {8192,245760,50000000,OMX_VIDEO_AVCLevel41,OMX_VIDEO_AVCProfileHigh},
- {8704,522240,50000000,OMX_VIDEO_AVCLevel42,OMX_VIDEO_AVCProfileHigh},
- {22080,589824,135000000,OMX_VIDEO_AVCLevel5,OMX_VIDEO_AVCProfileHigh},
- {36864,983040,240000000,OMX_VIDEO_AVCLevel51,OMX_VIDEO_AVCProfileHigh},
- {36864,2073600,240000000,OMX_VIDEO_AVCLevel52,OMX_VIDEO_AVCProfileHigh},
- {0,0,0,0,0},
-
- {99,1485,64000,OMX_VIDEO_AVCLevel1,OMX_VIDEO_AVCProfileMain},
- {99,1485,128000,OMX_VIDEO_AVCLevel1b,OMX_VIDEO_AVCProfileMain},
- {396,3000,192000,OMX_VIDEO_AVCLevel11,OMX_VIDEO_AVCProfileMain},
- {396,6000,384000,OMX_VIDEO_AVCLevel12,OMX_VIDEO_AVCProfileMain},
- {396,11880,768000,OMX_VIDEO_AVCLevel13,OMX_VIDEO_AVCProfileMain},
- {396,11880,2000000,OMX_VIDEO_AVCLevel2,OMX_VIDEO_AVCProfileMain},
- {792,19800,4000000,OMX_VIDEO_AVCLevel21,OMX_VIDEO_AVCProfileMain},
- {1620,20250,4000000,OMX_VIDEO_AVCLevel22,OMX_VIDEO_AVCProfileMain},
- {1620,40500,10000000,OMX_VIDEO_AVCLevel3,OMX_VIDEO_AVCProfileMain},
- {3600,108000,14000000,OMX_VIDEO_AVCLevel31,OMX_VIDEO_AVCProfileMain},
- {5120,216000,20000000,OMX_VIDEO_AVCLevel32,OMX_VIDEO_AVCProfileMain},
- {8192,245760,20000000,OMX_VIDEO_AVCLevel4,OMX_VIDEO_AVCProfileMain},
- {8192,245760,50000000,OMX_VIDEO_AVCLevel41,OMX_VIDEO_AVCProfileMain},
- {8704,522240,50000000,OMX_VIDEO_AVCLevel42,OMX_VIDEO_AVCProfileMain},
- {22080,589824,135000000,OMX_VIDEO_AVCLevel5,OMX_VIDEO_AVCProfileMain},
- {36864,983040,240000000,OMX_VIDEO_AVCLevel51,OMX_VIDEO_AVCProfileMain},
- {36864,2073600,240000000,OMX_VIDEO_AVCLevel52,OMX_VIDEO_AVCProfileBaseline},
- {0,0,0,0,0}
+static const unsigned int h264_profile_level_table[][MAX_PROFILE_PARAMS]= {
+ /*max mb per frame, max mb per sec, max bitrate, level, profile, dpbmbs*/
+ {99,1485,64000,OMX_VIDEO_AVCLevel1,OMX_VIDEO_AVCProfileBaseline,396},
+ {99,1485,128000,OMX_VIDEO_AVCLevel1b,OMX_VIDEO_AVCProfileBaseline,396},
+ {396,3000,192000,OMX_VIDEO_AVCLevel11,OMX_VIDEO_AVCProfileBaseline,900},
+ {396,6000,384000,OMX_VIDEO_AVCLevel12,OMX_VIDEO_AVCProfileBaseline,2376},
+ {396,11880,768000,OMX_VIDEO_AVCLevel13,OMX_VIDEO_AVCProfileBaseline,2376},
+ {396,11880,2000000,OMX_VIDEO_AVCLevel2,OMX_VIDEO_AVCProfileBaseline,2376},
+ {792,19800,4000000,OMX_VIDEO_AVCLevel21,OMX_VIDEO_AVCProfileBaseline,4752},
+ {1620,20250,4000000,OMX_VIDEO_AVCLevel22,OMX_VIDEO_AVCProfileBaseline,8100},
+ {1620,40500,10000000,OMX_VIDEO_AVCLevel3,OMX_VIDEO_AVCProfileBaseline,8100},
+ {3600,108000,14000000,OMX_VIDEO_AVCLevel31,OMX_VIDEO_AVCProfileBaseline,18000},
+ {5120,216000,20000000,OMX_VIDEO_AVCLevel32,OMX_VIDEO_AVCProfileBaseline,20480},
+ {8192,245760,20000000,OMX_VIDEO_AVCLevel4,OMX_VIDEO_AVCProfileBaseline,32768},
+ {8192,245760,50000000,OMX_VIDEO_AVCLevel41,OMX_VIDEO_AVCProfileBaseline,32768},
+ {8704,522240,50000000,OMX_VIDEO_AVCLevel42,OMX_VIDEO_AVCProfileBaseline,34816},
+ {22080,589824,135000000,OMX_VIDEO_AVCLevel5,OMX_VIDEO_AVCProfileBaseline,110400},
+ {36864,983040,240000000,OMX_VIDEO_AVCLevel51,OMX_VIDEO_AVCProfileBaseline,184320},
+ {36864,2073600,240000000,OMX_VIDEO_AVCLevel52,OMX_VIDEO_AVCProfileBaseline,184320},
+ {0,0,0,0,0,0},
+
+ {99,1485,64000,OMX_VIDEO_AVCLevel1,OMX_VIDEO_AVCProfileHigh,396},
+ {99,1485,160000,OMX_VIDEO_AVCLevel1b,OMX_VIDEO_AVCProfileHigh,396},
+ {396,3000,240000,OMX_VIDEO_AVCLevel11,OMX_VIDEO_AVCProfileHigh,900},
+ {396,6000,480000,OMX_VIDEO_AVCLevel12,OMX_VIDEO_AVCProfileHigh,2376},
+ {396,11880,960000,OMX_VIDEO_AVCLevel13,OMX_VIDEO_AVCProfileHigh,2376},
+ {396,11880,2500000,OMX_VIDEO_AVCLevel2,OMX_VIDEO_AVCProfileHigh,2376},
+ {792,19800,5000000,OMX_VIDEO_AVCLevel21,OMX_VIDEO_AVCProfileHigh,4752},
+ {1620,20250,5000000,OMX_VIDEO_AVCLevel22,OMX_VIDEO_AVCProfileHigh,8100},
+ {1620,40500,12500000,OMX_VIDEO_AVCLevel3,OMX_VIDEO_AVCProfileHigh,8100},
+ {3600,108000,17500000,OMX_VIDEO_AVCLevel31,OMX_VIDEO_AVCProfileHigh,18000},
+ {5120,216000,25000000,OMX_VIDEO_AVCLevel32,OMX_VIDEO_AVCProfileHigh,20480},
+ {8192,245760,25000000,OMX_VIDEO_AVCLevel4,OMX_VIDEO_AVCProfileHigh,32768},
+ {8192,245760,50000000,OMX_VIDEO_AVCLevel41,OMX_VIDEO_AVCProfileHigh,32768},
+ {8704,522240,50000000,OMX_VIDEO_AVCLevel42,OMX_VIDEO_AVCProfileHigh,34816},
+ {22080,589824,135000000,OMX_VIDEO_AVCLevel5,OMX_VIDEO_AVCProfileHigh,110400},
+ {36864,983040,240000000,OMX_VIDEO_AVCLevel51,OMX_VIDEO_AVCProfileHigh,184320},
+ {36864,2073600,240000000,OMX_VIDEO_AVCLevel52,OMX_VIDEO_AVCProfileHigh,184320},
+ {0,0,0,0,0,0},
+
+ {99,1485,64000,OMX_VIDEO_AVCLevel1,OMX_VIDEO_AVCProfileMain,396},
+ {99,1485,128000,OMX_VIDEO_AVCLevel1b,OMX_VIDEO_AVCProfileMain,396},
+ {396,3000,192000,OMX_VIDEO_AVCLevel11,OMX_VIDEO_AVCProfileMain,900},
+ {396,6000,384000,OMX_VIDEO_AVCLevel12,OMX_VIDEO_AVCProfileMain,2376},
+ {396,11880,768000,OMX_VIDEO_AVCLevel13,OMX_VIDEO_AVCProfileMain,2376},
+ {396,11880,2000000,OMX_VIDEO_AVCLevel2,OMX_VIDEO_AVCProfileMain,2376},
+ {792,19800,4000000,OMX_VIDEO_AVCLevel21,OMX_VIDEO_AVCProfileMain,4752},
+ {1620,20250,4000000,OMX_VIDEO_AVCLevel22,OMX_VIDEO_AVCProfileMain,8100},
+ {1620,40500,10000000,OMX_VIDEO_AVCLevel3,OMX_VIDEO_AVCProfileMain,8100},
+ {3600,108000,14000000,OMX_VIDEO_AVCLevel31,OMX_VIDEO_AVCProfileMain,18000},
+ {5120,216000,20000000,OMX_VIDEO_AVCLevel32,OMX_VIDEO_AVCProfileMain,20480},
+ {8192,245760,20000000,OMX_VIDEO_AVCLevel4,OMX_VIDEO_AVCProfileMain,32768},
+ {8192,245760,50000000,OMX_VIDEO_AVCLevel41,OMX_VIDEO_AVCProfileMain,32768},
+ {8704,522240,50000000,OMX_VIDEO_AVCLevel42,OMX_VIDEO_AVCProfileMain,34816},
+ {22080,589824,135000000,OMX_VIDEO_AVCLevel5,OMX_VIDEO_AVCProfileMain,110400},
+ {36864,983040,240000000,OMX_VIDEO_AVCLevel51,OMX_VIDEO_AVCProfileMain,184320},
+ {36864,2073600,240000000,OMX_VIDEO_AVCLevel52,OMX_VIDEO_AVCProfileMain,184320},
+ {0,0,0,0,0,0}
};
/* H263 profile and level table*/
-static const unsigned int h263_profile_level_table[][5]= {
+static const unsigned int h263_profile_level_table[][MAX_PROFILE_PARAMS]= {
+ /*max mb per frame, max mb per sec, max bitrate, level, profile, dpbmbs*/
+ {99,1485,64000,OMX_VIDEO_H263Level10,OMX_VIDEO_H263ProfileBaseline,0},
+ {396,5940,128000,OMX_VIDEO_H263Level20,OMX_VIDEO_H263ProfileBaseline,0},
+ {396,11880,384000,OMX_VIDEO_H263Level30,OMX_VIDEO_H263ProfileBaseline,0},
+ {396,11880,2048000,OMX_VIDEO_H263Level40,OMX_VIDEO_H263ProfileBaseline,0},
+ {99,1485,128000,OMX_VIDEO_H263Level45,OMX_VIDEO_H263ProfileBaseline,0},
+ {396,19800,4096000,OMX_VIDEO_H263Level50,OMX_VIDEO_H263ProfileBaseline,0},
+ {810,40500,8192000,OMX_VIDEO_H263Level60,OMX_VIDEO_H263ProfileBaseline,0},
+ {1620,81000,16384000,OMX_VIDEO_H263Level70,OMX_VIDEO_H263ProfileBaseline,0},
+ {32400,972000,20000000,OMX_VIDEO_H263Level70,OMX_VIDEO_H263ProfileBaseline,0},
+ {34560,1036800,20000000,OMX_VIDEO_H263Level70,OMX_VIDEO_H263ProfileBaseline,0},
+ {0,0,0,0,0,0}
+};
+
+/* HEVC profile and level table*/
+static const unsigned int hevc_profile_level_table[][MAX_PROFILE_PARAMS]= {
/*max mb per frame, max mb per sec, max bitrate, level, profile*/
- {99,1485,64000,OMX_VIDEO_H263Level10,OMX_VIDEO_H263ProfileBaseline},
- {396,5940,128000,OMX_VIDEO_H263Level20,OMX_VIDEO_H263ProfileBaseline},
- {396,11880,384000,OMX_VIDEO_H263Level30,OMX_VIDEO_H263ProfileBaseline},
- {396,11880,2048000,OMX_VIDEO_H263Level40,OMX_VIDEO_H263ProfileBaseline},
- {99,1485,128000,OMX_VIDEO_H263Level45,OMX_VIDEO_H263ProfileBaseline},
- {396,19800,4096000,OMX_VIDEO_H263Level50,OMX_VIDEO_H263ProfileBaseline},
- {810,40500,8192000,OMX_VIDEO_H263Level60,OMX_VIDEO_H263ProfileBaseline},
- {1620,81000,16384000,OMX_VIDEO_H263Level70,OMX_VIDEO_H263ProfileBaseline},
- {32400,972000,20000000,OMX_VIDEO_H263Level70,OMX_VIDEO_H263ProfileBaseline},
- {34560,1036800,20000000,OMX_VIDEO_H263Level70,OMX_VIDEO_H263ProfileBaseline},
- {0,0,0,0,0}
+ {99,1485,128000,OMX_VIDEO_HEVCMainTierLevel1,OMX_VIDEO_HEVCProfileMain,0},
+ {396,11880,1500000,OMX_VIDEO_HEVCMainTierLevel2,OMX_VIDEO_HEVCProfileMain,0},
+ {900,27000,3000000,OMX_VIDEO_HEVCMainTierLevel21,OMX_VIDEO_HEVCProfileMain,0},
+ {2025,60750,6000000,OMX_VIDEO_HEVCMainTierLevel3,OMX_VIDEO_HEVCProfileMain,0},
+ {8640,259200,10000000,OMX_VIDEO_HEVCMainTierLevel31,OMX_VIDEO_HEVCProfileMain,0},
+ {34560,1166400,12000000,OMX_VIDEO_HEVCMainTierLevel4,OMX_VIDEO_HEVCProfileMain,0},
+ {138240,4147200,20000000,OMX_VIDEO_HEVCMainTierLevel41,OMX_VIDEO_HEVCProfileMain,0},
+ {138240,8294400,25000000,OMX_VIDEO_HEVCMainTierLevel5,OMX_VIDEO_HEVCProfileMain,0},
+ {138240,4147200,40000000,OMX_VIDEO_HEVCMainTierLevel51,OMX_VIDEO_HEVCProfileMain,0},
+ {138240,4147200,50000000,OMX_VIDEO_HEVCHighTierLevel41,OMX_VIDEO_HEVCProfileMain,0},
+ {138240,4147200,100000000,OMX_VIDEO_HEVCHighTierLevel5,OMX_VIDEO_HEVCProfileMain,0},
+ {138240,4147200,1600000000,OMX_VIDEO_HEVCHighTierLevel51,OMX_VIDEO_HEVCProfileMain,0},
+ {0,0,0,0,0},
+
+ {99,1485,128000,OMX_VIDEO_HEVCMainTierLevel1,OMX_VIDEO_HEVCProfileMain10,0},
+ {396,11880,1500000,OMX_VIDEO_HEVCMainTierLevel2,OMX_VIDEO_HEVCProfileMain10,0},
+ {900,27000,3000000,OMX_VIDEO_HEVCMainTierLevel21,OMX_VIDEO_HEVCProfileMain10,0},
+ {2025,60750,6000000,OMX_VIDEO_HEVCMainTierLevel3,OMX_VIDEO_HEVCProfileMain10,0},
+ {8640,259200,10000000,OMX_VIDEO_HEVCMainTierLevel31,OMX_VIDEO_HEVCProfileMain10,0},
+ {34560,1166400,12000000,OMX_VIDEO_HEVCMainTierLevel4,OMX_VIDEO_HEVCProfileMain10,0},
+ {138240,4147200,20000000,OMX_VIDEO_HEVCMainTierLevel41,OMX_VIDEO_HEVCProfileMain10,0},
+ {138240,8294400,25000000,OMX_VIDEO_HEVCMainTierLevel5,OMX_VIDEO_HEVCProfileMain10,0},
+ {138240,4147200,40000000,OMX_VIDEO_HEVCMainTierLevel51,OMX_VIDEO_HEVCProfileMain10,0},
+ {138240,4147200,50000000,OMX_VIDEO_HEVCHighTierLevel41,OMX_VIDEO_HEVCProfileMain10,0},
+ {138240,4147200,100000000,OMX_VIDEO_HEVCHighTierLevel5,OMX_VIDEO_HEVCProfileMain10,0},
+ {138240,4147200,1600000000,OMX_VIDEO_HEVCHighTierLevel51,OMX_VIDEO_HEVCProfileMain10,0},
+ {0,0,0,0,0},
};
#define Log2(number, power) { OMX_U32 temp = number; power = 0; while( (0 == (temp & 0x1)) && power < 16) { temp >>=0x1; power++; } }
@@ -184,6 +223,7 @@ venc_dev::venc_dev(class omx_venc *venc_class)
paused = false;
async_thread_created = false;
color_format = 0;
+ hw_overload = false;
pthread_mutex_init(&pause_resume_mlock, NULL);
pthread_cond_init(&pause_resume_cond, NULL);
memset(&extradata_info, 0, sizeof(extradata_info));
@@ -207,10 +247,14 @@ venc_dev::venc_dev(class omx_venc *venc_class)
memset(&voptimecfg, 0, sizeof(voptimecfg));
memset(&capability, 0, sizeof(capability));
memset(&m_debug,0,sizeof(m_debug));
- memset(&hier_p_layers,0,sizeof(hier_p_layers));
- memset(&display_info,0,sizeof(display_info));
+ memset(&hier_layers,0,sizeof(hier_layers));
is_searchrange_set = false;
enable_mv_narrow_searchrange = false;
+ supported_rc_modes = RC_ALL;
+ camera_mode_enabled = false;
+ memset(&ltrinfo, 0, sizeof(ltrinfo));
+ sess_priority.priority = 1;
+ operating_rate = 0;
char property_value[PROPERTY_VALUE_MAX] = {0};
property_get("vidc.enc.log.in", property_value, "0");
@@ -347,7 +391,11 @@ void* venc_dev::async_venc_message_thread (void *input)
while (!ioctl(pfd.fd, VIDIOC_DQBUF, &v4l2_buf)) {
venc_msg.msgcode=VEN_MSG_INPUT_BUFFER_DONE;
venc_msg.statuscode=VEN_S_SUCCESS;
- omxhdr=omx_venc_base->m_inp_mem_ptr+v4l2_buf.index;
+ if (omx_venc_base->mUseProxyColorFormat && !omx_venc_base->mUsesColorConversion)
+ omxhdr = &omx_venc_base->meta_buffer_hdr[v4l2_buf.index];
+ else
+ omxhdr = &omx_venc_base->m_inp_mem_ptr[v4l2_buf.index];
+
venc_msg.buf.clientdata=(void*)omxhdr;
omx->handle->ebd++;
@@ -380,6 +428,15 @@ void* venc_dev::async_venc_message_thread (void *input)
DEBUG_PRINT_ERROR("ERROR: Wrong ioctl message");
break;
}
+ } else if (dqevent.type == V4L2_EVENT_MSM_VIDC_HW_OVERLOAD) {
+ DEBUG_PRINT_ERROR("HW Overload received");
+ venc_msg.statuscode = VEN_S_EFAIL;
+ venc_msg.msgcode = VEN_MSG_HW_OVERLOAD;
+
+ if (omx->async_message_process(input,&venc_msg) < 0) {
+ DEBUG_PRINT_ERROR("ERROR: Wrong ioctl message");
+ break;
+ }
} else if (dqevent.type == V4L2_EVENT_MSM_VIDC_SYS_ERROR) {
DEBUG_PRINT_ERROR("ERROR: Encoder is in bad state");
venc_msg.msgcode = VEN_MSG_INDICATION;
@@ -500,6 +557,16 @@ bool venc_dev::handle_extradata(void *buffer, int index)
p_extra->nDataSize = payloadSize;
break;
}
+ case MSM_VIDC_EXTRADATA_METADATA_LTR:
+ {
+ *p_extra->data = *p_extradata->data;
+ p_extra->nSize = ALIGN(sizeof(OMX_OTHER_EXTRADATATYPE) + p_extradata->data_size, 4);
+ p_extra->nVersion.nVersion = OMX_SPEC_VERSION;
+ p_extra->nPortIndex = OMX_DirOutput;
+ p_extra->eType = (OMX_EXTRADATATYPE) OMX_ExtraDataVideoLTRInfo;
+ p_extra->nDataSize = p_extradata->data_size;
+ break;
+ }
case MSM_VIDC_EXTRADATA_NONE:
p_extra->nSize = ALIGN(sizeof(OMX_OTHER_EXTRADATATYPE), 4);
p_extra->nVersion.nVersion = OMX_SPEC_VERSION;
@@ -614,6 +681,11 @@ bool venc_dev::venc_get_output_log_flag()
int venc_dev::venc_output_log_buffers(const char *buffer_addr, int buffer_len)
{
+ if (venc_handle->is_secure_session()) {
+ DEBUG_PRINT_ERROR("logging secure output buffers is not allowed!");
+ return -1;
+ }
+
if (!m_debug.outfile) {
int size = 0;
if(m_sVenc_cfg.codectype == V4L2_PIX_FMT_MPEG4) {
@@ -622,6 +694,9 @@ int venc_dev::venc_output_log_buffers(const char *buffer_addr, int buffer_len)
} else if(m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264) {
size = snprintf(m_debug.outfile_name, PROPERTY_VALUE_MAX, "%s/output_enc_%lu_%lu_%p.264",
m_debug.log_loc, m_sVenc_cfg.input_width, m_sVenc_cfg.input_height, this);
+ } else if(m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC) {
+ size = snprintf(m_debug.outfile_name, PROPERTY_VALUE_MAX, "%s/output_enc_%ld_%ld_%p.265",
+ m_debug.log_loc, m_sVenc_cfg.input_width, m_sVenc_cfg.input_height, this);
} else if(m_sVenc_cfg.codectype == V4L2_PIX_FMT_H263) {
size = snprintf(m_debug.outfile_name, PROPERTY_VALUE_MAX, "%s/output_enc_%lu_%lu_%p.263",
m_debug.log_loc, m_sVenc_cfg.input_width, m_sVenc_cfg.input_height, this);
@@ -658,6 +733,9 @@ int venc_dev::venc_extradata_log_buffers(char *buffer_addr)
} else if(m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264) {
size = snprintf(m_debug.extradatafile_name, PROPERTY_VALUE_MAX, "%s/extradata_enc_%lu_%lu_%p.264",
m_debug.log_loc, m_sVenc_cfg.input_width, m_sVenc_cfg.input_height, this);
+ } else if(m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC) {
+ size = snprintf(m_debug.extradatafile_name, PROPERTY_VALUE_MAX, "%s/extradata_enc_%lu_%lu_%p.265",
+ m_debug.log_loc, m_sVenc_cfg.input_width, m_sVenc_cfg.input_height, this);
} else if(m_sVenc_cfg.codectype == V4L2_PIX_FMT_H263) {
size = snprintf(m_debug.extradatafile_name, PROPERTY_VALUE_MAX, "%s/extradata_enc_%lu_%lu_%p.263",
m_debug.log_loc, m_sVenc_cfg.input_width, m_sVenc_cfg.input_height, this);
@@ -691,6 +769,11 @@ int venc_dev::venc_extradata_log_buffers(char *buffer_addr)
}
int venc_dev::venc_input_log_buffers(OMX_BUFFERHEADERTYPE *pbuffer, int fd, int plane_offset) {
+ if (venc_handle->is_secure_session()) {
+ DEBUG_PRINT_ERROR("logging secure input buffers is not allowed!");
+ return -1;
+ }
+
if (!m_debug.infile) {
int size = snprintf(m_debug.infile_name, PROPERTY_VALUE_MAX, "%s/input_enc_%lu_%lu_%p.yuv",
m_debug.log_loc, m_sVenc_cfg.input_width, m_sVenc_cfg.input_height, this);
@@ -754,21 +837,17 @@ bool venc_dev::venc_open(OMX_U32 codec)
int r;
unsigned int alignment = 0,buffer_size = 0, temp =0;
struct v4l2_control control;
- OMX_STRING device_name = (OMX_STRING)"/dev/video/venus_enc";
+ OMX_STRING device_name = (OMX_STRING)"/dev/video33";
+ char property_value[PROPERTY_VALUE_MAX] = {0};
+ char platform_name[PROPERTY_VALUE_MAX] = {0};
- char platform_name[PROPERTY_VALUE_MAX];
property_get("ro.board.platform", platform_name, "0");
+ property_get("vidc.enc.narrow.searchrange", property_value, "0");
+ enable_mv_narrow_searchrange = atoi(property_value);
if (!strncmp(platform_name, "msm8610", 7)) {
device_name = (OMX_STRING)"/dev/video/q6_enc";
- }
- if (!strncmp(platform_name, "msm8916", 7)) {
- enable_mv_narrow_searchrange = true;
- sp<IBinder> display(SurfaceComposerClient::getBuiltInDisplay(
- ISurfaceComposer::eDisplayIdMain));
- SurfaceComposerClient::getDisplayInfo(display, &display_info);
- DEBUG_PRINT_LOW("Display panel resolution %dX%d",
- display_info.w, display_info.h);
+ supported_rc_modes = (RC_ALL & ~RC_CBR_CFR);
}
m_nDriver_fd = open (device_name, O_RDWR);
@@ -818,6 +897,12 @@ bool venc_dev::venc_open(OMX_U32 codec)
profile_level.level = V4L2_MPEG_VIDC_VIDEO_VP8_VERSION_0;
session_qp_range.minqp = 1;
session_qp_range.maxqp = 128;
+ } else if (codec == OMX_VIDEO_CodingHEVC) {
+ m_sVenc_cfg.codectype = V4L2_PIX_FMT_HEVC;
+ session_qp_range.minqp = 1;
+ session_qp_range.maxqp = 51;
+ codec_profile.profile = V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN;
+ profile_level.level = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_1;
}
session_qp_values.minqp = session_qp_range.minqp;
session_qp_values.maxqp = session_qp_range.maxqp;
@@ -923,6 +1008,7 @@ bool venc_dev::venc_open(OMX_U32 codec)
resume_in_stopped = 0;
metadatamode = 0;
+ camera_mode_enabled = false;
control.id = V4L2_CID_MPEG_VIDEO_HEADER_MODE;
control.value = V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE;
@@ -959,6 +1045,21 @@ bool venc_dev::venc_open(OMX_U32 codec)
DEBUG_PRINT_ERROR("Failed to set V4L2_CID_MPEG_VIDC_VIDEO_NUM_P_FRAME\n");
}
+ property_get("vidc.debug.turbo", property_value, "0");
+ if (atoi(property_value)) {
+ DEBUG_PRINT_HIGH("Turbo mode debug property enabled");
+ control.id = V4L2_CID_MPEG_VIDC_SET_PERF_LEVEL;
+ control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO;
+ if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) {
+ DEBUG_PRINT_ERROR("Failed to set turbo mode");
+ }
+ }
+
+ sess_priority.priority = 1; /* default to non-real-time */
+ if (venc_set_session_priority(sess_priority.priority)) {
+ DEBUG_PRINT_ERROR("Setting session priority failed");
+ return OMX_ErrorUnsupportedSetting;
+ }
return true;
}
@@ -1071,7 +1172,7 @@ bool venc_dev::venc_loaded_stop_done()
}
bool venc_dev::venc_get_seq_hdr(void *buffer,
- unsigned buffer_size, OMX_U32 *header_len)
+ unsigned buffer_size, unsigned *header_len)
{
(void) buffer, (void) buffer_size, (void) header_len;
return true;
@@ -1101,6 +1202,14 @@ bool venc_dev::venc_get_buf_req(OMX_U32 *min_buff_count,
else
bufreq.count = 2;
+ // Increase buffer-header count for metadata-mode on input port
+ // to improve buffering and reduce bottlenecks in clients
+ if (metadatamode && (bufreq.count < 9)) {
+ DEBUG_PRINT_LOW("FW returned buffer count = %d , overwriting with 16",
+ bufreq.count);
+ bufreq.count = 9;
+ }
+
bufreq.type=V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
ret = ioctl(m_nDriver_fd,VIDIOC_REQBUFS, &bufreq);
@@ -1120,7 +1229,7 @@ bool venc_dev::venc_get_buf_req(OMX_U32 *min_buff_count,
#endif
*buff_size = m_sInput_buff_property.datasize;
} else {
- int extra_idx = 0;
+ unsigned int extra_idx = 0;
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
fmt.fmt.pix_mp.height = m_sVenc_cfg.dvs_height;
fmt.fmt.pix_mp.width = m_sVenc_cfg.dvs_width;
@@ -1194,8 +1303,7 @@ bool venc_dev::venc_set_param(void *paramData,OMX_INDEXTYPE index )
if (!venc_set_color_format(portDefn->format.video.eColorFormat)) {
return false;
}
- if ((display_info.w * display_info.h) > (OMX_CORE_720P_WIDTH * OMX_CORE_720P_HEIGHT)
- && enable_mv_narrow_searchrange &&
+ if (enable_mv_narrow_searchrange &&
(m_sVenc_cfg.input_width * m_sVenc_cfg.input_height) >=
(OMX_CORE_1080P_WIDTH * OMX_CORE_1080P_HEIGHT)) {
if (venc_set_searchrange() == false) {
@@ -1214,6 +1322,7 @@ bool venc_dev::venc_set_param(void *paramData,OMX_INDEXTYPE index )
if (ioctl(m_nDriver_fd, VIDIOC_S_FMT, &fmt)) {
DEBUG_PRINT_ERROR("VIDIOC_S_FMT OUTPUT_MPLANE Failed");
+ hw_overload = errno == EBUSY;
return false;
}
@@ -1246,6 +1355,7 @@ bool venc_dev::venc_set_param(void *paramData,OMX_INDEXTYPE index )
if (ioctl(m_nDriver_fd, VIDIOC_S_FMT, &fmt)) {
DEBUG_PRINT_ERROR("VIDIOC_S_FMT CAPTURE_MPLANE Failed");
+ hw_overload = errno == EBUSY;
return false;
}
@@ -1467,7 +1577,10 @@ bool venc_dev::venc_set_param(void *paramData,OMX_INDEXTYPE index )
pParam->eProfile, pParam->eLevel);
return false;
}
-
+ if(venc_set_vpx_error_resilience(pParam->bErrorResilientMode) == false) {
+ DEBUG_PRINT_ERROR("ERROR: Failed to set vpx error resilience");
+ return false;
+ }
if(!venc_set_ltrmode(1, 1)) {
DEBUG_PRINT_ERROR("ERROR: Failed to enable ltrmode");
return false;
@@ -1484,6 +1597,20 @@ bool venc_dev::venc_set_param(void *paramData,OMX_INDEXTYPE index )
break;
}
+ case (OMX_INDEXTYPE)OMX_IndexParamVideoHevc:
+ {
+ DEBUG_PRINT_LOW("venc_set_param:OMX_IndexParamVideoHevc");
+ OMX_VIDEO_PARAM_HEVCTYPE* pParam = (OMX_VIDEO_PARAM_HEVCTYPE*)paramData;
+ if (!venc_set_profile_level (pParam->eProfile, pParam->eLevel)) {
+ DEBUG_PRINT_ERROR("ERROR: Unsuccessful in updating Profile and level %d, %d",
+ pParam->eProfile, pParam->eLevel);
+ return false;
+ }
+ if (!venc_set_inloop_filter(OMX_VIDEO_AVCLoopFilterEnable))
+ DEBUG_PRINT_HIGH("WARN: Request for setting Inloop filter failed for HEVC encoder");
+
+ break;
+ }
case OMX_IndexParamVideoIntraRefresh:
{
DEBUG_PRINT_LOW("venc_set_param:OMX_IndexParamVideoIntraRefresh");
@@ -1737,6 +1864,35 @@ bool venc_dev::venc_set_param(void *paramData,OMX_INDEXTYPE index )
}
}
break;
+ case OMX_QcomIndexParamVideoLTRCount:
+ {
+ DEBUG_PRINT_LOW("venc_set_param: OMX_QcomIndexParamVideoLTRCount");
+ OMX_QCOM_VIDEO_PARAM_LTRCOUNT_TYPE* pParam =
+ (OMX_QCOM_VIDEO_PARAM_LTRCOUNT_TYPE*)paramData;
+ if (pParam->nCount > 0) {
+ if (venc_set_ltrmode(1, pParam->nCount) == false) {
+ DEBUG_PRINT_ERROR("ERROR: Enable LTR mode failed");
+ return false;
+ }
+ } else {
+ if (venc_set_ltrmode(0, 0) == false) {
+ DEBUG_PRINT_ERROR("ERROR: Disable LTR mode failed");
+ return false;
+ }
+ }
+ break;
+ }
+ case OMX_QcomIndexParamVideoHybridHierpMode:
+ {
+ QOMX_EXTNINDEX_VIDEO_HYBRID_HP_MODE* pParam =
+ (QOMX_EXTNINDEX_VIDEO_HYBRID_HP_MODE*)paramData;
+
+ if (!venc_set_hybrid_hierp(pParam->nHpLayers)) {
+ DEBUG_PRINT_ERROR("Setting hybrid Hier-P mode failed");
+ return OMX_ErrorUnsupportedSetting;
+ }
+ break;
+ }
case OMX_IndexParamVideoSliceFMO:
default:
DEBUG_PRINT_ERROR("ERROR: Unsupported parameter in venc_set_param: %u",
@@ -1825,6 +1981,9 @@ bool venc_dev::venc_set_config(void *configData, OMX_INDEXTYPE index)
OMX_CONFIG_ROTATIONTYPE *config_rotation =
reinterpret_cast<OMX_CONFIG_ROTATIONTYPE*>(configData);
OMX_U32 nFrameWidth;
+ if (!config_rotation) {
+ return false;
+ }
if (true == deinterlace_enabled) {
DEBUG_PRINT_ERROR("ERROR: Rotation is not supported with deinterlacing");
return false;
@@ -1880,13 +2039,13 @@ bool venc_dev::venc_set_config(void *configData, OMX_INDEXTYPE index)
DEBUG_PRINT_LOW("venc_set_config: OMX_IndexConfigVideoVp8ReferenceFrame");
if ((vp8refframe->nPortIndex == (OMX_U32)PORT_INDEX_IN) &&
(vp8refframe->bUseGoldenFrame)) {
- if(venc_set_useltr() == false) {
+ if(venc_set_useltr(0x1) == false) {
DEBUG_PRINT_ERROR("ERROR: use goldenframe failed");
return false;
}
} else if((vp8refframe->nPortIndex == (OMX_U32)PORT_INDEX_IN) &&
(vp8refframe->bGoldenFrameRefresh)) {
- if(venc_set_markltr() == false) {
+ if(venc_set_markltr(0x1) == false) {
DEBUG_PRINT_ERROR("ERROR: Setting goldenframe failed");
return false;
}
@@ -1895,6 +2054,77 @@ bool venc_dev::venc_set_config(void *configData, OMX_INDEXTYPE index)
}
break;
}
+ case OMX_QcomIndexConfigVideoLTRUse:
+ {
+ OMX_QCOM_VIDEO_CONFIG_LTRUSE_TYPE* pParam = (OMX_QCOM_VIDEO_CONFIG_LTRUSE_TYPE*)configData;
+ DEBUG_PRINT_LOW("venc_set_config: OMX_QcomIndexConfigVideoLTRUse");
+ if (pParam->nPortIndex == (OMX_U32)PORT_INDEX_IN) {
+ if (venc_set_useltr(pParam->nID) == false) {
+ DEBUG_PRINT_ERROR("ERROR: Use LTR failed");
+ return false;
+ }
+ } else {
+ DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_QcomIndexConfigVideoLTRUse");
+ }
+ break;
+ }
+ case OMX_QcomIndexConfigVideoLTRMark:
+ {
+ OMX_QCOM_VIDEO_CONFIG_LTRMARK_TYPE* pParam = (OMX_QCOM_VIDEO_CONFIG_LTRMARK_TYPE*)configData;
+ DEBUG_PRINT_LOW("venc_set_config: OMX_QcomIndexConfigVideoLTRMark");
+ if (pParam->nPortIndex == (OMX_U32)PORT_INDEX_IN) {
+ if (venc_set_markltr(pParam->nID) == false) {
+ DEBUG_PRINT_ERROR("ERROR: Mark LTR failed");
+ return false;
+ }
+ } else {
+ DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_QcomIndexConfigVideoLTRMark");
+ }
+ break;
+ }
+ case OMX_QcomIndexConfigPerfLevel:
+ {
+ OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL *perf =
+ (OMX_QCOM_VIDEO_CONFIG_PERF_LEVEL *)configData;
+ DEBUG_PRINT_LOW("Set perf level: %d", perf->ePerfLevel);
+ if (!venc_set_perf_level(perf->ePerfLevel)) {
+ DEBUG_PRINT_ERROR("ERROR: Failed to set perf level to %d", perf->ePerfLevel);
+ return false;
+ } else {
+ performance_level.perflevel = (unsigned int) perf->ePerfLevel;
+ }
+ break;
+ }
+ case OMX_QcomIndexConfigVideoVencPerfMode:
+ {
+ QOMX_EXTNINDEX_VIDEO_PERFMODE *pParam = (QOMX_EXTNINDEX_VIDEO_PERFMODE *) configData;
+ DEBUG_PRINT_LOW("venc_set_config: OMX_QcomIndexConfigVideoVencPerfMode");
+ if (venc_set_perf_mode(pParam->nPerfMode) == false) {
+ DEBUG_PRINT_ERROR("Failed to set V4L2_CID_MPEG_VIDC_VIDEO_PERF_MODE");
+ return false;
+ }
+ break;
+ }
+ case OMX_IndexConfigPriority:
+ {
+ OMX_PARAM_U32TYPE *priority = (OMX_PARAM_U32TYPE *)configData;
+ DEBUG_PRINT_LOW("Set_config: priority %u",priority->nU32);
+ if (!venc_set_session_priority(priority->nU32)) {
+ DEBUG_PRINT_ERROR("Failed to set priority");
+ return false;
+ }
+ break;
+ }
+ case OMX_IndexConfigOperatingRate:
+ {
+ OMX_PARAM_U32TYPE *rate = (OMX_PARAM_U32TYPE *)configData;
+ DEBUG_PRINT_LOW("Set_config: operating rate %d", rate->nU32);
+ if (!venc_set_operatingrate(rate->nU32)) {
+ DEBUG_PRINT_ERROR("Failed to set operating rate");
+ return false;
+ }
+ break;
+ }
default:
DEBUG_PRINT_ERROR("Unsupported config index = %u", index);
break;
@@ -2022,6 +2252,7 @@ unsigned venc_dev::venc_start(void)
DEBUG_PRINT_HIGH("%s(): Check Profile/Level set in driver before start",
__func__);
+ m_level_set = false;
if (!venc_set_profile_level(0, 0)) {
DEBUG_PRINT_ERROR("ERROR: %s(): Driver Profile/Level is NOT SET",
@@ -2069,6 +2300,23 @@ unsigned venc_dev::venc_start(void)
return 0;
}
+inline const char* hiermode_string(int val)
+{
+ switch(val)
+ {
+ case HIER_NONE:
+ return "No Hier";
+ case HIER_P:
+ return "Hier-P";
+ case HIER_B:
+ return "Hier-B";
+ case HIER_P_HYBRID:
+ return "Hybrid Hier-P";
+ default:
+ return "No hier";
+ }
+}
+
void venc_dev::venc_config_print()
{
@@ -2083,8 +2331,8 @@ void venc_dev::venc_config_print()
m_sVenc_cfg.dvs_width, m_sVenc_cfg.dvs_height,
m_sVenc_cfg.fps_num/m_sVenc_cfg.fps_den);
- DEBUG_PRINT_HIGH("ENC_CONFIG: Bitrate: %ld, RC: %ld, I-Period: %ld",
- bitrate.target_bitrate, rate_ctrl.rcmode, intra_period.num_pframes);
+ DEBUG_PRINT_HIGH("ENC_CONFIG: Bitrate: %ld, RC: %ld, P - Frames : %ld, B - Frames = %ld",
+ bitrate.target_bitrate, rate_ctrl.rcmode, intra_period.num_pframes, intra_period.num_bframes);
DEBUG_PRINT_HIGH("ENC_CONFIG: qpI: %ld, qpP: %ld, qpb: %ld",
session_qp.iframeqp, session_qp.pframeqp, session_qp.bframeqp);
@@ -2092,9 +2340,6 @@ void venc_dev::venc_config_print()
DEBUG_PRINT_HIGH("ENC_CONFIG: Init_qpI: %ld, Init_qpP: %ld, Init_qpb: %ld",
init_qp.iframeqp, init_qp.pframeqp, init_qp.bframeqp);
- DEBUG_PRINT_HIGH("ENC_CONFIG: Init_qpI: %ld, Init_qpP: %ld, Init_qpb: %ld",
- init_qp.iframeqp, init_qp.pframeqp, init_qp.bframeqp);
-
DEBUG_PRINT_HIGH("ENC_CONFIG: minQP: %lu, maxQP: %lu",
session_qp_values.minqp, session_qp_values.maxqp);
@@ -2112,13 +2357,21 @@ void venc_dev::venc_config_print()
DEBUG_PRINT_HIGH("ENC_CONFIG: IntraMB/Frame: %ld, HEC: %ld, IDR Period: %ld",
intra_refresh.mbcount, hec.header_extension, idrperiod.idrperiod);
- DEBUG_PRINT_HIGH("ENC_CONFIG: Hier-P layers: %d", hier_p_layers.numlayers);
+ DEBUG_PRINT_HIGH("ENC_CONFIG: LTR Enabled: %d, Count: %d",
+ ltrinfo.enabled, ltrinfo.count);
+
+ DEBUG_PRINT_HIGH("ENC_CONFIG: Hier layers: %d, Hier Mode: %s VPX_ErrorResilience: %d",
+ hier_layers.numlayers, hiermode_string(hier_layers.hier_mode), vpx_err_resilience.enable);
DEBUG_PRINT_HIGH("ENC_CONFIG: Performace level: %d", performance_level.perflevel);
DEBUG_PRINT_HIGH("ENC_CONFIG: VUI timing info enabled: %d", vui_timing_info.enabled);
DEBUG_PRINT_HIGH("ENC_CONFIG: Peak bitrate: %d", peak_bitrate.peakbitrate);
+
+ DEBUG_PRINT_HIGH("ENC_CONFIG: Session Priority: %u", sess_priority.priority);
+
+ DEBUG_PRINT_HIGH("ENC_CONFIG: Operating Rate: %u", operating_rate);
}
bool venc_dev::venc_reconfig_reqbufs()
@@ -2170,7 +2423,8 @@ bool venc_dev::venc_use_buf(void *buf_addr, unsigned port,unsigned index)
struct pmem *pmem_tmp;
struct v4l2_buffer buf;
struct v4l2_plane plane[VIDEO_MAX_PLANES];
- int rc = 0, extra_idx;
+ int rc = 0;
+ unsigned int extra_idx;
pmem_tmp = (struct pmem *)buf_addr;
DEBUG_PRINT_LOW("venc_use_buf:: pmem_tmp = %p", pmem_tmp);
@@ -2355,6 +2609,7 @@ bool venc_dev::venc_empty_buf(void *buffer, void *pmem_data_buf, unsigned index,
struct v4l2_plane plane;
int rc=0;
struct OMX_BUFFERHEADERTYPE *bufhdr;
+ struct v4l2_control control;
encoder_media_buffer_type * meta_buf = NULL;
temp_buffer = (struct pmem *)buffer;
@@ -2401,11 +2656,24 @@ bool venc_dev::venc_empty_buf(void *buffer, void *pmem_data_buf, unsigned index,
}
} else if (!color_format) {
if (meta_buf->buffer_type == kMetadataBufferTypeCameraSource) {
- if (meta_buf->meta_handle->data[3] & private_handle_t::PRIV_FLAGS_ITU_R_709)
+ if (meta_buf->meta_handle->numFds + meta_buf->meta_handle->numInts > 3 &&
+ meta_buf->meta_handle->data[3] & private_handle_t::PRIV_FLAGS_ITU_R_709)
buf.flags = V4L2_MSM_BUF_FLAG_YUV_601_709_CLAMP;
+ if (meta_buf->meta_handle->numFds + meta_buf->meta_handle->numInts > 2) {
plane.data_offset = meta_buf->meta_handle->data[1];
plane.length = meta_buf->meta_handle->data[2];
plane.bytesused = meta_buf->meta_handle->data[2];
+ }
+ if (!camera_mode_enabled) {
+ camera_mode_enabled = true;
+ control.id = V4L2_CID_MPEG_VIDC_SET_PERF_LEVEL;
+ control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL;
+ rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
+ if (rc)
+ DEBUG_PRINT_HIGH("Failed to set control for perf level");
+ DEBUG_PRINT_LOW("Set control id = 0x%x, value = 0x%x, meta_buf type = %d",
+ control.id, control.value, meta_buf->buffer_type);
+ }
DEBUG_PRINT_LOW("venc_empty_buf: camera buf: fd = %d filled %d of %d flag 0x%x",
fd, plane.bytesused, plane.length, buf.flags);
} else if (meta_buf->buffer_type == kMetadataBufferTypeGrallocSource) {
@@ -2414,6 +2682,29 @@ bool venc_dev::venc_empty_buf(void *buffer, void *pmem_data_buf, unsigned index,
plane.data_offset = 0;
plane.length = handle->size;
plane.bytesused = handle->size;
+ if ((!camera_mode_enabled) && (handle->flags & private_handle_t:: PRIV_FLAGS_CAMERA_WRITE)) {
+ camera_mode_enabled = true;
+ control.id = V4L2_CID_MPEG_VIDC_SET_PERF_LEVEL;
+ control.value = V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL;
+ rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
+ if (rc)
+ DEBUG_PRINT_HIGH("Failed to set perl level");
+ DEBUG_PRINT_LOW("Set control id = 0x%x, value = 0x%x, flags = 0x%x",
+ control.id, control.value, handle->flags);
+ }
+
+ if (handle->base_metadata) {
+ MetaData_t *pMeta =
+ reinterpret_cast<MetaData_t*>(handle->base_metadata);
+ ColorSpace_t csc = pMeta->operation & UPDATE_COLOR_SPACE ?
+ pMeta->colorSpace : (ColorSpace_t)-1;
+ if (csc == ITU_R_709) {
+ buf.flags |= V4L2_MSM_BUF_FLAG_YUV_601_709_CLAMP;
+ DEBUG_PRINT_LOW("venc_empty_buf: force 601 -> 709 clamping");
+ }
+ } else {
+ DEBUG_PRINT_LOW("venc_empty_buf: gralloc metadata is NULL");
+ }
DEBUG_PRINT_LOW("venc_empty_buf: Opaque camera buf: fd = %d "
": filled %d of %d", fd, plane.bytesused, plane.length);
}
@@ -2463,6 +2754,9 @@ bool venc_dev::venc_empty_buf(void *buffer, void *pmem_data_buf, unsigned index,
if (ret) {
DEBUG_PRINT_ERROR("Failed to call streamon");
+ if (errno == EBUSY) {
+ hw_overload = true;
+ }
return false;
} else {
streaming[OUTPUT_PORT] = true;
@@ -2480,7 +2774,8 @@ bool venc_dev::venc_fill_buf(void *buffer, void *pmem_data_buf,unsigned index,un
struct venc_buffer frameinfo;
struct v4l2_buffer buf;
struct v4l2_plane plane[VIDEO_MAX_PLANES];
- int rc = 0, extra_idx;
+ int rc = 0;
+ unsigned int extra_idx;
struct OMX_BUFFERHEADERTYPE *bufhdr;
if (buffer == NULL)
@@ -2572,23 +2867,76 @@ bool venc_dev::venc_set_au_delimiter(OMX_BOOL enable)
return true;
}
+bool venc_dev::venc_validate_hybridhp_params(OMX_U32 layers, OMX_U32 bFrames, OMX_U32 count, int mode)
+{
+ // Check for layers in Hier-p/hier-B with Hier-P-Hybrid
+ if (layers && (mode == HIER_P || mode == HIER_B) && hier_layers.hier_mode == HIER_P_HYBRID)
+ return false;
+
+ // Check for bframes with Hier-P-Hybrid
+ if (bFrames && hier_layers.hier_mode == HIER_P_HYBRID)
+ return false;
+
+ // Check for Hier-P-Hybrid with bframes/LTR/hier-p/Hier-B
+ if (layers && mode == HIER_P_HYBRID && (intra_period.num_bframes || hier_layers.hier_mode == HIER_P ||
+ hier_layers.hier_mode == HIER_B || ltrinfo.count))
+ return false;
+
+ // Check for LTR with Hier-P-Hybrid
+ if (count && hier_layers.hier_mode == HIER_P_HYBRID)
+ return false;
+
+ return true;
+}
+
bool venc_dev::venc_set_hier_layers(QOMX_VIDEO_HIERARCHICALCODINGTYPE type,
OMX_U32 num_layers)
{
struct v4l2_control control;
- control.id = V4L2_CID_MPEG_VIDC_VIDEO_HIER_P_NUM_LAYERS;
+
+ if (!venc_validate_hybridhp_params(num_layers, 0, 0, (int)type)){
+ DEBUG_PRINT_ERROR("Invalid settings, Hier-pLayers enabled with HybridHP");
+ return false;
+ }
+
if (type == QOMX_HIERARCHICALCODING_P) {
- control.value = num_layers;
+ // Reduce layer count by 1 before sending to driver. This avoids
+ // driver doing the same in multiple places.
+ control.id = V4L2_CID_MPEG_VIDC_VIDEO_HIER_P_NUM_LAYERS;
+ control.value = num_layers - 1;
DEBUG_PRINT_HIGH("Set Hier P num layers: %u", (unsigned int)num_layers);
if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) {
DEBUG_PRINT_ERROR("Request to set Hier P num layers failed");
return false;
}
- hier_p_layers.numlayers = num_layers;
+ if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264) {
+ DEBUG_PRINT_LOW("Set H264_SVC_NAL");
+ control.id = V4L2_CID_MPEG_VIDC_VIDEO_H264_NAL_SVC;
+ control.value = V4L2_CID_MPEG_VIDC_VIDEO_H264_NAL_SVC_ENABLED;
+ if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) {
+ DEBUG_PRINT_ERROR("Failed to enable SVC_NAL");
+ return false;
+ }
+ }
+ hier_layers.hier_mode = HIER_P;
+ } else if (type == QOMX_HIERARCHICALCODING_B) {
+ if (m_sVenc_cfg.codectype != V4L2_PIX_FMT_HEVC) {
+ DEBUG_PRINT_ERROR("Failed : Hier B layers supported only for HEVC encode");
+ return false;
+ }
+ control.id = V4L2_CID_MPEG_VIDC_VIDEO_HIER_B_NUM_LAYERS;
+ control.value = num_layers - 1;
+ DEBUG_PRINT_INFO("Set Hier B num layers: %u", (unsigned int)num_layers);
+ if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) {
+ DEBUG_PRINT_ERROR("Request to set Hier P num layers failed");
+ return false;
+ }
+ hier_layers.hier_mode = HIER_B;
} else {
DEBUG_PRINT_ERROR("Request to set hier num layers failed for type: %d", type);
return false;
}
+ hier_layers.numlayers = num_layers;
return true;
}
@@ -2773,7 +3121,7 @@ bool venc_dev::venc_set_session_qp_range(OMX_U32 min_qp, OMX_U32 max_qp)
control.id, control.value);
rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
if (rc) {
- DEBUG_PRINT_ERROR("Failed to set control\n");
+ DEBUG_PRINT_ERROR("Failed to set control");
return false;
}
@@ -2787,12 +3135,12 @@ bool venc_dev::venc_set_session_qp_range(OMX_U32 min_qp, OMX_U32 max_qp)
control.id, control.value);
rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
if (rc) {
- DEBUG_PRINT_ERROR("Failed to set control\n");
+ DEBUG_PRINT_ERROR("Failed to set control");
return false;
}
} else {
- DEBUG_PRINT_ERROR("Wrong qp values[%lu %lu], allowed range[%lu %lu]",
- min_qp, max_qp, session_qp_range.minqp, session_qp_range.maxqp);
+ DEBUG_PRINT_ERROR("Wrong qp values[%u %u], allowed range[%u %u]",
+ (unsigned int)min_qp, (unsigned int)max_qp, (unsigned int)session_qp_range.minqp, (unsigned int)session_qp_range.maxqp);
}
return true;
@@ -3047,6 +3395,96 @@ bool venc_dev::venc_set_profile_level(OMX_U32 eProfile,OMX_U32 eLevel)
return false;
break;
}
+ } else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC) {
+ if (eProfile == OMX_VIDEO_HEVCProfileMain) {
+ requested_profile.profile = V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN;
+ } else if(eProfile == OMX_VIDEO_HEVCProfileMain10) {
+ requested_profile.profile = V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN10;
+ } else {
+ DEBUG_PRINT_ERROR("ERROR: Unsupported HEVC profile = %lu",
+ requested_profile.profile);
+ return false;
+ }
+
+ //profile level
+ switch (eLevel) {
+ case OMX_VIDEO_HEVCMainTierLevel1:
+ requested_level.level = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_1;
+ break;
+ case OMX_VIDEO_HEVCHighTierLevel1:
+ requested_level.level = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_1;
+ break;
+ case OMX_VIDEO_HEVCMainTierLevel2:
+ requested_level.level = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_2;
+ break;
+ case OMX_VIDEO_HEVCHighTierLevel2:
+ requested_level.level = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_2;
+ break;
+ case OMX_VIDEO_HEVCMainTierLevel21:
+ requested_level.level = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_2_1;
+ break;
+ case OMX_VIDEO_HEVCHighTierLevel21:
+ requested_level.level = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_2_1;
+ break;
+ case OMX_VIDEO_HEVCMainTierLevel3:
+ requested_level.level = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_3;
+ break;
+ case OMX_VIDEO_HEVCHighTierLevel3:
+ requested_level.level = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_3;
+ break;
+ case OMX_VIDEO_HEVCMainTierLevel31:
+ requested_level.level = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_3_1;
+ break;
+ case OMX_VIDEO_HEVCHighTierLevel31:
+ requested_level.level = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_3_1;
+ break;
+ case OMX_VIDEO_HEVCMainTierLevel4:
+ requested_level.level = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_4;
+ break;
+ case OMX_VIDEO_HEVCHighTierLevel4:
+ requested_level.level = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_4;
+ break;
+ case OMX_VIDEO_HEVCMainTierLevel41:
+ requested_level.level = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_4_1;
+ break;
+ case OMX_VIDEO_HEVCHighTierLevel41:
+ requested_level.level = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_4_1;
+ break;
+ case OMX_VIDEO_HEVCMainTierLevel5:
+ requested_level.level = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_5;
+ break;
+ case OMX_VIDEO_HEVCHighTierLevel5:
+ requested_level.level = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_5;
+ break;
+ case OMX_VIDEO_HEVCMainTierLevel51:
+ requested_level.level = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_5_1;
+ break;
+ case OMX_VIDEO_HEVCHighTierLevel51:
+ requested_level.level = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_5_1;
+ break;
+ case OMX_VIDEO_HEVCMainTierLevel52:
+ requested_level.level = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_5_2;
+ break;
+ case OMX_VIDEO_HEVCHighTierLevel52:
+ requested_level.level = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_5_2;
+ break;
+ case OMX_VIDEO_HEVCMainTierLevel6:
+ requested_level.level = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_6;
+ break;
+ case OMX_VIDEO_HEVCHighTierLevel6:
+ requested_level.level = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_6;
+ break;
+ case OMX_VIDEO_HEVCMainTierLevel61:
+ requested_level.level = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_6_1;
+ break;
+ case OMX_VIDEO_HEVCHighTierLevel61:
+ requested_level.level = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_6_1;
+ break;
+ default :
+ DEBUG_PRINT_ERROR("ERROR: Unsupported HEVC level= %lu",
+ requested_level.level);
+ return false;
+ }
}
if (!m_profile_set) {
@@ -3059,6 +3497,8 @@ bool venc_dev::venc_set_profile_level(OMX_U32 eProfile,OMX_U32 eLevel)
control.id = V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE;
} else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_H263) {
control.id = V4L2_CID_MPEG_VIDC_VIDEO_H263_PROFILE;
+ } else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC) {
+ control.id = V4L2_CID_MPEG_VIDC_VIDEO_HEVC_PROFILE;
} else {
DEBUG_PRINT_ERROR("Wrong CODEC");
return false;
@@ -3092,6 +3532,8 @@ bool venc_dev::venc_set_profile_level(OMX_U32 eProfile,OMX_U32 eLevel)
control.id = V4L2_CID_MPEG_VIDC_VIDEO_H263_LEVEL;
} else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_VP8) {
control.id = V4L2_CID_MPEG_VIDC_VIDEO_VP8_PROFILE_LEVEL;
+ } else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC) {
+ control.id = V4L2_CID_MPEG_VIDC_VIDEO_HEVC_TIER_LEVEL;
} else {
DEBUG_PRINT_ERROR("Wrong CODEC");
return false;
@@ -3140,17 +3582,28 @@ bool venc_dev::venc_set_intra_period(OMX_U32 nPFrames, OMX_U32 nBFrames)
if ((codec_profile.profile != V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_SIMPLE) &&
(codec_profile.profile != V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) &&
+ (codec_profile.profile != V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN) &&
+ (codec_profile.profile != V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN10) &&
(codec_profile.profile != V4L2_MPEG_VIDEO_H264_PROFILE_HIGH)) {
nBFrames=0;
}
- if ((display_info.w * display_info.h > OMX_CORE_720P_WIDTH * OMX_CORE_720P_HEIGHT)
- && enable_mv_narrow_searchrange && (m_sVenc_cfg.input_width * m_sVenc_cfg.input_height >=
- OMX_CORE_1080P_WIDTH * OMX_CORE_1080P_HEIGHT || is_searchrange_set)) {
- nBFrames=0;
+
+ if (!venc_validate_hybridhp_params(0, nBFrames, 0, 0)) {
+ DEBUG_PRINT_ERROR("Invalid settings, bframes cannot be enabled with HybridHP");
+ return false;
+ }
+
+ intra_period.num_pframes = nPFrames;
+ intra_period.num_bframes = nBFrames;
+
+ if (!venc_calibrate_gop())
+ {
+ DEBUG_PRINT_ERROR("Invalid settings, Hybrid HP enabled with LTR OR Hier-pLayers OR bframes");
+ return false;
}
control.id = V4L2_CID_MPEG_VIDC_VIDEO_NUM_P_FRAMES;
- control.value = nPFrames;
+ control.value = intra_period.num_pframes;
rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
if (rc) {
@@ -3160,9 +3613,8 @@ bool venc_dev::venc_set_intra_period(OMX_U32 nPFrames, OMX_U32 nBFrames)
DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
- intra_period.num_pframes = control.value;
control.id = V4L2_CID_MPEG_VIDC_VIDEO_NUM_B_FRAMES;
- control.value = nBFrames;
+ control.value = intra_period.num_bframes;
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);
@@ -3171,7 +3623,6 @@ bool venc_dev::venc_set_intra_period(OMX_U32 nPFrames, OMX_U32 nBFrames)
return false;
}
- intra_period.num_bframes = nBFrames;
DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%lu", control.id, intra_period.num_bframes);
if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264) {
@@ -3357,6 +3808,11 @@ bool venc_dev::venc_set_intra_refresh(OMX_VIDEO_INTRAREFRESHTYPE ir_mode, OMX_U3
} else if ((ir_mode == OMX_VIDEO_IntraRefreshBoth) &&
(irMBs < ((m_sVenc_cfg.dvs_width * m_sVenc_cfg.dvs_height)>>8))) {
control_mode.value = V4L2_CID_MPEG_VIDC_VIDEO_INTRA_REFRESH_CYCLIC_ADAPTIVE;
+ } else if ((ir_mode == OMX_VIDEO_IntraRefreshRandom) &&
+ (irMBs < ((m_sVenc_cfg.dvs_width * m_sVenc_cfg.dvs_height)>>8))) {
+ control_mode.value = V4L2_CID_MPEG_VIDC_VIDEO_INTRA_REFRESH_RANDOM;
+ control_mbs.id = V4L2_CID_MPEG_VIDC_VIDEO_AIR_MBS;
+ control_mbs.value = irMBs;
} else {
DEBUG_PRINT_ERROR("ERROR: Invalid IntraRefresh Parameters:"
"mb count: %u, mb mode:%d", (unsigned int)irMBs, ir_mode);
@@ -3668,6 +4124,146 @@ bool venc_dev::venc_set_deinterlace(OMX_U32 enable)
return true;
}
+bool venc_dev::venc_calibrate_gop()
+{
+ int ratio, sub_gop_size, gop_size, nPframes, nBframes, nLayers;
+ int num_sub_gops_in_a_gop;
+ nPframes = intra_period.num_pframes;
+ nBframes = intra_period.num_bframes;
+ nLayers = hier_layers.numlayers;
+
+ if (!nPframes) {
+ DEBUG_PRINT_ERROR("nPframes should be non-zero\n");
+ return false;
+ }
+
+ if (nLayers > 1) { /*Multi-layer encoding*/
+ sub_gop_size = 1 << (nLayers - 1);
+ /* Actual GOP definition is nPframes + nBframes + 1 but for the sake of
+ * below calculations we are ignoring +1 . Ignoring +1 in below
+ * calculations is not a mistake but intentional.
+ */
+ gop_size = MAX(sub_gop_size, ROUND(nPframes + nBframes, sub_gop_size));
+ num_sub_gops_in_a_gop = gop_size/sub_gop_size;
+ if (nBframes) { /*Hier-B case*/
+ /*
+ * Frame Type--> I B B B P B B B P I B B P ...
+ * Layer --> 0 2 1 2 0 2 1 2 0 0 2 1 2 ...
+ * nPframes = 2, nBframes = 6, nLayers = 3
+ *
+ * Intention is to keep the intraperiod as close as possible to what is desired
+ * by the client while adjusting nPframes and nBframes to meet other constraints.
+ * eg1: Input by client: nPframes = 9, nBframes = 14, nLayers = 2
+ * Output of this fn: nPframes = 12, nBframes = 12, nLayers = 2
+ *
+ * eg2: Input by client: nPframes = 9, nBframes = 4, nLayers = 2
+ * Output of this fn: nPframes = 7, nBframes = 7, nLayers = 2
+ */
+ nPframes = num_sub_gops_in_a_gop;
+ nBframes = gop_size - nPframes;
+ } else { /*Hier-P case*/
+ /*
+ * Frame Type--> I P P P P P P P I P P P P ...
+ * Layer--> 0 2 1 2 0 2 1 2 0 2 1 2 0 ...
+ * nPframes = 7, nBframes = 0, nLayers = 3
+ *
+ * Intention is to keep the intraperiod as close as possible to what is desired
+ * by the client while adjusting nPframes and nBframes to meet other constraints.
+ * eg1: Input by client: nPframes = 9, nBframes = 0, nLayers = 3
+ * Output of this fn: nPframes = 7, nBframes = 0, nLayers = 3
+ *
+ * eg2: Input by client: nPframes = 10, nBframes = 0, nLayers = 3
+ * Output of this fn:nPframes = 12, nBframes = 0, nLayers = 3
+ */
+ nPframes = gop_size - 1;
+ }
+ } else { /*Single-layer encoding*/
+ if (nBframes) {
+ /* I P B B B P B B B P B B B I P B B...
+ * 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17...
+ * nPframes = 3, nBframes = 9, nLayers = 0
+ *
+ * ratio is rounded,
+ * eg1: nPframes = 9, nBframes = 11 => ratio = 1
+ * eg2: nPframes = 9, nBframes = 16 => ratio = 2
+ */
+ ratio = MAX(1, MIN((nBframes + (nPframes >> 1))/nPframes, 3));
+ nBframes = ratio * nPframes;
+ }
+ }
+ DEBUG_PRINT_LOW("P/B Frames changed from: %ld/%ld to %d/%d",
+ intra_period.num_pframes, intra_period.num_bframes, nPframes, nBframes);
+ intra_period.num_pframes = nPframes;
+ intra_period.num_bframes = nBframes;
+ hier_layers.numlayers = nLayers;
+ return true;
+}
+
+bool venc_dev::venc_set_hybrid_hierp(OMX_U32 layers)
+{
+ DEBUG_PRINT_LOW("venc_set_hybrid_hierp layers: %u", layers);
+ struct v4l2_control control;
+ int rc;
+
+ if (!venc_validate_hybridhp_params(layers, 0, 0, (int) HIER_P_HYBRID)) {
+ DEBUG_PRINT_ERROR("Invalid settings, Hybrid HP enabled with LTR OR Hier-pLayers OR bframes");
+ return false;
+ }
+
+ if (!layers || layers > MAX_HYB_HIERP_LAYERS) {
+ DEBUG_PRINT_ERROR("Invalid numbers of layers set: %d (max supported is 6)", layers);
+ return false;
+ }
+
+ hier_layers.numlayers = layers;
+ hier_layers.hier_mode = HIER_P_HYBRID;
+ if (venc_calibrate_gop()) {
+ // Update the driver with the new nPframes and nBframes
+ control.id = V4L2_CID_MPEG_VIDC_VIDEO_NUM_P_FRAMES;
+ control.value = intra_period.num_pframes;
+ rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
+ if (rc) {
+ DEBUG_PRINT_ERROR("Failed to set control");
+ return false;
+ }
+
+ control.id = V4L2_CID_MPEG_VIDC_VIDEO_NUM_B_FRAMES;
+ control.value = intra_period.num_bframes;
+ rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
+ if (rc) {
+ DEBUG_PRINT_ERROR("Failed to set control");
+ return false;
+ }
+ DEBUG_PRINT_LOW("Updated nPframes (%ld) and nBframes (%ld)",
+ intra_period.num_pframes, intra_period.num_bframes);
+ } else {
+ DEBUG_PRINT_ERROR("Invalid settings, Hybrid HP enabled with LTR OR Hier-pLayers OR bframes");
+ return false;
+ }
+
+ control.id = V4L2_CID_MPEG_VIDC_VIDEO_HYBRID_HIERP_MODE;
+ control.value = layers - 1;
+
+ DEBUG_PRINT_LOW("Calling IOCTL set control for id=%x, val=%d",
+ control.id, control.value);
+
+ rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
+ if (rc) {
+ DEBUG_PRINT_ERROR("Failed to set hybrid hierp %d", rc);
+ return false;
+ }
+
+ DEBUG_PRINT_LOW("SUCCESS IOCTL set control for id=%x, val=%d",
+ control.id, control.value);
+ control.id = V4L2_CID_MPEG_VIDC_VIDEO_H264_NAL_SVC;
+ control.value = V4L2_CID_MPEG_VIDC_VIDEO_H264_NAL_SVC_ENABLED;
+ if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) {
+ DEBUG_PRINT_ERROR("Failed to enable SVC_NAL");
+ return false;
+ }
+ return true;
+}
+
bool venc_dev::venc_set_ltrmode(OMX_U32 enable, OMX_U32 count)
{
DEBUG_PRINT_LOW("venc_set_ltrmode: enable = %u", (unsigned int)enable);
@@ -3676,6 +4272,11 @@ bool venc_dev::venc_set_ltrmode(OMX_U32 enable, OMX_U32 count)
struct v4l2_ext_controls controls;
int rc;
+ if (!venc_validate_hybridhp_params(0, 0, count, 0)) {
+ DEBUG_PRINT_ERROR("Invalid settings, LTR enabled with HybridHP");
+ return false;
+ }
+
ctrl[0].id = V4L2_CID_MPEG_VIDC_VIDEO_LTRMODE;
if (enable)
ctrl[0].value = V4L2_MPEG_VIDC_VIDEO_LTR_MODE_MANUAL;
@@ -3683,10 +4284,12 @@ bool venc_dev::venc_set_ltrmode(OMX_U32 enable, OMX_U32 count)
ctrl[0].value = V4L2_MPEG_VIDC_VIDEO_LTR_MODE_DISABLE;
ctrl[1].id = V4L2_CID_MPEG_VIDC_VIDEO_LTRCOUNT;
- if (count)
+ if (enable && count > 0)
ctrl[1].value = count;
- else
+ else if (enable)
ctrl[1].value = 1;
+ else
+ ctrl[1].value = 0;
controls.count = 2;
controls.ctrl_class = V4L2_CTRL_CLASS_MPEG;
@@ -3701,6 +4304,8 @@ bool venc_dev::venc_set_ltrmode(OMX_U32 enable, OMX_U32 count)
DEBUG_PRINT_ERROR("Failed to set ltrmode %d", rc);
return false;
}
+ ltrinfo.enabled = enable;
+ ltrinfo.count = count;
DEBUG_PRINT_LOW("Success IOCTL set control for id=%x, val=%d id=%x, val=%d",
controls.controls[0].id, controls.controls[0].value,
@@ -3713,17 +4318,26 @@ bool venc_dev::venc_set_ltrmode(OMX_U32 enable, OMX_U32 count)
DEBUG_PRINT_ERROR("ERROR: Request for setting extradata failed");
return false;
}
+
+ if (!venc_set_profile_level(0, 0)) {
+ DEBUG_PRINT_ERROR("ERROR: %s(): Driver Profile/Level is NOT SET",
+ __func__);
+ } else {
+ DEBUG_PRINT_HIGH("%s(): Driver Profile[%lu]/Level[%lu] successfully SET",
+ __func__, codec_profile.profile, profile_level.level);
+ }
+
return true;
}
-bool venc_dev::venc_set_useltr()
+bool venc_dev::venc_set_useltr(OMX_U32 frameIdx)
{
DEBUG_PRINT_LOW("venc_use_goldenframe");
int rc = true;
struct v4l2_control control;
control.id = V4L2_CID_MPEG_VIDC_VIDEO_USELTRFRAME;
- control.value = 1;
+ control.value = frameIdx;
rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
if (rc) {
@@ -3736,14 +4350,14 @@ bool venc_dev::venc_set_useltr()
return true;
}
-bool venc_dev::venc_set_markltr()
+bool venc_dev::venc_set_markltr(OMX_U32 frameIdx)
{
DEBUG_PRINT_LOW("venc_set_goldenframe");
int rc = true;
struct v4l2_control control;
control.id = V4L2_CID_MPEG_VIDC_VIDEO_MARKLTRFRAME;
- control.value = 1;
+ control.value = frameIdx;
rc = ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control);
if (rc) {
@@ -3896,16 +4510,24 @@ bool venc_dev::venc_set_ratectrl_cfg(OMX_VIDEO_CONTROLRATETYPE eControlRate)
control.value=V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_OFF;
break;
case OMX_Video_ControlRateVariableSkipFrames:
- control.value=V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_VBR_VFR;
+ (supported_rc_modes & RC_VBR_VFR) ?
+ control.value = V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_VBR_VFR :
+ status = false;
break;
case OMX_Video_ControlRateVariable:
- control.value=V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_VBR_CFR;
+ (supported_rc_modes & RC_VBR_CFR) ?
+ control.value = V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_VBR_CFR :
+ status = false;
break;
case OMX_Video_ControlRateConstantSkipFrames:
- control.value=V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_CBR_VFR;
+ (supported_rc_modes & RC_CBR_VFR) ?
+ control.value = V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_CBR_VFR :
+ status = false;
break;
case OMX_Video_ControlRateConstant:
- control.value=V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_CBR_CFR;
+ (supported_rc_modes & RC_CBR_CFR) ?
+ control.value = V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_CBR_CFR :
+ status = false;
break;
default:
status = false;
@@ -3963,6 +4585,24 @@ bool venc_dev::venc_set_perf_level(QOMX_VIDEO_PERF_LEVEL ePerfLevel)
return status;
}
+bool venc_dev::venc_set_perf_mode(OMX_U32 mode)
+{
+ struct v4l2_control control;
+ if (mode && mode <= V4L2_MPEG_VIDC_VIDEO_PERF_POWER_SAVE) {
+ control.id = V4L2_CID_MPEG_VIDC_VIDEO_PERF_MODE;
+ control.value = mode;
+ DEBUG_PRINT_LOW("Going to set V4L2_CID_MPEG_VIDC_VIDEO_PERF_MODE");
+ if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) {
+ DEBUG_PRINT_ERROR("Failed to set V4L2_CID_MPEG_VIDC_VIDEO_PERF_MODE");
+ return false;
+ }
+ return true;
+ } else {
+ DEBUG_PRINT_ERROR("Invalid mode set for V4L2_CID_MPEG_VIDC_VIDEO_PERF_MODE: %d", mode);
+ return false;
+ }
+}
+
bool venc_dev::venc_set_vui_timing_info(OMX_BOOL enable)
{
struct v4l2_control control;
@@ -4006,6 +4646,82 @@ bool venc_dev::venc_set_peak_bitrate(OMX_U32 nPeakBitrate)
return true;
}
+bool venc_dev::venc_set_vpx_error_resilience(OMX_BOOL enable)
+{
+ struct v4l2_control control;
+ int rc = 0;
+ control.id = V4L2_CID_MPEG_VIDC_VIDEO_VPX_ERROR_RESILIENCE;
+
+ if (enable)
+ control.value = 1;
+ else
+ control.value = 0;
+
+ DEBUG_PRINT_LOW("venc_set_vpx_error_resilience: %d", control.value);
+
+ 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 VPX Error Resilience");
+ return false;
+ }
+ vpx_err_resilience.enable = 1;
+ DEBUG_PRINT_LOW("Success IOCTL set control for id=%d, value=%d", control.id, control.value);
+ return true;
+}
+
+bool venc_dev::venc_set_session_priority(OMX_U32 priority) {
+ struct v4l2_control control;
+
+ control.id = V4L2_CID_MPEG_VIDC_VIDEO_PRIORITY;
+ switch(priority) {
+ case 0:
+ control.value = V4L2_MPEG_VIDC_VIDEO_PRIORITY_REALTIME_ENABLE;
+ break;
+ case 1:
+ control.value = V4L2_MPEG_VIDC_VIDEO_PRIORITY_REALTIME_DISABLE;
+ break;
+ default:
+ priority = 1;
+ control.value = V4L2_MPEG_VIDC_VIDEO_PRIORITY_REALTIME_DISABLE;
+ DEBUG_PRINT_ERROR("Unsupported priority level %u", priority);
+ break;
+ }
+
+ if (ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) {
+ DEBUG_PRINT_ERROR("Failed to set V4L2_MPEG_VIDC_VIDEO_PRIORITY_REALTIME_%s",
+ priority == 0 ? "ENABLE" : "DISABLE");
+ return false;
+ }
+
+ sess_priority.priority = priority;
+
+ DEBUG_PRINT_LOW("Success IOCTL set control for id=%x, val=%d",
+ control.id, control.value);
+ return true;
+}
+
+bool venc_dev::venc_set_operatingrate(OMX_U32 rate) {
+ struct v4l2_control control;
+
+ control.id = V4L2_CID_MPEG_VIDC_VIDEO_OPERATING_RATE;
+ control.value = rate;
+
+ DEBUG_PRINT_LOW("venc_set_operating_rate: %d fps", rate >> 16);
+ DEBUG_PRINT_LOW("Calling IOCTL set control for id=%d, val=%d", control.id, control.value);
+
+ if(ioctl(m_nDriver_fd, VIDIOC_S_CTRL, &control)) {
+ hw_overload = errno == EBUSY;
+ DEBUG_PRINT_ERROR("Failed to set operating rate %d fps (%s)",
+ rate >> 16, hw_overload ? "HW overload" : strerror(errno));
+ return false;
+ }
+ operating_rate = rate;
+ DEBUG_PRINT_LOW("Operating Rate Set = %d fps", rate >> 16);
+ return true;
+}
+
bool venc_dev::venc_get_profile_level(OMX_U32 *eProfile,OMX_U32 *eLevel)
{
bool status = true;
@@ -4218,6 +4934,104 @@ bool venc_dev::venc_get_profile_level(OMX_U32 *eProfile,OMX_U32 *eLevel)
status = false;
break;
}
+ } else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC) {
+ switch (codec_profile.profile) {
+ case V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN:
+ *eProfile = OMX_VIDEO_HEVCProfileMain;
+ break;
+ case V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN10:
+ *eProfile = OMX_VIDEO_HEVCProfileMain10;
+ break;
+ default:
+ *eProfile = OMX_VIDEO_HEVCProfileMax;
+ status = false;
+ break;
+ }
+ if (!status) {
+ return status;
+ }
+
+ switch (profile_level.level) {
+ case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_1:
+ *eLevel = OMX_VIDEO_HEVCMainTierLevel1;
+ break;
+ case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_1:
+ *eLevel = OMX_VIDEO_HEVCHighTierLevel1;
+ break;
+ case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_2:
+ *eLevel = OMX_VIDEO_HEVCMainTierLevel2;
+ break;
+ case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_2:
+ *eLevel = OMX_VIDEO_HEVCHighTierLevel2;
+ break;
+ case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_2_1:
+ *eLevel = OMX_VIDEO_HEVCMainTierLevel21;
+ break;
+ case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_2_1:
+ *eLevel = OMX_VIDEO_HEVCHighTierLevel21;
+ break;
+ case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_3:
+ *eLevel = OMX_VIDEO_HEVCMainTierLevel3;
+ break;
+ case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_3:
+ *eLevel = OMX_VIDEO_HEVCHighTierLevel3;
+ break;
+ case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_3_1:
+ *eLevel = OMX_VIDEO_HEVCMainTierLevel31;
+ break;
+ case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_3_1:
+ *eLevel = OMX_VIDEO_HEVCHighTierLevel31;
+ break;
+ case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_4:
+ *eLevel = OMX_VIDEO_HEVCMainTierLevel4;
+ break;
+ case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_4:
+ *eLevel = OMX_VIDEO_HEVCHighTierLevel4;
+ break;
+ case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_4_1:
+ *eLevel = OMX_VIDEO_HEVCMainTierLevel41;
+ break;
+ case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_4_1:
+ *eLevel = OMX_VIDEO_HEVCHighTierLevel41;
+ break;
+ case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_5:
+ *eLevel = OMX_VIDEO_HEVCMainTierLevel5;
+ break;
+ case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_5:
+ *eLevel = OMX_VIDEO_HEVCHighTierLevel5;
+ break;
+ case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_5_1:
+ *eLevel = OMX_VIDEO_HEVCMainTierLevel51;
+ break;
+ case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_5_1:
+ *eLevel = OMX_VIDEO_HEVCHighTierLevel51;
+ break;
+ case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_5_2:
+ *eLevel = OMX_VIDEO_HEVCMainTierLevel52;
+ break;
+ case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_5_2:
+ *eLevel = OMX_VIDEO_HEVCHighTierLevel52;
+ break;
+ case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_6:
+ *eLevel = OMX_VIDEO_HEVCMainTierLevel6;
+ break;
+ case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_6:
+ *eLevel = OMX_VIDEO_HEVCHighTierLevel6;
+ break;
+ case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_6_1:
+ *eLevel = OMX_VIDEO_HEVCMainTierLevel61;
+ break;
+ case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_6_1:
+ *eLevel = OMX_VIDEO_HEVCHighTierLevel61;
+ break;
+ case V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_MAIN_TIER_LEVEL_6_2:
+ *eLevel = OMX_VIDEO_HEVCMainTierLevel62;
+ break;
+ default:
+ *eLevel = OMX_VIDEO_HEVCLevelMax;
+ status = false;
+ break;
+ }
}
return status;
@@ -4372,8 +5186,40 @@ bool venc_dev::venc_validate_profile_level(OMX_U32 *eProfile, OMX_U32 *eLevel)
}
}
return true;
+ } else if (m_sVenc_cfg.codectype == V4L2_PIX_FMT_HEVC) {
+ if (*eProfile == 0) {
+ if (!m_profile_set) {
+ *eProfile = OMX_VIDEO_HEVCProfileMain;
} else {
- DEBUG_PRINT_LOW("Invalid codec type");
+ switch (codec_profile.profile) {
+ case V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN:
+ *eProfile = OMX_VIDEO_HEVCProfileMain;
+ break;
+ case V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN10:
+ *eProfile = OMX_VIDEO_HEVCProfileMain10;
+ break;
+ default:
+ DEBUG_PRINT_ERROR("%s(): Unknown Error", __func__);
+ return false;
+ }
+ }
+ }
+
+ if (*eLevel == 0 && !m_level_set) {
+ *eLevel = OMX_VIDEO_HEVCLevelMax;
+ }
+
+ if (*eProfile == OMX_VIDEO_HEVCProfileMain) {
+ profile_tbl = (unsigned int const *)hevc_profile_level_table;
+ } else if (*eProfile == OMX_VIDEO_HEVCProfileMain10) {
+ profile_tbl = (unsigned int const *)
+ (&hevc_profile_level_table[HEVC_MAIN10_START]);
+ } else {
+ DEBUG_PRINT_ERROR("Unsupported HEVC profile type %u", (unsigned int)*eProfile);
+ return false;
+ }
+ } else {
+ DEBUG_PRINT_ERROR("Invalid codec type");
return false;
}
@@ -4396,20 +5242,46 @@ bool venc_dev::venc_validate_profile_level(OMX_U32 *eProfile, OMX_U32 *eLevel)
mb_per_sec = mb_per_frame * m_sVenc_cfg.fps_num / m_sVenc_cfg.fps_den;
+ bool h264, ltr, hlayers;
+ unsigned int hybridp = 0, maxDpb = profile_tbl[5] / mb_per_frame;
+ h264 = m_sVenc_cfg.codectype == V4L2_PIX_FMT_H264;
+ ltr = ltrinfo.enabled && ((ltrinfo.count + 2) <= MIN((unsigned int) (profile_tbl[5] / mb_per_frame), MAXDPB));
+ hlayers = hier_layers.numlayers && hier_layers.hier_mode == HIER_P &&
+ ((intra_period.num_bframes + ltrinfo.count + hier_layers.numlayers + 1) <= (unsigned int) (profile_tbl[5] / profile_tbl[0]));
+
+ /* Hybrid HP reference buffers:
+ layers = 1, 2 need 1 reference buffer
+ layers = 3, 4 need 2 reference buffers
+ layers = 5, 6 need 3 reference buffers
+ */
+
+ if(hier_layers.hier_mode == HIER_P_HYBRID)
+ hybridp = MIN(MAX(maxDpb, ((hier_layers.numlayers + 1) / 2)), 16);
+
do {
if (mb_per_frame <= (unsigned int)profile_tbl[0]) {
if (mb_per_sec <= (unsigned int)profile_tbl[1]) {
if (m_sVenc_cfg.targetbitrate <= (unsigned int)profile_tbl[2]) {
+ if (h264 && (ltr || hlayers || hybridp)) {
+ // Update profile and level to adapt to the LTR and Hier-p/Hybrid-HP settings
+ new_level = (int)profile_tbl[3];
+ new_profile = (int)profile_tbl[4];
+ profile_level_found = true;
+ DEBUG_PRINT_LOW("Appropriate profile/level for LTR count: %u OR Hier-p: %u is %u/%u, maxDPB: %u",
+ ltrinfo.count, hier_layers.numlayers, (int)new_profile, (int)new_level,
+ MIN((unsigned int) (profile_tbl[5] / mb_per_frame), MAXDPB));
+ break;
+ } else {
new_level = (int)profile_tbl[3];
new_profile = (int)profile_tbl[4];
profile_level_found = true;
- DEBUG_PRINT_LOW("Appropriate profile/level found %u/%u", (unsigned int)new_profile, (unsigned int)new_level);
+ DEBUG_PRINT_LOW("Appropriate profile/level found %u/%u", (int) new_profile, (int) new_level);
break;
}
}
}
-
- profile_tbl = profile_tbl + 5;
+ }
+ profile_tbl = profile_tbl + MAX_PROFILE_PARAMS;
} while (profile_tbl[0] != 0);
if (profile_level_found != true) {
@@ -4418,7 +5290,8 @@ bool venc_dev::venc_validate_profile_level(OMX_U32 *eProfile, OMX_U32 *eLevel)
}
if ((*eLevel == OMX_VIDEO_MPEG4LevelMax) || (*eLevel == OMX_VIDEO_AVCLevelMax)
- || (*eLevel == OMX_VIDEO_H263LevelMax || (*eLevel == OMX_VIDEO_VP8ProfileMax))) {
+ || (*eLevel == OMX_VIDEO_H263LevelMax) || (*eLevel == OMX_VIDEO_VP8ProfileMax)
+ || (*eLevel == OMX_VIDEO_HEVCLevelMax)) {
*eLevel = new_level;
}