| 1 | /*
|
|---|
| 2 | * x264Encoder.c
|
|---|
| 3 | * x264Encoder
|
|---|
| 4 | *
|
|---|
| 5 | * Created by Takashi Mochizuki on 07/02/18. (mochi at da2.so-net.ne.jp)
|
|---|
| 6 | * Copyright 2007-2010 MyCometG3. All rights reserved.
|
|---|
| 7 | *
|
|---|
| 8 |
|
|---|
| 9 | This file is part of x264Encoder.
|
|---|
| 10 |
|
|---|
| 11 | x264Encoder is free software; you can redistribute it and/or modify
|
|---|
| 12 | it under the terms of the GNU General Public License as published by
|
|---|
| 13 | the Free Software Foundation; either version 2 of the License, or
|
|---|
| 14 | (at your option) any later version.
|
|---|
| 15 |
|
|---|
| 16 | x264Encoder is distributed in the hope that it will be useful,
|
|---|
| 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|---|
| 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|---|
| 19 | GNU General Public License for more details.
|
|---|
| 20 |
|
|---|
| 21 | You should have received a copy of the GNU General Public License
|
|---|
| 22 | along with x264Encoder; if not, write to the Free Software
|
|---|
| 23 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|---|
| 24 |
|
|---|
| 25 | */
|
|---|
| 26 |
|
|---|
| 27 | #include "x264EncoderVersion.h"
|
|---|
| 28 | #include "x264EncoderUtil.h"
|
|---|
| 29 |
|
|---|
| 30 | #define kNibName "Settings"
|
|---|
| 31 | #define kMaxSourceFrame 128 /* So much encoder delay... */
|
|---|
| 32 | #define kBundleIdentifier "com.MyCometG3.x264Encoder"
|
|---|
| 33 | #define kDispatchFile "x264EncoderDispatch.h"
|
|---|
| 34 | #define kCodecID CODEC_ID_H264
|
|---|
| 35 | #define kCodec_FormatType "avc1" /* not 'avc1' but "avc1" here */
|
|---|
| 36 | #define kCodec_cType 'avc1' /* OSType */
|
|---|
| 37 | #define kExtraDataTag 'avcC' /* MPEG4=esds, x264=avcC */
|
|---|
| 38 | #define REMOVELOG 1 /* Should be 1 */
|
|---|
| 39 | #define WRITELOG 0 /* MPEG4=1, x264=0, xvid=1 */
|
|---|
| 40 | #define MPEG4 0 /* MPEG4=1, x264=0, xvid=0 */
|
|---|
| 41 | #define XVID 0 /* MPEG4=0, x264=0, xvid=1 */
|
|---|
| 42 | #define TESTVFR 1 /* MPEG4=0, x264=1, xvid=0 */ /* test vfr (variable frame rate) support */
|
|---|
| 43 | #define X264 1 /* MPEG4=0, x264=1, xvid=0 */
|
|---|
| 44 | #define NATIVERECT 0 /* default u/v plane does not have correct alignment */
|
|---|
| 45 | #define USECoreVF 1 /* CoreVF Framework support */
|
|---|
| 46 | #define STRICTFLAG 0 /* Use strict flags on each samples */
|
|---|
| 47 |
|
|---|
| 48 | #define REV_ENDIAN_BIG 1 /* params struct version; 0:NativeEndian, positive:BigEndian */
|
|---|
| 49 | #define REV_PSYRD 2 /* params struct version; with psyrd, and without FLAG2_TRELLIS_QUANT */
|
|---|
| 50 | #define REV_MAXQDIFF 3 /* params struct version; with MAXQDIFF and CHROMAOFFSET */
|
|---|
| 51 | #define REV_COREVF 4 /* params struct version; with CoreVF framework support; 1.0.0 */
|
|---|
| 52 | #define REV_SUBSAMPLE 5 /* params struct version; chroma subsampling mode support; 1.0.1 */
|
|---|
| 53 | #define REV_X264PROFILE 6 /* params struct version; new x264 profile support; 1.1.0 */
|
|---|
| 54 | #define REV_MBTREE 7 /* params struct version; new x264 mbtree support; 1.1.2 */
|
|---|
| 55 | #define REV_WEIGHTP 8 /* params struct version; with weightp; 1.1.8 */
|
|---|
| 56 | #define REV_FLAG2_MBTREE 9 /* params struct version; libav20774 support FLAG2_MBTREE natively; 1.1.10 */
|
|---|
| 57 | #define REV_INTERLACED 10 /* params struct version; interlaced,lossless,aspect,cleanaperture; 1.2.0 */
|
|---|
| 58 | #define REV_FLAG2_PSY 11 /* params struct version; libav22670 supports FLAG2_PSY, FLAG2_SSIM natively; 1.2.3 */
|
|---|
| 59 | #define REV_LEVELFREE 12 /* params struct version; support all h.264 level value; 1.2.7 */
|
|---|
| 60 | #define REV_IGNOREQSLIDER 13 /* params struct version; user can ignore quality slider; 1.2.8 */
|
|---|
| 61 | #define REV_FAKEINTERLACED 14 /* params struct version; new --fake-interlaced support; 1.2.9 */
|
|---|
| 62 | #define REV_X264OPENGOP 15 /* params struct version; support open gop; 1.2.13 */
|
|---|
| 63 |
|
|---|
| 64 | #define X264PROFILE_UNDEF 0
|
|---|
| 65 | #define X264PROFILE_BASE 1
|
|---|
| 66 | #define X264PROFILE_MAIN 2
|
|---|
| 67 | #define X264PROFILE_HIGH 3
|
|---|
| 68 |
|
|---|
| 69 | #define X264PRESET_ULTRAFAST -3
|
|---|
| 70 | #define X264PRESET_SUPERFAST -5
|
|---|
| 71 | #define X264PRESET_VERYFAST -2
|
|---|
| 72 | #define X264PRESET_FASTER -4
|
|---|
| 73 | #define X264PRESET_FAST -1
|
|---|
| 74 | #define X264PRESET_MEDIUM 0
|
|---|
| 75 | #define X264PRESET_SLOW 1
|
|---|
| 76 | #define X264PRESET_SLOWER 2
|
|---|
| 77 | #define X264PRESET_VERYSLOW 4
|
|---|
| 78 | #define X264PRESET_PLACEBO 3
|
|---|
| 79 |
|
|---|
| 80 | #define X264TUNE_UNDEF 0
|
|---|
| 81 | #define X264TUNE_FILM 1
|
|---|
| 82 | #define X264TUNE_ANIMATION 2
|
|---|
| 83 | #define X264TUNE_GRAIN 3
|
|---|
| 84 | #define X264TUNE_STILLIMAGE 9
|
|---|
| 85 | #define X264TUNE_PSNR 4
|
|---|
| 86 | #define X264TUNE_SSIM 5
|
|---|
| 87 | #define X264TUNE_TOUHOU 6
|
|---|
| 88 | #define X264TUNE_FASTDECODE 7
|
|---|
| 89 | #define X264TUNE_ZEROLATENCY 8
|
|---|
| 90 |
|
|---|
| 91 | #pragma mark -
|
|---|
| 92 | #pragma mark Struct definitions
|
|---|
| 93 |
|
|---|
| 94 |
|
|---|
| 95 | typedef struct {
|
|---|
| 96 | //
|
|---|
| 97 | Boolean LOG_INFO;
|
|---|
| 98 | Boolean LOG_DEBUG;
|
|---|
| 99 | Boolean LOG_STATS;
|
|---|
| 100 | Boolean REV_STRUCT; // 0:native-endian, 1:big-endian, 2:(0.9.0~).
|
|---|
| 101 |
|
|---|
| 102 | // codec context flag store
|
|---|
| 103 | Boolean reserved0x0001;
|
|---|
| 104 | Boolean FLAG_QSCALE; // 0x0002
|
|---|
| 105 | Boolean FLAG_4MV; // 0x0004
|
|---|
| 106 | Boolean reserved0x0008;
|
|---|
| 107 | Boolean FLAG_QPEL; // 0x0010
|
|---|
| 108 | Boolean FLAG_GMC; // 0x0020
|
|---|
| 109 | Boolean FLAG_MV0; // 0x0040
|
|---|
| 110 | Boolean FLAG_PART; // 0x0080
|
|---|
| 111 | Boolean reserved0x0100;
|
|---|
| 112 | Boolean reserved0x0200;
|
|---|
| 113 | Boolean reserved0x0400;
|
|---|
| 114 | Boolean FLAG_LOOP_FILTER; // 0x0800
|
|---|
| 115 | Boolean reserved0x1000;
|
|---|
| 116 | Boolean reserved0x2000;
|
|---|
| 117 | Boolean reserved0x4000;
|
|---|
| 118 | Boolean FLAG_PSNR; // 0x8000
|
|---|
| 119 | Boolean reserved0x00010000;
|
|---|
| 120 | Boolean FLAG_NORMALIZE_AQP; // 0x00020000
|
|---|
| 121 | Boolean FLAG_INTERLACED_DCT; // 0x00040000;
|
|---|
| 122 | Boolean reserved0x00080000;
|
|---|
| 123 | Boolean reserved0x00100000;
|
|---|
| 124 | Boolean reserved0x00200000;
|
|---|
| 125 | Boolean reserved0x00400000;
|
|---|
| 126 | Boolean reserved0x00800000;
|
|---|
| 127 | Boolean FLAG_AC_PRED; // 0x01000000
|
|---|
| 128 | Boolean reserved0x02000000;
|
|---|
| 129 | Boolean FLAG_CBP_RD; // 0x04000000
|
|---|
| 130 | Boolean FLAG_QP_RD; // 0x08000000
|
|---|
| 131 | Boolean reserved0x10000000;
|
|---|
| 132 | Boolean reserved0x20000000;
|
|---|
| 133 | Boolean reserved0x40000000;
|
|---|
| 134 | Boolean FLAG_CLOSED_GOP; // 0x80000000
|
|---|
| 135 |
|
|---|
| 136 | char NATIVE_FPS; // 1:NTSC, 2:PAL, 3:FILM, 11:N/2, 12:P/2, 13:F/2, 21:Nx2, 22:Px2, 23:Fx2
|
|---|
| 137 | char MB_DECISION; // 1:FF_MB_DECISION_SIMPLE, 2:FF_MB_DECISION_BITS, 3:FF_MB_DECISION_RD
|
|---|
| 138 | char RC_QSQUISH; // 0-> clipping, 1-> use a nice continous function to limit qscale wthin qmin/qmax
|
|---|
| 139 | char MPEG_QUANT; // 0-> h263 quant 1-> mpeg quant.
|
|---|
| 140 | char THREADS; // Thread count. 1:single, 2:dual, 3:quad, 4:octa, 9:auto.
|
|---|
| 141 | char GAMMA; // 0:DontAddGamma, 1:Gamma2.2
|
|---|
| 142 | char NCLC; // 1:DontAddNCLC, 3:616, 4:516, 5:677, 6:111, 7:222
|
|---|
| 143 | char ME_METHOD; // 1:EPZS, 2:HEX, 3:UMH, 4:FULL, 5:X1, 6:TESA
|
|---|
| 144 |
|
|---|
| 145 | int SC_THRESHOLD; // limited to (-75K, 75K)
|
|---|
| 146 | int QCOMPRESS; // limited to (50, 80) as (0.50, 0.80)
|
|---|
| 147 | int NOISE_REDUCTION; // limited to (0, 1000)
|
|---|
| 148 | int RC_MAXRATE; // limited to (0, 245760); Kbps
|
|---|
| 149 |
|
|---|
| 150 | char REFS; // limited to (1, 13); default 1
|
|---|
| 151 | char ME_RANGE; // limited to (4, 64); default 16
|
|---|
| 152 | char MAX_BFRAMES; // limited to (1, 13); default 1
|
|---|
| 153 | char CODER_TYPE; // 1:CAVLC, 2:CABAC
|
|---|
| 154 | char DIRECTPRED; // 1:Disabled, 2:Spatial, 3:Temporal, 4:Auto
|
|---|
| 155 | char CRF; // 0:Normal, 1:ConstantRateFactor
|
|---|
| 156 | char ADAPTIVE_BFRAME; // 0:Normal, 1:B_ADAPT_FAST, 2:B_ADAPT_TRELLIS
|
|---|
| 157 | char ME_SUBQ; // limited to (0, 11); subpel quality
|
|---|
| 158 |
|
|---|
| 159 | char TRELLIS; // 1:Disabled, 2:FinalOnly, 3:All; default 1
|
|---|
| 160 | char TURBO; // 1:Disabled, 2:Turbo 1, 3:Turbo 2
|
|---|
| 161 | char CHROMA_ME; // 0:OFF, 1:ON; default 1
|
|---|
| 162 | char PART_4X4; // 0:OFF, 1:partition=all; default 0
|
|---|
| 163 | char BIDIR_ME; // 0:OFF, 1:ON; default 0
|
|---|
| 164 | char USE3RDPASS; // 0:OFF, 1:ON; default 0
|
|---|
| 165 | char LEVEL; // 9->auto, 13->1.3, 21->2.1, 30->3.0, 31->3.1, 41->4.1, 51->5.1
|
|---|
| 166 | char EMBEDUUID; // 0:OFF, 1:ON
|
|---|
| 167 |
|
|---|
| 168 | // codec context flag2 store
|
|---|
| 169 | Boolean reserved20x0001;
|
|---|
| 170 | Boolean reserved20x0002;
|
|---|
| 171 | Boolean reserved20x0004;
|
|---|
| 172 | Boolean reserved20x0008;
|
|---|
| 173 | Boolean FLAG2_BPYRAMID; // 0x0010
|
|---|
| 174 | Boolean FLAG2_WPRED; // 0x0020
|
|---|
| 175 | Boolean FLAG2_MIXED_REFS; // 0x0040
|
|---|
| 176 | Boolean FLAG2_8X8DCT; // 0x0080
|
|---|
| 177 | Boolean FLAG2_FASTPSKIP; // 0x0100
|
|---|
| 178 | Boolean FLAG2_AUD; // 0x0200
|
|---|
| 179 | Boolean FLAG2_BRDO; // 0x0400
|
|---|
| 180 | Boolean reserved20x0800;
|
|---|
| 181 | Boolean reserved20x1000;
|
|---|
| 182 | Boolean reserved20x2000;
|
|---|
| 183 | Boolean reserved20x4000;
|
|---|
| 184 | Boolean reserved20x8000;
|
|---|
| 185 | Boolean reserved20x00010000;
|
|---|
| 186 | Boolean reserved20x00020000;
|
|---|
| 187 | Boolean FLAG2_MBTREE; // 0x00040000
|
|---|
| 188 | Boolean FLAG2_PSY; // 0x00080000;
|
|---|
| 189 | Boolean FLAG2_SSIM; // 0x00100000;
|
|---|
| 190 | Boolean reserved20x00200000;
|
|---|
| 191 | Boolean reserved20x00400000;
|
|---|
| 192 | Boolean reserved20x00800000;
|
|---|
| 193 | Boolean reserved20x01000000;
|
|---|
| 194 | Boolean reserved20x02000000;
|
|---|
| 195 | Boolean reserved20x04000000;
|
|---|
| 196 | Boolean reserved20x08000000;
|
|---|
| 197 | Boolean reserved20x10000000;
|
|---|
| 198 | Boolean reserved20x20000000;
|
|---|
| 199 | Boolean reserved20x40000000;
|
|---|
| 200 | Boolean reserved20x80000000;
|
|---|
| 201 |
|
|---|
| 202 | int RC_BUFSIZE; // limited to (0, 245760); Kbit
|
|---|
| 203 | int AQ_STRENGTH; // limited to (50, 150) as (0.5, 1.5); default 100
|
|---|
| 204 | int PSYRD_RDO; // limited to (0, 100) as (0.0, 10.0); default 10
|
|---|
| 205 | int PSYRD_TRELLIS; // limited to (0, 100) as (0.0, 10.0); default 0
|
|---|
| 206 |
|
|---|
| 207 | char DEBLOCK_ALPHA; // limited to (-6, 6); default 0
|
|---|
| 208 | char DEBLOCK_BETA; // limited to (-6, 6); default 0
|
|---|
| 209 | char AQ_MODE; // 1:NONE, 2:VARIANCE, 3:AUTOVARIANCE; default 2
|
|---|
| 210 | char LUMI_MASKING; // xvid; lumi_masking; 0:off, 1:on; default 0
|
|---|
| 211 |
|
|---|
| 212 | char KEYINT_MIN; // x264; IDR Interval; 0-25; clipped at (1 + KEYINT/2); default 25
|
|---|
| 213 | char CQM_PRESET; // x264; quantizer matrix; 0:flat16, 1:jvt; default 0
|
|---|
| 214 | char NO_DCT_DECIMATE; // x264; dct-decimate; 0:On, 1:Off; default 0
|
|---|
| 215 | char MAX_QDIFF; // limited to (3, 16); x264 default 4; mp4v default 3
|
|---|
| 216 |
|
|---|
| 217 | char CHROMAOFFSET; // x264; chroma-qp-offset; (-12, 12) default 0
|
|---|
| 218 | char FILTERPRESET; // CoreVF; off:0, 1-8:preset1-preset8, -1:CoreVF Default
|
|---|
| 219 | char SUBSAMPLING; // 422->420; 0:progressive, 1:interlaced-3:1, 2:interlaced-5:3, -1:422direct(CoreVF)
|
|---|
| 220 | char X264PROFILE; // x264; --profile (git-1177); default 3
|
|---|
| 221 |
|
|---|
| 222 | char X264PRESET; // x264; --preset (git-1177); default 0
|
|---|
| 223 | char X264TUNE; // x264; --tune (git-1177); default 0
|
|---|
| 224 | char MBTREE; // legacy; x264; --mbtree (git-1197); default 1 ; Use FLAG2_MBTREE instead from 1.1.10
|
|---|
| 225 | char PSY; // legacy; x264; --psy (git-1197); default 1 ; Use FLAG2_PSY instead from 1.2.3
|
|---|
| 226 |
|
|---|
| 227 | int RC_LOOKAHEAD; // x264; --rc-lookahead (git-1197); default 40
|
|---|
| 228 | int IP_FACTOR; // limited to (-300, 300) as (-3.0, 3.0); default 140 (as 1.4)
|
|---|
| 229 | int PB_FACTOR; // limited to (-300, 300) AS (-3.0, 3.0); default 130 (as 1.3)
|
|---|
| 230 | int reservedInt4; //
|
|---|
| 231 |
|
|---|
| 232 | char WEIGHTP; // x264; --weightp; 1:Disabled, 2:Weighted refs, 3:Weighted refs + Duplicates
|
|---|
| 233 | char TOPFIELDFIRST; // top field first; default 0 (=Progressive or bottom field first)
|
|---|
| 234 | char LOSSLESS; // x264; same as "--qp 0"; 1:On, 1:Off; default is 0
|
|---|
| 235 | char BD_TUNE; // x264; --nal-hrd vbr --b-pyramid strict --slices 4
|
|---|
| 236 |
|
|---|
| 237 | char USEASPECTRATIO; // Embed container level Pixel Aspect Ratio
|
|---|
| 238 | char USECLEANAPERTURE; // Embed container level Clean Aperture
|
|---|
| 239 | char TAGASPECTRATIO; // Preset Tag for Pixel Aspect Ratio
|
|---|
| 240 | char TAGCLEANAPERTURE; // Preset Tag for Clean Aperture
|
|---|
| 241 |
|
|---|
| 242 | UInt32 hSpacing; /* Horizontal Spacing */
|
|---|
| 243 | UInt32 vSpacing; /* Vertical Spacing */
|
|---|
| 244 | UInt32 cleanApertureWidthN; /* width of clean aperture, numerator, denominator */
|
|---|
| 245 | UInt32 cleanApertureWidthD;
|
|---|
| 246 | UInt32 cleanApertureHeightN; /* height of clean aperture, numerator, denominator*/
|
|---|
| 247 | UInt32 cleanApertureHeightD;
|
|---|
| 248 | SInt32 horizOffN; /* horizontal offset of clean aperture center minus (width-1)/2, numerator, denominator */
|
|---|
| 249 | UInt32 horizOffD;
|
|---|
| 250 | SInt32 vertOffN; /* vertical offset of clean aperture center minus (height-1)/2, numerator, denominator */
|
|---|
| 251 | UInt32 vertOffD;
|
|---|
| 252 |
|
|---|
| 253 | char OVERRIDECRFQSCALE; /* override quality slider setting in application for CRF/QSCALE */
|
|---|
| 254 | char USERCRFQSCALE; /* user specified qscale value; default 23 */
|
|---|
| 255 | char OVERRIDEQMIN; /* override quality slider setting in application for ABR */
|
|---|
| 256 | char USERQMIN; /* user specified qmin value; default 4 */
|
|---|
| 257 |
|
|---|
| 258 | char FAKEINTERLACED; // x264; --fake-interlaced; default 0 (=off)
|
|---|
| 259 | char reservedChar2; //
|
|---|
| 260 | char reservedChar3; //
|
|---|
| 261 | char reservedChar4; //
|
|---|
| 262 | } params;
|
|---|
| 263 |
|
|---|
| 264 | // Additional parameters which are not supported in AVCodecContext struct
|
|---|
| 265 | typedef struct {
|
|---|
| 266 | char* log_file_path;
|
|---|
| 267 | char CQM_PRESET;
|
|---|
| 268 | char NO_DCT_DECIMATE;
|
|---|
| 269 | char X264PRESET;
|
|---|
| 270 | char X264TUNE;
|
|---|
| 271 | char TOPFIELDFIRST;
|
|---|
| 272 | char BD_TUNE;
|
|---|
| 273 | int TIMESCALE;
|
|---|
| 274 | char FAKEINTERLACED;
|
|---|
| 275 | } params_opaque;
|
|---|
| 276 |
|
|---|
| 277 | typedef struct {
|
|---|
| 278 | ComponentInstance self;
|
|---|
| 279 | ComponentInstance target;
|
|---|
| 280 |
|
|---|
| 281 | ICMCompressorSessionRef session; // NOTE: we do not need to retain or release this
|
|---|
| 282 | ICMCompressionSessionOptionsRef sessionOptions;
|
|---|
| 283 |
|
|---|
| 284 | Boolean meetsErr;
|
|---|
| 285 |
|
|---|
| 286 | // ICMCompressorFrame set
|
|---|
| 287 | CFMutableArrayRef array_source_frame;
|
|---|
| 288 |
|
|---|
| 289 | //
|
|---|
| 290 | params params;
|
|---|
| 291 | ImageDescriptionHandle imageDescription;
|
|---|
| 292 | params_opaque params_opaque;
|
|---|
| 293 |
|
|---|
| 294 | //
|
|---|
| 295 | int width, height, widthRoundedUp, heightRoundedUp;
|
|---|
| 296 |
|
|---|
| 297 | //
|
|---|
| 298 | Boolean use_B_frame;
|
|---|
| 299 | Boolean only_I_frame;
|
|---|
| 300 | Boolean add_gamma;
|
|---|
| 301 | Boolean add_nclc;
|
|---|
| 302 | Boolean add_uuid; // Special UUID for iPod Video VGA H.264
|
|---|
| 303 |
|
|---|
| 304 | int frame_count;
|
|---|
| 305 | int delayCount;
|
|---|
| 306 |
|
|---|
| 307 | // time calculation
|
|---|
| 308 | CFDateRef initialDate;
|
|---|
| 309 | CFDateRef passDate;
|
|---|
| 310 |
|
|---|
| 311 | // Multipass support
|
|---|
| 312 | int ICM_passcount;
|
|---|
| 313 | Boolean emit_frame;
|
|---|
| 314 | Boolean use3rdpass;
|
|---|
| 315 | Boolean fakeMultipass;
|
|---|
| 316 |
|
|---|
| 317 | // libavcodec
|
|---|
| 318 | AVCodec* codec;
|
|---|
| 319 | AVCodecContext* codecCont;
|
|---|
| 320 |
|
|---|
| 321 | Boolean codec_is_opened;
|
|---|
| 322 | Boolean codec_open_failed;
|
|---|
| 323 | Boolean extraDataReady;
|
|---|
| 324 |
|
|---|
| 325 | FILE* logfile;
|
|---|
| 326 |
|
|---|
| 327 | int64_t next_pts_value;
|
|---|
| 328 | int64_t video_size;
|
|---|
| 329 |
|
|---|
| 330 | // Encoded frame buffer
|
|---|
| 331 | UInt8* encode_buffer;
|
|---|
| 332 | int encode_buffer_size;
|
|---|
| 333 | int frame_size;
|
|---|
| 334 |
|
|---|
| 335 | // YUV Source frame buffer
|
|---|
| 336 | AVFrame* frame;
|
|---|
| 337 | UInt8* planer_buffer;
|
|---|
| 338 |
|
|---|
| 339 | // Chroma subsampling mode
|
|---|
| 340 | int subsampling;
|
|---|
| 341 |
|
|---|
| 342 | #if USECoreVF
|
|---|
| 343 | int filterPreset;
|
|---|
| 344 | CFStringRef filterString;
|
|---|
| 345 | CVF_Context* cvfCont;
|
|---|
| 346 | CVF_Video* cvfInVideo;
|
|---|
| 347 | CVF_Video* cvfOutVideo;
|
|---|
| 348 | CVF_Frame* cvfInFrame;
|
|---|
| 349 | CVF_Frame* cvfOutFrame;
|
|---|
| 350 | CFMutableArrayRef cvfSourceArray;
|
|---|
| 351 | #endif
|
|---|
| 352 | } lavcEncoderGlobalRecord, *lavcEncoderGlobals;
|
|---|
| 353 |
|
|---|
| 354 |
|
|---|
| 355 | #pragma mark -
|
|---|
| 356 | #pragma mark Component requirements
|
|---|
| 357 |
|
|---|
| 358 |
|
|---|
| 359 | // Setup required for ComponentDispatchHelper.c
|
|---|
| 360 | #define IMAGECODEC_BASENAME() lavcEncoder_
|
|---|
| 361 | #define IMAGECODEC_GLOBALS() lavcEncoderGlobals storage
|
|---|
| 362 |
|
|---|
| 363 | #define CALLCOMPONENT_BASENAME() IMAGECODEC_BASENAME()
|
|---|
| 364 | #define CALLCOMPONENT_GLOBALS() IMAGECODEC_GLOBALS()
|
|---|
| 365 |
|
|---|
| 366 | #define QT_BASENAME() CALLCOMPONENT_BASENAME()
|
|---|
| 367 | #define QT_GLOBALS() CALLCOMPONENT_GLOBALS()
|
|---|
| 368 |
|
|---|
| 369 | #define COMPONENT_UPP_PREFIX() uppImageCodec
|
|---|
| 370 | #define COMPONENT_DISPATCH_FILE kDispatchFile
|
|---|
| 371 | #define COMPONENT_SELECT_PREFIX() kImageCodec
|
|---|
| 372 |
|
|---|
| 373 |
|
|---|
| 374 | // Include Component Dispatch Macros and others
|
|---|
| 375 | #include <CoreServices/Components.k.h>
|
|---|
| 376 | #include <QuickTime/ImageCodec.k.h>
|
|---|
| 377 | #include <QuickTime/ImageCompression.k.h>
|
|---|
| 378 | #include <QuickTime/ComponentDispatchHelper.c>
|
|---|
| 379 |
|
|---|
| 380 |
|
|---|
| 381 | #pragma mark -
|
|---|
| 382 | #pragma mark UIbundle Prototypes
|
|---|
| 383 |
|
|---|
| 384 |
|
|---|
| 385 | typedef void (*InitializeNibProc)();
|
|---|
| 386 | typedef void (*SetFourCCProc)(CFStringRef fourCC);
|
|---|
| 387 | typedef void (*SetBundleIDProc)(CFStringRef newBundleID);
|
|---|
| 388 | typedef params* (*ShowDialogProc)(params* inParams);
|
|---|
| 389 | typedef void (*ReleaseNibProc)();
|
|---|
| 390 | typedef void (*InitializeCocoaProc)();
|
|---|
| 391 | InitializeNibProc uiInitializeNib;
|
|---|
| 392 | SetFourCCProc uiSetFourCC;
|
|---|
| 393 | SetBundleIDProc uiSetBundleID;
|
|---|
| 394 | ShowDialogProc uiShowDialog;
|
|---|
| 395 | ReleaseNibProc uiReleaseNib;
|
|---|
| 396 | InitializeCocoaProc uiInitializeCocoa;
|
|---|
| 397 |
|
|---|
| 398 |
|
|---|
| 399 | #pragma mark -
|
|---|
| 400 | #pragma mark Prototypes
|
|---|
| 401 |
|
|---|
| 402 |
|
|---|
| 403 | static OSStatus setup_codecCont(lavcEncoderGlobalRecord *glob);
|
|---|
| 404 | static OSStatus open_libAV(lavcEncoderGlobalRecord *glob);
|
|---|
| 405 | static OSStatus process_libAV(lavcEncoderGlobalRecord *glob, ICMCompressorSourceFrameRef source_frame);
|
|---|
| 406 | static OSStatus emitFrameData(lavcEncoderGlobalRecord *glob);
|
|---|
| 407 |
|
|---|
| 408 | static OSStatus createPixelBufferAttributesDictionary( lavcEncoderGlobalRecord *glob,
|
|---|
| 409 | const OSType *pixelFormatList, int pixelFormatCount, CFMutableDictionaryRef *pixelBufferAttributesOut );
|
|---|
| 410 |
|
|---|
| 411 | static ICMCompressorSourceFrameRef getSourceFrameForEncodedFrame(lavcEncoderGlobalRecord *glob);
|
|---|
| 412 | static Boolean removeSourceFrame(lavcEncoderGlobalRecord *glob, ICMCompressorSourceFrameRef source_frame);
|
|---|
| 413 | static Boolean doesQueueContainEarlierDisplayNumbers( lavcEncoderGlobalRecord *glob, long display_number );
|
|---|
| 414 | static Boolean removeSourceFrameForEncodedFrame( lavcEncoderGlobalRecord *glob );
|
|---|
| 415 |
|
|---|
| 416 | static Handle avcCExtension( lavcEncoderGlobalRecord *glob );
|
|---|
| 417 | static Handle esdsExtension( lavcEncoderGlobalRecord *glob );
|
|---|
| 418 | static OSStatus prepareImageDescriptionExtensions(lavcEncoderGlobalRecord *glob);
|
|---|
| 419 |
|
|---|
| 420 | static void logInfo(lavcEncoderGlobalRecord *glob, char* fmt, ...);
|
|---|
| 421 | static void logDebug(lavcEncoderGlobalRecord *glob, char* fmt, ...);
|
|---|
| 422 |
|
|---|
| 423 | static OSStatus openCoreVF( lavcEncoderGlobals glob );
|
|---|
| 424 | static OSStatus closeCoreVF( lavcEncoderGlobals glob );
|
|---|
| 425 |
|
|---|
| 426 | static void checkValues( lavcEncoderGlobals glob );
|
|---|
| 427 | static void initValues( lavcEncoderGlobals glob );
|
|---|
| 428 |
|
|---|
| 429 |
|
|---|
| 430 | #pragma mark -
|
|---|
| 431 | #pragma mark Standard Component Call handler
|
|---|
| 432 |
|
|---|
| 433 |
|
|---|
| 434 | // StdComponentCall (Target) // 2
|
|---|
| 435 | ComponentResult lavcEncoder_Target(lavcEncoderGlobalRecord *glob, ComponentInstance target)
|
|---|
| 436 | {
|
|---|
| 437 | // logDebug(NULL, "lavcEncoder: [%08x %s]\n", glob, __FUNCTION__);
|
|---|
| 438 |
|
|---|
| 439 | glob->target = target;
|
|---|
| 440 | return noErr;
|
|---|
| 441 | }
|
|---|
| 442 |
|
|---|
| 443 |
|
|---|
| 444 | // StdComponentCall (Version) // 4
|
|---|
| 445 | ComponentResult lavcEncoder_Version(lavcEncoderGlobalRecord *glob)
|
|---|
| 446 | {
|
|---|
| 447 | // logDebug(NULL, "lavcEncoder: [%08x %s]\n", glob, __FUNCTION__);
|
|---|
| 448 |
|
|---|
| 449 | return klavcEncoderVersion;
|
|---|
| 450 | }
|
|---|
| 451 |
|
|---|
| 452 |
|
|---|
| 453 | // StdComponentCall (CanDo) // 5
|
|---|
| 454 | // ...missing???
|
|---|
| 455 |
|
|---|
| 456 |
|
|---|
| 457 | // StdComponentCall (Close) // 6
|
|---|
| 458 | ComponentResult lavcEncoder_Close(lavcEncoderGlobalRecord *glob, ComponentInstance self)
|
|---|
| 459 | {
|
|---|
| 460 | // logDebug(NULL, "lavcEncoder: [%08x %s]\n", glob, __FUNCTION__);
|
|---|
| 461 |
|
|---|
| 462 | if (glob) {
|
|---|
| 463 | #if REMOVELOG
|
|---|
| 464 | if( glob->params_opaque.log_file_path && strlen(glob->params_opaque.log_file_path) > 0 ) {
|
|---|
| 465 | int ret = noErr;
|
|---|
| 466 |
|
|---|
| 467 | char* path = NULL;
|
|---|
| 468 | char* suffix = NULL;
|
|---|
| 469 | int size = 0;
|
|---|
| 470 |
|
|---|
| 471 | ret = remove(glob->params_opaque.log_file_path);
|
|---|
| 472 | if( ret && errno != ENOENT )
|
|---|
| 473 | fprintf(stderr, "(%s) removal failed.(%d)\n", glob->params_opaque.log_file_path, ret);
|
|---|
| 474 |
|
|---|
| 475 | suffix = ".mbtree";
|
|---|
| 476 | size = 1 + strlen(suffix) + strlen(glob->params_opaque.log_file_path);
|
|---|
| 477 | if( (path = calloc(1, size)) ) {
|
|---|
| 478 | snprintf(path, size, "%s%s", glob->params_opaque.log_file_path, suffix);
|
|---|
| 479 | ret = remove(path);
|
|---|
| 480 | if( ret && errno != ENOENT )
|
|---|
| 481 | fprintf(stderr, "(%s) removal failed.(%d)\n", path, ret);
|
|---|
| 482 | free(path);
|
|---|
| 483 | }
|
|---|
| 484 |
|
|---|
| 485 | suffix = ".temp";
|
|---|
| 486 | size = 1 + strlen(suffix) + strlen(glob->params_opaque.log_file_path);
|
|---|
| 487 | if( (path = calloc(1, size)) ) {
|
|---|
| 488 | snprintf(path, size, "%s%s", glob->params_opaque.log_file_path, suffix);
|
|---|
| 489 | ret = remove(path);
|
|---|
| 490 | if( ret && errno != ENOENT )
|
|---|
| 491 | fprintf(stderr, "(%s) removal failed.(%d)\n", path, ret);
|
|---|
| 492 | free(path);
|
|---|
| 493 | }
|
|---|
| 494 |
|
|---|
| 495 | suffix = ".mbtree.temp";
|
|---|
| 496 | size = 1 + strlen(suffix) + strlen(glob->params_opaque.log_file_path);
|
|---|
| 497 | if( (path = calloc(1, size)) ) {
|
|---|
| 498 | snprintf(path, size, "%s%s", glob->params_opaque.log_file_path, suffix);
|
|---|
| 499 | ret = remove(path);
|
|---|
| 500 | if( ret && errno != ENOENT )
|
|---|
| 501 | fprintf(stderr, "(%s) removal failed.(%d)\n", path, ret);
|
|---|
| 502 | free(path);
|
|---|
| 503 | }
|
|---|
| 504 |
|
|---|
| 505 | // release path string buffer
|
|---|
| 506 | free(glob->params_opaque.log_file_path);
|
|---|
| 507 | glob->params_opaque.log_file_path = NULL;
|
|---|
| 508 | }
|
|---|
| 509 | #endif
|
|---|
| 510 |
|
|---|
| 511 | // Clean up
|
|---|
| 512 | if( glob->codecCont ) {
|
|---|
| 513 | if( glob->codec_is_opened ) {
|
|---|
| 514 | avcodec_close( glob->codecCont );
|
|---|
| 515 | glob->codec_is_opened = FALSE;
|
|---|
| 516 | glob->extraDataReady = FALSE;
|
|---|
| 517 | }
|
|---|
| 518 |
|
|---|
| 519 | #if USECoreVF
|
|---|
| 520 | if( glob->cvfCont ) closeCoreVF( glob );
|
|---|
| 521 | #endif
|
|---|
| 522 |
|
|---|
| 523 | if( glob->encode_buffer ) {
|
|---|
| 524 | free( glob->encode_buffer );
|
|---|
| 525 | glob->encode_buffer = NULL;
|
|---|
| 526 | }
|
|---|
| 527 | if( glob->planer_buffer ) {
|
|---|
| 528 | av_free( glob->planer_buffer );
|
|---|
| 529 | glob->planer_buffer = NULL;
|
|---|
| 530 | }
|
|---|
| 531 |
|
|---|
| 532 | if( glob->frame ) {
|
|---|
| 533 | av_free( glob->frame );
|
|---|
| 534 | glob->frame = NULL;
|
|---|
| 535 | }
|
|---|
| 536 |
|
|---|
| 537 | av_free( glob->codecCont );
|
|---|
| 538 | glob->codecCont = NULL;
|
|---|
| 539 | }
|
|---|
| 540 |
|
|---|
| 541 | //
|
|---|
| 542 | if (glob->array_source_frame) {
|
|---|
| 543 | CFArrayRemoveAllValues(glob->array_source_frame);
|
|---|
| 544 | CFRelease(glob->array_source_frame);
|
|---|
| 545 | glob->array_source_frame = NULL;
|
|---|
| 546 | }
|
|---|
| 547 |
|
|---|
| 548 | if( glob->sessionOptions ) {
|
|---|
| 549 | ICMCompressionSessionOptionsRelease( glob->sessionOptions );
|
|---|
| 550 | glob->sessionOptions = NULL;
|
|---|
| 551 | }
|
|---|
| 552 |
|
|---|
| 553 | //
|
|---|
| 554 | if( glob->initialDate && glob->frame_count > 1) {
|
|---|
| 555 | CFDateRef lastDate = CFDateCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent());
|
|---|
| 556 | CFTimeInterval diff = CFDateGetTimeIntervalSinceDate(lastDate, glob->initialDate);
|
|---|
| 557 | logInfo(glob, "lavcEncoder: - Total time: %.1f sec.\n", diff);
|
|---|
| 558 | CFRelease(lastDate);
|
|---|
| 559 |
|
|---|
| 560 | CFRelease(glob->initialDate);
|
|---|
| 561 | glob->initialDate = NULL;
|
|---|
| 562 | }
|
|---|
| 563 |
|
|---|
| 564 | // Release Component Instance Storage
|
|---|
| 565 | free(glob);
|
|---|
| 566 | }
|
|---|
| 567 |
|
|---|
| 568 | // Exit with no error
|
|---|
| 569 | return noErr;
|
|---|
| 570 | }
|
|---|
| 571 |
|
|---|
| 572 |
|
|---|
| 573 | // StdComponentCall (Open) // 7
|
|---|
| 574 | ComponentResult lavcEncoder_Open(lavcEncoderGlobalRecord *glob, ComponentInstance self)
|
|---|
| 575 | {
|
|---|
| 576 | // logDebug(NULL, "lavcEncoder: [%s]\n", __FUNCTION__);
|
|---|
| 577 |
|
|---|
| 578 | // Create Component Instance Storage
|
|---|
| 579 | glob = calloc(sizeof(lavcEncoderGlobalRecord), 1);
|
|---|
| 580 | if (!glob)
|
|---|
| 581 | return memFullErr;
|
|---|
| 582 |
|
|---|
| 583 | // logDebug(NULL, "lavcEncoder: [%08x %s]\n", glob, __FUNCTION__);
|
|---|
| 584 |
|
|---|
| 585 | SetComponentInstanceStorage(self, (Handle)glob);
|
|---|
| 586 |
|
|---|
| 587 | // Set Initial Instance
|
|---|
| 588 | glob->self = self;
|
|---|
| 589 | glob->target = self;
|
|---|
| 590 |
|
|---|
| 591 | //
|
|---|
| 592 | glob->ICM_passcount = -1;
|
|---|
| 593 |
|
|---|
| 594 | //
|
|---|
| 595 | initValues(glob);
|
|---|
| 596 |
|
|---|
| 597 | return noErr;
|
|---|
| 598 | }
|
|---|
| 599 |
|
|---|
| 600 |
|
|---|
| 601 | #pragma mark -
|
|---|
| 602 | #pragma mark Component Call handler
|
|---|
| 603 |
|
|---|
| 604 |
|
|---|
| 605 | // ComponentCall (GetCodecInfo) // 0
|
|---|
| 606 | ComponentResult lavcEncoder_GetCodecInfo(lavcEncoderGlobalRecord *glob, CodecInfo *info)
|
|---|
| 607 | {
|
|---|
| 608 | // logDebug(NULL, "lavcEncoder: [%08x %s]\n", glob, __FUNCTION__);
|
|---|
| 609 |
|
|---|
| 610 | OSErr err = noErr;
|
|---|
| 611 | CodecInfo **tempCodecInfo = NULL;
|
|---|
| 612 |
|
|---|
| 613 | if (info == NULL) {
|
|---|
| 614 | err = paramErr;
|
|---|
| 615 | } else {
|
|---|
| 616 | err = GetComponentResource((Component)glob->self, codecInfoResourceType, 256, (Handle *)&tempCodecInfo);
|
|---|
| 617 | if (err == noErr) {
|
|---|
| 618 | *info = **tempCodecInfo;
|
|---|
| 619 | DisposeHandle((Handle)tempCodecInfo);
|
|---|
| 620 | }
|
|---|
| 621 | }
|
|---|
| 622 |
|
|---|
| 623 | return err;
|
|---|
| 624 | }
|
|---|
| 625 |
|
|---|
| 626 |
|
|---|
| 627 | // ComponentCall (GetMaxCompressionSize) // 2
|
|---|
| 628 | ComponentResult lavcEncoder_GetMaxCompressionSize(lavcEncoderGlobalRecord *glob,
|
|---|
| 629 | PixMapHandle src, const Rect *srcRect, short depth, CodecQ quality, long *size)
|
|---|
| 630 | {
|
|---|
| 631 | // logDebug(NULL, "lavcEncoder: [%08x %s]\n", glob, __FUNCTION__);
|
|---|
| 632 |
|
|---|
| 633 | if( !size ) {
|
|---|
| 634 | fprintf(stderr, "ERROR: No size location given.\n");
|
|---|
| 635 | return paramErr;
|
|---|
| 636 | }
|
|---|
| 637 |
|
|---|
| 638 | *size = (srcRect->right - srcRect->left) * (srcRect->bottom - srcRect->top) * 4;
|
|---|
| 639 |
|
|---|
| 640 | return noErr;
|
|---|
| 641 | }
|
|---|
| 642 |
|
|---|
| 643 |
|
|---|
| 644 | #pragma mark -
|
|---|
| 645 |
|
|---|
| 646 |
|
|---|
| 647 | // ComponentCall (RequestSettings) // 11
|
|---|
| 648 | ComponentResult lavcEncoder_RequestSettings(lavcEncoderGlobalRecord *glob,
|
|---|
| 649 | Handle settings, Rect *rp, ModalFilterUPP filter_proc)
|
|---|
| 650 | {
|
|---|
| 651 | // logDebug(NULL, "lavcEncoder: [%08x %s]\n", glob, __FUNCTION__);
|
|---|
| 652 |
|
|---|
| 653 | // Check for glob-struct update (safty)
|
|---|
| 654 | checkValues(glob);
|
|---|
| 655 |
|
|---|
| 656 | // Prepare UIbundle Reference
|
|---|
| 657 | CFBundleRef baseBundleRef = NULL, uiBundleRef = NULL;
|
|---|
| 658 | CFURLRef baseBundleURL = NULL, uiBundleURL = NULL;
|
|---|
| 659 |
|
|---|
| 660 | baseBundleRef = CFBundleGetBundleWithIdentifier(CFSTR(kBundleIdentifier));
|
|---|
| 661 | if(baseBundleRef) {
|
|---|
| 662 | baseBundleURL = CFBundleCopyPrivateFrameworksURL( baseBundleRef );
|
|---|
| 663 | if(baseBundleURL) {
|
|---|
| 664 | uiBundleURL = CFURLCreateCopyAppendingPathComponent( kCFAllocatorDefault, baseBundleURL, CFSTR("UIbundle.bundle"), false );
|
|---|
| 665 | if(uiBundleURL) {
|
|---|
| 666 | uiBundleRef = CFBundleCreate( kCFAllocatorDefault, uiBundleURL );
|
|---|
| 667 | CFRelease(uiBundleURL);
|
|---|
| 668 | uiBundleURL = NULL;
|
|---|
| 669 | }
|
|---|
| 670 | CFRelease(baseBundleURL);
|
|---|
| 671 | baseBundleURL = NULL;
|
|---|
| 672 | }
|
|---|
| 673 | }
|
|---|
| 674 |
|
|---|
| 675 | // Show dialog
|
|---|
| 676 | if ( uiBundleRef ) {
|
|---|
| 677 | // Get Function pointers
|
|---|
| 678 | uiInitializeNib = (InitializeNibProc)CFBundleGetFunctionPointerForName(uiBundleRef, CFSTR("InitializeNib"));
|
|---|
| 679 | uiSetFourCC = (SetFourCCProc)CFBundleGetFunctionPointerForName(uiBundleRef, CFSTR("SetFourCC"));
|
|---|
| 680 | uiSetBundleID = (SetBundleIDProc)CFBundleGetFunctionPointerForName(uiBundleRef, CFSTR("SetBundleID"));
|
|---|
| 681 | uiShowDialog = (ShowDialogProc)CFBundleGetFunctionPointerForName(uiBundleRef, CFSTR("ShowDialog"));
|
|---|
| 682 | uiReleaseNib = (ReleaseNibProc)CFBundleGetFunctionPointerForName(uiBundleRef, CFSTR("ReleaseNib"));
|
|---|
| 683 | uiInitializeCocoa = (InitializeCocoaProc)CFBundleGetFunctionPointerForName(uiBundleRef, CFSTR("InitializeCocoa"));
|
|---|
| 684 |
|
|---|
| 685 | // Check if something corrupted
|
|---|
| 686 | assert(uiInitializeNib);
|
|---|
| 687 | assert(uiSetFourCC);
|
|---|
| 688 | assert(uiSetBundleID);
|
|---|
| 689 | assert(uiShowDialog);
|
|---|
| 690 | assert(uiReleaseNib);
|
|---|
| 691 | assert(uiInitializeCocoa);
|
|---|
| 692 |
|
|---|
| 693 | // Initialize Cocoa
|
|---|
| 694 | uiInitializeCocoa();
|
|---|
| 695 |
|
|---|
| 696 | // Initialize controller
|
|---|
| 697 | uiInitializeNib();
|
|---|
| 698 | uiSetFourCC(CFSTR(kCodec_FormatType));
|
|---|
| 699 | uiSetBundleID(CFSTR(kBundleIdentifier));
|
|---|
| 700 |
|
|---|
| 701 | // Copy supplied setting into glob
|
|---|
| 702 | lavcEncoder_SetSettings(glob, settings);
|
|---|
| 703 |
|
|---|
| 704 | // Call UIbundle
|
|---|
| 705 | params* outParamsPtr = uiShowDialog(&glob->params);
|
|---|
| 706 |
|
|---|
| 707 | // Get result settings
|
|---|
| 708 | if(outParamsPtr)
|
|---|
| 709 | glob->params = *outParamsPtr;
|
|---|
| 710 |
|
|---|
| 711 | // Release controller
|
|---|
| 712 | uiReleaseNib();
|
|---|
| 713 |
|
|---|
| 714 | // Release UIBundle CFBundleRef
|
|---|
| 715 | CFRelease( uiBundleRef );
|
|---|
| 716 | } else {
|
|---|
| 717 | AudioServicesPlayAlertSound(kUserPreferredAlert);
|
|---|
| 718 | fprintf(stderr, "ERROR: Failed to load UIbundle.");
|
|---|
| 719 | }
|
|---|
| 720 |
|
|---|
| 721 | //
|
|---|
| 722 | lavcEncoder_GetSettings(glob, settings);
|
|---|
| 723 |
|
|---|
| 724 | return noErr;
|
|---|
| 725 | } // ComponentCall (RequestSettings)
|
|---|
| 726 |
|
|---|
| 727 |
|
|---|
| 728 | // ComponentCall (GetSettings) // 12
|
|---|
| 729 | ComponentResult lavcEncoder_GetSettings(lavcEncoderGlobalRecord *glob, Handle settings)
|
|---|
| 730 | {
|
|---|
| 731 | // logDebug(NULL, "lavcEncoder: [%08x %s]\n", glob, __FUNCTION__);
|
|---|
| 732 |
|
|---|
| 733 | // Check for glob-struct update
|
|---|
| 734 | checkValues(glob);
|
|---|
| 735 |
|
|---|
| 736 | SetHandleSize(settings, sizeof(glob->params));
|
|---|
| 737 | memcpy(*settings, &glob->params, sizeof(glob->params)); // write out
|
|---|
| 738 |
|
|---|
| 739 | // Endian handler
|
|---|
| 740 | params *p = (params*)*settings;
|
|---|
| 741 | p->REV_STRUCT = REV_X264OPENGOP; // 1.2.13 or later.
|
|---|
| 742 |
|
|---|
| 743 | p->SC_THRESHOLD = EndianS32_NtoB(p->SC_THRESHOLD);
|
|---|
| 744 | p->QCOMPRESS = EndianS32_NtoB(p->QCOMPRESS);
|
|---|
| 745 | p->NOISE_REDUCTION = EndianS32_NtoB(p->NOISE_REDUCTION);
|
|---|
| 746 | p->RC_MAXRATE = EndianS32_NtoB(p->RC_MAXRATE);
|
|---|
| 747 | p->RC_BUFSIZE = EndianS32_NtoB(p->RC_BUFSIZE);
|
|---|
| 748 | p->AQ_STRENGTH = EndianS32_NtoB(p->AQ_STRENGTH);
|
|---|
| 749 | p->PSYRD_RDO = EndianS32_NtoB(p->PSYRD_RDO);
|
|---|
| 750 | p->PSYRD_TRELLIS = EndianS32_NtoB(p->PSYRD_TRELLIS);
|
|---|
| 751 | p->RC_LOOKAHEAD = EndianS32_NtoB(p->RC_LOOKAHEAD);
|
|---|
| 752 | p->IP_FACTOR = EndianS32_NtoB(p->IP_FACTOR);
|
|---|
| 753 | p->PB_FACTOR = EndianS32_NtoB(p->PB_FACTOR);
|
|---|
| 754 |
|
|---|
| 755 | p->hSpacing = EndianU32_NtoB(p->hSpacing);
|
|---|
| 756 | p->vSpacing = EndianU32_NtoB(p->vSpacing);
|
|---|
| 757 | p->cleanApertureWidthN = EndianU32_NtoB(p->cleanApertureWidthN);
|
|---|
| 758 | p->cleanApertureWidthD = EndianU32_NtoB(p->cleanApertureWidthD);
|
|---|
| 759 | p->cleanApertureHeightN = EndianU32_NtoB(p->cleanApertureHeightN);
|
|---|
| 760 | p->cleanApertureHeightD = EndianU32_NtoB(p->cleanApertureHeightD);
|
|---|
| 761 | p->horizOffN = EndianS32_NtoB(p->horizOffN);
|
|---|
| 762 | p->horizOffD = EndianU32_NtoB(p->horizOffD);
|
|---|
| 763 | p->vertOffN = EndianS32_NtoB(p->vertOffN);
|
|---|
| 764 | p->vertOffD = EndianU32_NtoB(p->vertOffD);
|
|---|
| 765 |
|
|---|
| 766 | return noErr;
|
|---|
| 767 | }
|
|---|
| 768 |
|
|---|
| 769 |
|
|---|
| 770 | // ComponentCall (SetSettings) // 13
|
|---|
| 771 | ComponentResult lavcEncoder_SetSettings(lavcEncoderGlobalRecord *glob, Handle settings)
|
|---|
| 772 | {
|
|---|
| 773 | // logDebug(NULL, "lavcEncoder: [%08x %s]\n", glob, __FUNCTION__);
|
|---|
| 774 |
|
|---|
| 775 | if( sizeof(glob->params) < GetHandleSize(settings) ) return paramErr;
|
|---|
| 776 | memcpy(&glob->params, *settings, GetHandleSize(settings)); // read in
|
|---|
| 777 |
|
|---|
| 778 | // Endian Handler
|
|---|
| 779 | params *p = &glob->params;
|
|---|
| 780 | if( !(p->QCOMPRESS <= 100 && p->QCOMPRESS >= 0 ) // Endian check
|
|---|
| 781 | ) {
|
|---|
| 782 | p->SC_THRESHOLD = EndianS32_BtoN(p->SC_THRESHOLD);
|
|---|
| 783 | p->QCOMPRESS = EndianS32_BtoN(p->QCOMPRESS);
|
|---|
| 784 | p->NOISE_REDUCTION = EndianS32_BtoN(p->NOISE_REDUCTION);
|
|---|
| 785 | p->RC_MAXRATE = EndianS32_BtoN(p->RC_MAXRATE);
|
|---|
| 786 | p->RC_BUFSIZE = EndianS32_BtoN(p->RC_BUFSIZE);
|
|---|
| 787 | p->AQ_STRENGTH = EndianS32_BtoN(p->AQ_STRENGTH);
|
|---|
| 788 | p->PSYRD_RDO = EndianS32_BtoN(p->PSYRD_RDO);
|
|---|
| 789 | p->PSYRD_TRELLIS = EndianS32_BtoN(p->PSYRD_TRELLIS);
|
|---|
| 790 | p->RC_LOOKAHEAD = EndianS32_BtoN(p->RC_LOOKAHEAD);
|
|---|
| 791 | p->IP_FACTOR = EndianS32_BtoN(p->IP_FACTOR);
|
|---|
| 792 | p->PB_FACTOR = EndianS32_BtoN(p->PB_FACTOR);
|
|---|
| 793 |
|
|---|
| 794 | p->hSpacing = EndianU32_BtoN(p->hSpacing);
|
|---|
| 795 | p->vSpacing = EndianU32_BtoN(p->vSpacing);
|
|---|
| 796 | p->cleanApertureWidthN = EndianU32_BtoN(p->cleanApertureWidthN);
|
|---|
| 797 | p->cleanApertureWidthD = EndianU32_BtoN(p->cleanApertureWidthD);
|
|---|
| 798 | p->cleanApertureHeightN = EndianU32_BtoN(p->cleanApertureHeightN);
|
|---|
| 799 | p->cleanApertureHeightD = EndianU32_BtoN(p->cleanApertureHeightD);
|
|---|
| 800 | p->horizOffN = EndianS32_BtoN(p->horizOffN);
|
|---|
| 801 | p->horizOffD = EndianU32_BtoN(p->horizOffD);
|
|---|
| 802 | p->vertOffN = EndianS32_BtoN(p->vertOffN);
|
|---|
| 803 | p->vertOffD = EndianU32_BtoN(p->vertOffD);
|
|---|
| 804 | }
|
|---|
| 805 |
|
|---|
| 806 | if(p->REV_STRUCT < REV_PSYRD) { /* 2: 0.9.0 or later */
|
|---|
| 807 | p->PSYRD_RDO = 10;
|
|---|
| 808 | p->PSYRD_TRELLIS = 0;
|
|---|
| 809 | p->AQ_MODE = ((p->AQ_MODE == 3) ? 1 : 0);
|
|---|
| 810 | }
|
|---|
| 811 | if(p->REV_STRUCT < REV_MAXQDIFF) { /* 3: 0.9.5 or later */
|
|---|
| 812 | #if X264
|
|---|
| 813 | p->MAX_QDIFF = 4;
|
|---|
| 814 | #else
|
|---|
| 815 | p->MAX_QDIFF = 3;
|
|---|
| 816 | #endif
|
|---|
| 817 | p->CHROMAOFFSET = 0;
|
|---|
| 818 | }
|
|---|
| 819 | if(p->REV_STRUCT < REV_COREVF) { /* 4: 1.0.0 or later */
|
|---|
| 820 | p->FILTERPRESET = 0;
|
|---|
| 821 | }
|
|---|
| 822 | if(p->REV_STRUCT < REV_SUBSAMPLE) { /* 5: 1.0.1 or later */
|
|---|
| 823 | p->SUBSAMPLING = 0;
|
|---|
| 824 | }
|
|---|
| 825 | if(p->REV_STRUCT < REV_X264PROFILE) { /* 6: 1.1.0 or later */
|
|---|
| 826 | p->X264PROFILE = 3;
|
|---|
| 827 | p->X264PRESET = 0;
|
|---|
| 828 | p->X264TUNE = 0;
|
|---|
| 829 | }
|
|---|
| 830 | if(p->REV_STRUCT < REV_MBTREE) { /* 7: 1.1.2 or later */
|
|---|
| 831 | #if X264
|
|---|
| 832 | p->MBTREE = 1;
|
|---|
| 833 | p->PSY = 1;
|
|---|
| 834 | p->RC_LOOKAHEAD = 40;
|
|---|
| 835 | p->IP_FACTOR = 140;
|
|---|
| 836 | p->PB_FACTOR = 130;
|
|---|
| 837 | #endif
|
|---|
| 838 | #if MPEG4
|
|---|
| 839 | p->MBTREE = 0;
|
|---|
| 840 | p->PSY = 0;
|
|---|
| 841 | p->RC_LOOKAHEAD = 0;
|
|---|
| 842 | p->IP_FACTOR = 125;
|
|---|
| 843 | p->PB_FACTOR = 125;
|
|---|
| 844 | #endif
|
|---|
| 845 | #if XVID
|
|---|
| 846 | p->MBTREE = 0;
|
|---|
| 847 | p->PSY = 0;
|
|---|
| 848 | p->RC_LOOKAHEAD = 0;
|
|---|
| 849 | p->IP_FACTOR = 125;
|
|---|
| 850 | p->PB_FACTOR = 150;
|
|---|
| 851 | #endif
|
|---|
| 852 | }
|
|---|
| 853 | if(p->REV_STRUCT < REV_WEIGHTP) { /* 8: 1.1.8 or later */
|
|---|
| 854 | #if X264
|
|---|
| 855 | p->WEIGHTP = 3;
|
|---|
| 856 | #else
|
|---|
| 857 | p->WEIGHTP = 1;
|
|---|
| 858 | #endif
|
|---|
| 859 | }
|
|---|
| 860 | if(p->REV_STRUCT < REV_FLAG2_MBTREE) { /* 9: 1.1.10 or later */
|
|---|
| 861 | p->FLAG2_MBTREE = p->MBTREE; // Copy old param to new param (used under 1.1.2-1.1.9)
|
|---|
| 862 | }
|
|---|
| 863 | if(p->REV_STRUCT < REV_INTERLACED) { /* 10: 1.2.0 or later */
|
|---|
| 864 | p->FLAG_INTERLACED_DCT = 0;
|
|---|
| 865 | p->TOPFIELDFIRST = 0;
|
|---|
| 866 | p->LOSSLESS = 0;
|
|---|
| 867 | p->USEASPECTRATIO = 0;
|
|---|
| 868 | p->USECLEANAPERTURE = 0;
|
|---|
| 869 | p->TAGASPECTRATIO = 0;
|
|---|
| 870 | p->TAGCLEANAPERTURE = 0;
|
|---|
| 871 | p->hSpacing = 1; // Square pixel
|
|---|
| 872 | p->vSpacing = 1; // Square pixel
|
|---|
| 873 | p->cleanApertureWidthN = 0; // undefined
|
|---|
| 874 | p->cleanApertureWidthD = 1; // equal denomiter
|
|---|
| 875 | p->cleanApertureHeightN = 0; // undefined
|
|---|
| 876 | p->cleanApertureHeightD = 1; // equal denomiter
|
|---|
| 877 | p->horizOffN = 0; // no offset
|
|---|
| 878 | p->horizOffD = 1; // equal denomiter
|
|---|
| 879 | p->vertOffN = 0; // no offset
|
|---|
| 880 | p->vertOffD = 1; // equal denomiter
|
|---|
| 881 | }
|
|---|
| 882 | if(p->REV_STRUCT < REV_FLAG2_PSY) { /* 11: 1.2.3 or later */
|
|---|
| 883 | p->FLAG2_PSY = p->PSY; // Copy old param to new param (used under 1.1.2-1.2.2)
|
|---|
| 884 | p->BD_TUNE = 0;
|
|---|
| 885 | }
|
|---|
| 886 | if(p->REV_STRUCT < REV_LEVELFREE) { /* 12: 1.2.7 or later */
|
|---|
| 887 | switch( p->LEVEL ) {
|
|---|
| 888 | case 1:
|
|---|
| 889 | p->LEVEL = 13;
|
|---|
| 890 | break;
|
|---|
| 891 | case 2:
|
|---|
| 892 | p->LEVEL = 21;
|
|---|
| 893 | break;
|
|---|
| 894 | case 3:
|
|---|
| 895 | p->LEVEL = 30;
|
|---|
| 896 | break;
|
|---|
| 897 | case 4:
|
|---|
| 898 | p->LEVEL = 31;
|
|---|
| 899 | break;
|
|---|
| 900 | case 5:
|
|---|
| 901 | p->LEVEL = 41;
|
|---|
| 902 | break;
|
|---|
| 903 | case 6:
|
|---|
| 904 | p->LEVEL = 51;
|
|---|
| 905 | break;
|
|---|
| 906 | case 9:
|
|---|
| 907 | default:
|
|---|
| 908 | p->LEVEL = 9;
|
|---|
| 909 | break;
|
|---|
| 910 | }
|
|---|
| 911 | }
|
|---|
| 912 | if(p->REV_STRUCT < REV_IGNOREQSLIDER) { /* 13: 1.2.8 or later */
|
|---|
| 913 | #if X264
|
|---|
| 914 | p->OVERRIDECRFQSCALE = 0;
|
|---|
| 915 | p->USERCRFQSCALE = 23;
|
|---|
| 916 | p->OVERRIDEQMIN = 1;
|
|---|
| 917 | p->USERQMIN = 0; // x264 r1795 changed default qmin from 10 to 0
|
|---|
| 918 | #endif
|
|---|
| 919 | #if MPEG4
|
|---|
| 920 | p->OVERRIDECRFQSCALE = 0;
|
|---|
| 921 | p->USERCRFQSCALE = 2;
|
|---|
| 922 | p->OVERRIDEQMIN = 0;
|
|---|
| 923 | p->USERQMIN = 2;
|
|---|
| 924 | #endif
|
|---|
| 925 | #if XVID
|
|---|
| 926 | p->OVERRIDECRFQSCALE = 0;
|
|---|
| 927 | p->USERCRFQSCALE = 2;
|
|---|
| 928 | p->OVERRIDEQMIN = 0;
|
|---|
| 929 | p->USERQMIN = 2;
|
|---|
| 930 | #endif
|
|---|
| 931 | }
|
|---|
| 932 | if(p->REV_STRUCT < REV_FAKEINTERLACED) { /* 14: 1.2.9 or later */
|
|---|
| 933 | p->FAKEINTERLACED = 0;
|
|---|
| 934 | }
|
|---|
| 935 | #if X264
|
|---|
| 936 | if(p->REV_STRUCT < REV_X264OPENGOP) { /* 15: 1.2.13 or later*/
|
|---|
| 937 | p->FLAG_CLOSED_GOP = TRUE;
|
|---|
| 938 | }
|
|---|
| 939 | #endif
|
|---|
| 940 |
|
|---|
| 941 | // Check for glob-struct update
|
|---|
| 942 | checkValues(glob);
|
|---|
| 943 |
|
|---|
| 944 | #if USECoreVF
|
|---|
| 945 | CFStringRef appID = CFSTR("com.MyCometG3.CoreVF");
|
|---|
| 946 | CFPreferencesAppSynchronize(appID);
|
|---|
| 947 | #endif
|
|---|
| 948 | return noErr;
|
|---|
| 949 | }
|
|---|
| 950 |
|
|---|
| 951 |
|
|---|
| 952 | #pragma mark -
|
|---|
| 953 |
|
|---|
| 954 |
|
|---|
| 955 | // ComponentCall (PrepareToCompressFrames) // 55
|
|---|
| 956 | ComponentResult lavcEncoder_PrepareToCompressFrames(lavcEncoderGlobalRecord *glob,
|
|---|
| 957 | ICMCompressorSessionRef session,
|
|---|
| 958 | ICMCompressionSessionOptionsRef session_options,
|
|---|
| 959 | ImageDescriptionHandle image_description,
|
|---|
| 960 | void *reserved,
|
|---|
| 961 | CFDictionaryRef *compressor_pixel_buffer_attributes_out)
|
|---|
| 962 | {
|
|---|
| 963 | logDebug(glob, "lavcEncoder: [%08x %s]\n", glob, __FUNCTION__);
|
|---|
| 964 |
|
|---|
| 965 | ComponentResult err = noErr;
|
|---|
| 966 |
|
|---|
| 967 | {
|
|---|
| 968 | glob->meetsErr = FALSE;
|
|---|
| 969 |
|
|---|
| 970 | // ICMCompressionSession and SessionOptions handling
|
|---|
| 971 | glob->session = session;
|
|---|
| 972 |
|
|---|
| 973 | //
|
|---|
| 974 | if( glob->sessionOptions )
|
|---|
| 975 | ICMCompressionSessionOptionsRelease( glob->sessionOptions );
|
|---|
| 976 | glob->sessionOptions = session_options;
|
|---|
| 977 | ICMCompressionSessionOptionsRetain(glob->sessionOptions);
|
|---|
| 978 |
|
|---|
| 979 | // Create source frames array
|
|---|
| 980 | if (glob->array_source_frame) {
|
|---|
| 981 | CFArrayRemoveAllValues(glob->array_source_frame);
|
|---|
| 982 | CFRelease(glob->array_source_frame);
|
|---|
| 983 | }
|
|---|
| 984 | glob->array_source_frame = CFArrayCreateMutable(NULL, kMaxSourceFrame, &kCFTypeArrayCallBacks);
|
|---|
| 985 | // This array_source_frame will be released at Close()
|
|---|
| 986 |
|
|---|
| 987 | /* ==================================== */
|
|---|
| 988 |
|
|---|
| 989 | // Reserve ImageDescriptionHandle to be able to modify later
|
|---|
| 990 | glob->imageDescription = image_description;
|
|---|
| 991 |
|
|---|
| 992 | // Update FourCC code as preffered one
|
|---|
| 993 | (*image_description)->cType = kCodec_cType;
|
|---|
| 994 |
|
|---|
| 995 | // Prepare rectangles prior to build attributes dictionary
|
|---|
| 996 | glob->width = (*image_description)->width;
|
|---|
| 997 | glob->height = (*image_description)->height;
|
|---|
| 998 |
|
|---|
| 999 | glob->widthRoundedUp = roundUpToMultipleOf16( glob->width ); // Macroblock width is 16
|
|---|
| 1000 | glob->heightRoundedUp = roundUpToMultipleOf16( glob->height ); // Macroblock height is 16
|
|---|
| 1001 |
|
|---|
| 1002 | // Prepare two flags prior to build attributes dictionary
|
|---|
| 1003 | glob->add_gamma = glob->params.GAMMA;
|
|---|
| 1004 | glob->add_nclc = ( glob->params.NCLC > 2 );
|
|---|
| 1005 |
|
|---|
| 1006 | #if X264
|
|---|
| 1007 | // Install uuid atom or not
|
|---|
| 1008 | glob->add_uuid = glob->params.EMBEDUUID;
|
|---|
| 1009 | #endif
|
|---|
| 1010 |
|
|---|
| 1011 | /* ==================================== */
|
|---|
| 1012 |
|
|---|
| 1013 | // Create a pixel buffer attributes dictionary
|
|---|
| 1014 | OSType pixelFormatList[] = { k422YpCbCr8PixelFormat };
|
|---|
| 1015 | CFMutableDictionaryRef compressorPixelBufferAttributes = NULL;
|
|---|
| 1016 |
|
|---|
| 1017 | err = createPixelBufferAttributesDictionary( glob,
|
|---|
| 1018 | pixelFormatList, sizeof(pixelFormatList) / sizeof(OSType),
|
|---|
| 1019 | &compressorPixelBufferAttributes );
|
|---|
| 1020 | if( err || !compressorPixelBufferAttributes ) {
|
|---|
| 1021 | fprintf(stderr, "ERROR: createPixelBufferAttributesDictionary() failed.\n");
|
|---|
| 1022 | err = paramErr;
|
|---|
| 1023 | goto bail;
|
|---|
| 1024 | }
|
|---|
| 1025 | *compressor_pixel_buffer_attributes_out = compressorPixelBufferAttributes;
|
|---|
| 1026 | // Returned CFDictionaryRef will be released by ICM later
|
|---|
| 1027 |
|
|---|
| 1028 | /* ==================================== */
|
|---|
| 1029 |
|
|---|
| 1030 | // Setup ImageDescription Extensions like esds
|
|---|
| 1031 | err = prepareImageDescriptionExtensions(glob);
|
|---|
| 1032 | if(err) goto bail;
|
|---|
| 1033 | }
|
|---|
| 1034 |
|
|---|
| 1035 | /* ================================================================================= */
|
|---|
| 1036 |
|
|---|
| 1037 | if( glob->ICM_passcount == -1 ) {
|
|---|
| 1038 | // Benchmark
|
|---|
| 1039 | glob->initialDate = CFDateCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent());
|
|---|
| 1040 |
|
|---|
| 1041 | /* ==================================== */
|
|---|
| 1042 |
|
|---|
| 1043 | // Initialize libavcodec
|
|---|
| 1044 | //avcodec_init();
|
|---|
| 1045 | avcodec_register_all();
|
|---|
| 1046 |
|
|---|
| 1047 | // Check codec
|
|---|
| 1048 | glob->codec = avcodec_find_encoder(kCodecID);
|
|---|
| 1049 | if( !glob->codec ) {
|
|---|
| 1050 | fprintf(stderr, "ERROR: Codec not found\n");
|
|---|
| 1051 | err = paramErr;
|
|---|
| 1052 | goto bail;
|
|---|
| 1053 | }
|
|---|
| 1054 |
|
|---|
| 1055 | /* ==================================== */
|
|---|
| 1056 |
|
|---|
| 1057 | // Prepare log file path
|
|---|
| 1058 | glob->logfile = NULL;
|
|---|
| 1059 | FSRef temp_folder;
|
|---|
| 1060 |
|
|---|
| 1061 | err = FSFindFolder( kOnAppropriateDisk, kTemporaryFolderType, TRUE, &temp_folder );
|
|---|
| 1062 | if( !err ) {
|
|---|
| 1063 | CFURLRef temp_folder_URL = NULL;
|
|---|
| 1064 | CFStringRef temp_folder_path = NULL;
|
|---|
| 1065 | CFStringRef log_file_path_raw = NULL;
|
|---|
| 1066 |
|
|---|
| 1067 | srandom( time(NULL) );
|
|---|
| 1068 | temp_folder_URL = CFURLCreateFromFSRef( NULL, &temp_folder );
|
|---|
| 1069 | temp_folder_path = CFURLCopyFileSystemPath( temp_folder_URL, kCFURLPOSIXPathStyle );
|
|---|
| 1070 | log_file_path_raw = CFStringCreateWithFormat( NULL, NULL,
|
|---|
| 1071 | CFSTR("%@/logfile-%d-%ld"), temp_folder_path,getpid() ,random() );
|
|---|
| 1072 |
|
|---|
| 1073 | // Copy to path string buffer
|
|---|
| 1074 | Boolean ret = FALSE;
|
|---|
| 1075 | if(glob->params_opaque.log_file_path == NULL) {
|
|---|
| 1076 | int newSize = 1 + CFStringGetMaximumSizeOfFileSystemRepresentation(log_file_path_raw);
|
|---|
| 1077 | char* newPtr = calloc( newSize, 1 );
|
|---|
| 1078 | if( newPtr ) {
|
|---|
| 1079 | glob->params_opaque.log_file_path = newPtr;
|
|---|
| 1080 | ret = CFStringGetFileSystemRepresentation(log_file_path_raw,
|
|---|
| 1081 | glob->params_opaque.log_file_path, newSize );
|
|---|
| 1082 | }
|
|---|
| 1083 | }
|
|---|
| 1084 |
|
|---|
| 1085 | CFRelease(temp_folder_URL);
|
|---|
| 1086 | CFRelease(temp_folder_path);
|
|---|
| 1087 | CFRelease(log_file_path_raw);
|
|---|
| 1088 |
|
|---|
| 1089 | if( !ret ) {
|
|---|
| 1090 | fprintf(stderr, "ERROR: Getting log file path failed.\n");
|
|---|
| 1091 | err = paramErr;
|
|---|
| 1092 | goto bail;
|
|---|
| 1093 | }
|
|---|
| 1094 | }
|
|---|
| 1095 | }
|
|---|
| 1096 |
|
|---|
| 1097 | /* ================================================================================= */
|
|---|
| 1098 |
|
|---|
| 1099 | // Prepare codec context and buffers
|
|---|
| 1100 | if( !glob->codecCont ) {
|
|---|
| 1101 | // Prepare codec context
|
|---|
| 1102 | av_log_set_level(AV_LOG_QUIET);
|
|---|
| 1103 | glob->codecCont = avcodec_alloc_context3(glob->codec);
|
|---|
| 1104 | if( !glob->codecCont ) {
|
|---|
| 1105 | fprintf(stderr, "ERROR: Allocating codec context failed.\n");
|
|---|
| 1106 | err = memFullErr;
|
|---|
| 1107 | goto bail;
|
|---|
| 1108 | }
|
|---|
| 1109 |
|
|---|
| 1110 | /* ==================================== */
|
|---|
| 1111 |
|
|---|
| 1112 | logDebug(glob, "lavcEncoder: codecCont->{flags, flags2} = {0x%010x, 0x%010x}\n"
|
|---|
| 1113 | , glob->codecCont->flags, glob->codecCont->flags2);
|
|---|
| 1114 |
|
|---|
| 1115 | // codec is opend at EncodeFrame()
|
|---|
| 1116 | glob->codec_is_opened = FALSE;
|
|---|
| 1117 | glob->codec_open_failed = FALSE;
|
|---|
| 1118 | glob->extraDataReady = FALSE;
|
|---|
| 1119 |
|
|---|
| 1120 | // Write frame out or not. This field is updated at ProcessBetweenPasses().
|
|---|
| 1121 | glob->emit_frame = TRUE;
|
|---|
| 1122 |
|
|---|
| 1123 | // Additional encoding pass support (x264)
|
|---|
| 1124 | glob->use3rdpass = glob->params.USE3RDPASS;
|
|---|
| 1125 |
|
|---|
| 1126 | // pts counter for AV_NOPTS_VALUE
|
|---|
| 1127 | glob->next_pts_value = 0;
|
|---|
| 1128 |
|
|---|
| 1129 | // Total bytes of all encoded frame
|
|---|
| 1130 | glob->video_size = 0;
|
|---|
| 1131 |
|
|---|
| 1132 | // Total encoded frames.
|
|---|
| 1133 | glob->frame_count = 0;
|
|---|
| 1134 |
|
|---|
| 1135 | // delayed frame count.
|
|---|
| 1136 | glob->delayCount = 0;
|
|---|
| 1137 |
|
|---|
| 1138 | // chroma subsampling
|
|---|
| 1139 | glob->subsampling = glob->params.SUBSAMPLING;
|
|---|
| 1140 | if(glob->subsampling < 0 && CVF_Context_Create == NULL) AudioServicesPlayAlertSound(kUserPreferredAlert); //glob->subsampling = 0;
|
|---|
| 1141 |
|
|---|
| 1142 | #if USECoreVF
|
|---|
| 1143 | // CoreVF filter support
|
|---|
| 1144 | glob->filterPreset = glob->params.FILTERPRESET;
|
|---|
| 1145 | if(glob->subsampling < 0 && glob->filterPreset == 0) AudioServicesPlayAlertSound(kUserPreferredAlert); //glob->subsampling = 0;
|
|---|
| 1146 | #endif
|
|---|
| 1147 |
|
|---|
| 1148 | /* ==================================== */
|
|---|
| 1149 |
|
|---|
| 1150 | // Fill a few codecContext prior to build AVFrame
|
|---|
| 1151 | glob->codecCont->width = (glob->width+1) & ~1; // Use even-value-width in libavcodec
|
|---|
| 1152 | glob->codecCont->height = (glob->height+1) & ~1; // Use even-value-height in libavcodec
|
|---|
| 1153 |
|
|---|
| 1154 | glob->codecCont->pix_fmt = PIX_FMT_YUV420P;
|
|---|
| 1155 |
|
|---|
| 1156 | // Encoded AVFrame buffer
|
|---|
| 1157 | int PixelCountRU = glob->widthRoundedUp * glob->heightRoundedUp;
|
|---|
| 1158 | glob->encode_buffer_size = 4 * PixelCountRU;
|
|---|
| 1159 | glob->encode_buffer = calloc(1, glob->encode_buffer_size);
|
|---|
| 1160 | if( !glob->encode_buffer ) {
|
|---|
| 1161 | fprintf(stderr, "ERROR: Allocating coded frame buffer failed.\n");
|
|---|
| 1162 | err = memFullErr;
|
|---|
| 1163 | goto bail;
|
|---|
| 1164 | }
|
|---|
| 1165 |
|
|---|
| 1166 | /* ==================================== */
|
|---|
| 1167 |
|
|---|
| 1168 | // Planer YUV Source AVFrame*
|
|---|
| 1169 | glob->frame = avcodec_alloc_frame();
|
|---|
| 1170 | if( !glob->frame ) {
|
|---|
| 1171 | fprintf(stderr, "ERROR: avcodec_alloc_frame failed.\n");
|
|---|
| 1172 | err = memFullErr;
|
|---|
| 1173 | goto bail;
|
|---|
| 1174 | }
|
|---|
| 1175 |
|
|---|
| 1176 | // YUV Source AVFrame buffer
|
|---|
| 1177 | #if NATIVERECT
|
|---|
| 1178 | if( glob->codecCont->get_buffer(glob->codecCont,glob->frame) ) {
|
|---|
| 1179 | fprintf(stderr, "ERROR: avcodec_default_get_buffer() failed.\n");
|
|---|
| 1180 | err = memFullErr;
|
|---|
| 1181 | goto bail;
|
|---|
| 1182 | }
|
|---|
| 1183 | #else
|
|---|
| 1184 | glob->planer_buffer = av_malloc(avpicture_get_size(
|
|---|
| 1185 | PIX_FMT_YUV420P, glob->widthRoundedUp, glob->heightRoundedUp) );
|
|---|
| 1186 | if( !glob->planer_buffer ) {
|
|---|
| 1187 | fprintf(stderr, "ERROR: av_malloc failed.\n");
|
|---|
| 1188 | err = memFullErr;
|
|---|
| 1189 | goto bail;
|
|---|
| 1190 | }
|
|---|
| 1191 | avpicture_fill( (AVPicture*)glob->frame, glob->planer_buffer,
|
|---|
| 1192 | PIX_FMT_YUV420P, glob->widthRoundedUp, glob->heightRoundedUp );
|
|---|
| 1193 | #endif
|
|---|
| 1194 |
|
|---|
| 1195 | //
|
|---|
| 1196 | #if USECoreVF
|
|---|
| 1197 | if( glob->filterPreset ) err = openCoreVF(glob);
|
|---|
| 1198 | if( err ) {
|
|---|
| 1199 | fprintf(stderr, "ERROR: Failed to initialize CoreVF engine.\n");
|
|---|
| 1200 | goto bail;
|
|---|
| 1201 | }
|
|---|
| 1202 | #endif
|
|---|
| 1203 | }
|
|---|
| 1204 |
|
|---|
| 1205 | /* ================================================================================= */
|
|---|
| 1206 |
|
|---|
| 1207 | // Setup encoder parameters in codecContext
|
|---|
| 1208 | if (setup_codecCont(glob)) {
|
|---|
| 1209 | err = paramErr;
|
|---|
| 1210 | goto bail;
|
|---|
| 1211 | }
|
|---|
| 1212 |
|
|---|
| 1213 | /* ================================================================================= */
|
|---|
| 1214 |
|
|---|
| 1215 | {
|
|---|
| 1216 | #if X264
|
|---|
| 1217 | // Check limitation for iPod/iTunes support
|
|---|
| 1218 | if(glob->add_uuid && glob->params.CODER_TYPE > 1){ // CAVLC only; no CABAC
|
|---|
| 1219 | fprintf(stderr, "ERROR: Unable to add UUID; Incompatible CABAC detected. (CAVLC required)\n");
|
|---|
| 1220 | AudioServicesPlayAlertSound(kUserPreferredAlert); glob->add_uuid = FALSE;
|
|---|
| 1221 | }
|
|---|
| 1222 | if(glob->add_uuid && glob->params.LEVEL > 30) { // iPod requires H.264/AVC Level 3.0 or below
|
|---|
| 1223 | fprintf(stderr, "ERROR: Unable to add UUID; Incompatible Level detected. (Level 3.0 max)\n");
|
|---|
| 1224 | AudioServicesPlayAlertSound(kUserPreferredAlert); glob->add_uuid = FALSE;
|
|---|
| 1225 | }
|
|---|
| 1226 | if(glob->add_uuid && glob->codecCont->rc_buffer_size > 2048*1024) { // Kbit; iPod Video VBV buffer size is 2Mbit
|
|---|
| 1227 | fprintf(stderr, "ERROR: Unable to add UUID; Incompatible RC_BUFSIZE detected. (%d Kbps)\n"
|
|---|
| 1228 | , glob->codecCont->rc_buffer_size/1024);
|
|---|
| 1229 | AudioServicesPlayAlertSound(kUserPreferredAlert); glob->add_uuid = FALSE;
|
|---|
| 1230 | }
|
|---|
| 1231 | if(glob->add_uuid && glob->use_B_frame) { // No B frame
|
|---|
| 1232 | fprintf(stderr, "ERROR: Unable to add UUID; Incompatible frame reordering detected. (i.e. B-frame)\n");
|
|---|
| 1233 | AudioServicesPlayAlertSound(kUserPreferredAlert); glob->add_uuid = FALSE;
|
|---|
| 1234 | }
|
|---|
| 1235 | if(glob->add_uuid && (glob->width + glob->height)/16 > 70) { // Max macro block count is 70
|
|---|
| 1236 | fprintf(stderr, "ERROR: Unable to add UUID; Incompatible large frame detected. (%d,%d)\n"
|
|---|
| 1237 | , glob->width, glob->height);
|
|---|
| 1238 | AudioServicesPlayAlertSound(kUserPreferredAlert); glob->add_uuid = FALSE;
|
|---|
| 1239 | }
|
|---|
| 1240 | if(glob->add_uuid && glob->codecCont->bit_rate > 1536*1024) { // Max bitrate is 1500kbps
|
|---|
| 1241 | fprintf(stderr, "ERROR: Unable to add UUID; Incompatible bit_rate detected. (%d Kbps)\n"
|
|---|
| 1242 | , glob->codecCont->bit_rate/1024);
|
|---|
| 1243 | AudioServicesPlayAlertSound(kUserPreferredAlert); glob->add_uuid = FALSE;
|
|---|
| 1244 | }
|
|---|
| 1245 | #endif
|
|---|
| 1246 | #if MPEG4
|
|---|
| 1247 | // Adjust incompatible flags
|
|---|
| 1248 | if( glob->codecCont->trellis == 0 )
|
|---|
| 1249 | glob->codecCont->flags &= ~ CODEC_FLAG_CBP_RD;
|
|---|
| 1250 | if( glob->codecCont->mb_decision != FF_MB_DECISION_RD )
|
|---|
| 1251 | glob->codecCont->flags &= ~ CODEC_FLAG_QP_RD;
|
|---|
| 1252 |
|
|---|
| 1253 | // Special parameters
|
|---|
| 1254 | if( glob->codecCont->mb_decision == FF_MB_DECISION_RD ) {
|
|---|
| 1255 | glob->codecCont->me_cmp = 0; // 0:FF_CMP_SAD 2:FF_CMP_SATD 6:FF_CMP_RD
|
|---|
| 1256 | glob->codecCont->me_sub_cmp = 6; // 0:FF_CMP_SAD 2:FF_CMP_SATD 6:FF_CMP_RD
|
|---|
| 1257 | glob->codecCont->me_pre_cmp = 0; // 0:FF_CMP_SAD 2:FF_CMP_SATD 6:FF_CMP_RD
|
|---|
| 1258 | glob->codecCont->mb_cmp = 6; // 0:FF_CMP_SAD 2:FF_CMP_SATD 6:FF_CMP_RD
|
|---|
| 1259 | glob->codecCont->dia_size = 512 + 16; // hex_search 16; motion_est_template.c:diamond_search()
|
|---|
| 1260 | glob->codecCont->last_predictor_count = 4; // motion_est_template.c:epzs_motion_search_internal()
|
|---|
| 1261 | //glob->codecCont->pre_me = 2; // value 1-4
|
|---|
| 1262 | //glob->codecCont->pre_dia_size = 2; // value 1-4
|
|---|
| 1263 | }
|
|---|
| 1264 | #endif
|
|---|
| 1265 | }
|
|---|
| 1266 |
|
|---|
| 1267 | logDebug(glob, "lavcEncoder: codecCont->{flags, flags2} = {0x%010x, 0x%010x}\n"
|
|---|
| 1268 | , glob->codecCont->flags, glob->codecCont->flags2);
|
|---|
| 1269 |
|
|---|
| 1270 | bail:
|
|---|
| 1271 | if(err && !glob->meetsErr) {
|
|---|
| 1272 | AudioServicesPlayAlertSound(kUserPreferredAlert); glob->meetsErr = TRUE;
|
|---|
| 1273 | }
|
|---|
| 1274 | return err;
|
|---|
| 1275 | } // ComponentCall (PrepareToCompressFrames)
|
|---|
| 1276 |
|
|---|
| 1277 |
|
|---|
| 1278 | // ComponentCall (EncodeFrame) // 56
|
|---|
| 1279 | ComponentResult lavcEncoder_EncodeFrame(lavcEncoderGlobalRecord *glob,
|
|---|
| 1280 | ICMCompressorSourceFrameRef source_frame, UInt32 flags)
|
|---|
| 1281 | {
|
|---|
| 1282 | // logDebug(glob, "lavcEncoder: [%08x %s]\n", glob, __FUNCTION__);
|
|---|
| 1283 |
|
|---|
| 1284 | ComponentResult err = paramErr;
|
|---|
| 1285 |
|
|---|
| 1286 | // Check
|
|---|
| 1287 | if( glob->ICM_passcount == 0 ) {
|
|---|
| 1288 | glob->frame_count++;
|
|---|
| 1289 | return noErr;
|
|---|
| 1290 | }
|
|---|
| 1291 |
|
|---|
| 1292 | if( glob->fakeMultipass && !glob->emit_frame ) {
|
|---|
| 1293 | // Skipping this pass... (QSCALE or CRF is enabled)
|
|---|
| 1294 | err = noErr;
|
|---|
| 1295 | goto bail;
|
|---|
| 1296 | }
|
|---|
| 1297 |
|
|---|
| 1298 | {
|
|---|
| 1299 | TimeValue64 displayTimeStamp, displayDuration;
|
|---|
| 1300 | TimeScale timeScale;
|
|---|
| 1301 | ICMCompressorSourceFrameGetDisplayTimeStampAndDuration( source_frame, &displayTimeStamp, &displayDuration, &timeScale, NULL);
|
|---|
| 1302 |
|
|---|
| 1303 | long displayNumber;
|
|---|
| 1304 | displayNumber = ICMCompressorSourceFrameGetDisplayNumber(source_frame);
|
|---|
| 1305 |
|
|---|
| 1306 | logDebug(glob, "lavcEncoder: [%08x %s] (%d, %lld, %lld, %d)\n", glob, __FUNCTION__
|
|---|
| 1307 | , displayNumber, displayTimeStamp, displayDuration, timeScale
|
|---|
| 1308 | );
|
|---|
| 1309 |
|
|---|
| 1310 | // Update media timescale
|
|---|
| 1311 | glob->params_opaque.TIMESCALE = timeScale;
|
|---|
| 1312 | }
|
|---|
| 1313 |
|
|---|
| 1314 | /* ================================================================================= */
|
|---|
| 1315 |
|
|---|
| 1316 | // Open Codec at encoding first frame
|
|---|
| 1317 | if( !glob->codec_is_opened ) {
|
|---|
| 1318 | if(open_libAV(glob)) {
|
|---|
| 1319 | err = paramErr;
|
|---|
| 1320 | goto bail;
|
|---|
| 1321 | }
|
|---|
| 1322 | }
|
|---|
| 1323 |
|
|---|
| 1324 | /* ================================================================================= */
|
|---|
| 1325 |
|
|---|
| 1326 | {
|
|---|
| 1327 | // Get source CVPixelBuffer
|
|---|
| 1328 | CVPixelBufferRef pixel_buffer = NULL;
|
|---|
| 1329 | OSType pixel_format_type;
|
|---|
| 1330 |
|
|---|
| 1331 | if( !source_frame ) {
|
|---|
| 1332 | fprintf(stderr, "ERROR: No source_frame\n");
|
|---|
| 1333 | goto bail;
|
|---|
| 1334 | }
|
|---|
| 1335 |
|
|---|
| 1336 | pixel_buffer = ICMCompressorSourceFrameGetPixelBuffer(source_frame);
|
|---|
| 1337 | if( !pixel_buffer ) {
|
|---|
| 1338 | fprintf(stderr, "ERROR: No pixel_buffer\n");
|
|---|
| 1339 | goto bail;
|
|---|
| 1340 | }
|
|---|
| 1341 |
|
|---|
| 1342 | pixel_format_type = CVPixelBufferGetPixelFormatType(pixel_buffer);
|
|---|
| 1343 | if( pixel_format_type != k422YpCbCr8CodecType ) { // packed YUV 4:2:2
|
|---|
| 1344 | fprintf(stderr, "ERROR: Improper pixel_format_type\n");
|
|---|
| 1345 | goto bail;
|
|---|
| 1346 | }
|
|---|
| 1347 |
|
|---|
| 1348 | // Lock Pixel buffer
|
|---|
| 1349 | CVPixelBufferLockBaseAddress(pixel_buffer, 0);
|
|---|
| 1350 |
|
|---|
| 1351 | // Odd height special; bottom line duplication
|
|---|
| 1352 | if( 1&(glob->height) )
|
|---|
| 1353 | memcpy(
|
|---|
| 1354 | CVPixelBufferGetBaseAddress(pixel_buffer) + CVPixelBufferGetBytesPerRow(pixel_buffer)*(glob->height),
|
|---|
| 1355 | CVPixelBufferGetBaseAddress(pixel_buffer) + CVPixelBufferGetBytesPerRow(pixel_buffer)*(glob->height-1),
|
|---|
| 1356 | CVPixelBufferGetBytesPerRow(pixel_buffer) );
|
|---|
| 1357 |
|
|---|
| 1358 | // Odd width special; Duplicate right edge's luminance (2vuy only)
|
|---|
| 1359 | if( 1&(glob->width) ) {
|
|---|
| 1360 | UInt8* pbroot = CVPixelBufferGetBaseAddress(pixel_buffer);
|
|---|
| 1361 | UInt32 rowbyte = CVPixelBufferGetBytesPerRow(pixel_buffer);
|
|---|
| 1362 | UInt32 y;
|
|---|
| 1363 | for( y = 0; y < (glob->codecCont->height); y++) {
|
|---|
| 1364 | UInt8* p = (pbroot + y * rowbyte) + (2 * glob->width);
|
|---|
| 1365 | p[1] = p[-1];
|
|---|
| 1366 | }
|
|---|
| 1367 | }
|
|---|
| 1368 |
|
|---|
| 1369 | // Convert packed YUV 4:2:2 -> planar YUV 4:2:0
|
|---|
| 1370 | if(glob->subsampling < 0) {
|
|---|
| 1371 | assert(CVF_Context_Create);
|
|---|
| 1372 | } else {
|
|---|
| 1373 | if(glob->subsampling > 0) {
|
|---|
| 1374 | copy_2vuy_to_planar_YUV420_i(
|
|---|
| 1375 | glob->widthRoundedUp, glob->height, // width>=ru16, height is native
|
|---|
| 1376 | CVPixelBufferGetBaseAddress(pixel_buffer), CVPixelBufferGetBytesPerRow(pixel_buffer),
|
|---|
| 1377 | glob->frame->data[0], glob->frame->linesize[0],
|
|---|
| 1378 | glob->frame->data[1], glob->frame->linesize[1],
|
|---|
| 1379 | glob->frame->data[2], glob->frame->linesize[2],
|
|---|
| 1380 | glob->subsampling);
|
|---|
| 1381 | } else
|
|---|
| 1382 | if(glob->subsampling == 0) {
|
|---|
| 1383 | copy_2vuy_to_planar_YUV420(
|
|---|
| 1384 | glob->widthRoundedUp, glob->height, // width>=ru16, height is native
|
|---|
| 1385 | CVPixelBufferGetBaseAddress(pixel_buffer), CVPixelBufferGetBytesPerRow(pixel_buffer),
|
|---|
| 1386 | glob->frame->data[0], glob->frame->linesize[0],
|
|---|
| 1387 | glob->frame->data[1], glob->frame->linesize[1],
|
|---|
| 1388 | glob->frame->data[2], glob->frame->linesize[2]);
|
|---|
| 1389 | }
|
|---|
| 1390 |
|
|---|
| 1391 | // Dup luma bottom line under odd height picture
|
|---|
| 1392 | int lumaH0 = glob->height;
|
|---|
| 1393 | if( lumaH0 & 1 ) {
|
|---|
| 1394 | memcpy(
|
|---|
| 1395 | glob->frame->data[0] + glob->frame->linesize[0] * (lumaH0),
|
|---|
| 1396 | glob->frame->data[0] + glob->frame->linesize[0] * (lumaH0 - 1),
|
|---|
| 1397 | glob->frame->linesize[0]);
|
|---|
| 1398 | }
|
|---|
| 1399 | }
|
|---|
| 1400 |
|
|---|
| 1401 | // Unlock PixelBuffer
|
|---|
| 1402 | CVPixelBufferUnlockBaseAddress(pixel_buffer, 0);
|
|---|
| 1403 | }
|
|---|
| 1404 |
|
|---|
| 1405 | /* ================================================================================= */
|
|---|
| 1406 |
|
|---|
| 1407 | {
|
|---|
| 1408 | // Encode source frame
|
|---|
| 1409 | if( CFArrayGetCount(glob->array_source_frame) == kMaxSourceFrame ) {
|
|---|
| 1410 | fprintf(stderr, "ERROR: Source frame buffer count hit limit(%d).\n", kMaxSourceFrame);
|
|---|
| 1411 | goto bail;
|
|---|
| 1412 | }
|
|---|
| 1413 |
|
|---|
| 1414 | CFArrayAppendValue(glob->array_source_frame, source_frame);
|
|---|
| 1415 | glob->frame_count++;
|
|---|
| 1416 | }
|
|---|
| 1417 | #if USECoreVF
|
|---|
| 1418 | if(glob->filterPreset) {
|
|---|
| 1419 | if(!glob->cvfCont) {
|
|---|
| 1420 | err = process_libAV(glob, source_frame);
|
|---|
| 1421 | if(err) goto bail;
|
|---|
| 1422 | } else {
|
|---|
| 1423 | // Xfer from AVFrame into CVF_Frame
|
|---|
| 1424 | if(glob->subsampling >= 0) {
|
|---|
| 1425 | CVF_CopyPlane(
|
|---|
| 1426 | glob->frame->data[0], glob->frame->linesize[0], glob->codecCont->height,
|
|---|
| 1427 | CVF_GetPlaneBase(glob->cvfInFrame, 0),
|
|---|
| 1428 | CVF_GetPlaneStride(glob->cvfInFrame, 0), CVF_GetPlaneRow(glob->cvfInFrame, 0)
|
|---|
| 1429 | );
|
|---|
| 1430 | CVF_CopyPlane(
|
|---|
| 1431 | glob->frame->data[1], glob->frame->linesize[1], glob->codecCont->height,
|
|---|
| 1432 | CVF_GetPlaneBase(glob->cvfInFrame, 1),
|
|---|
| 1433 | CVF_GetPlaneStride(glob->cvfInFrame, 1), CVF_GetPlaneRow(glob->cvfInFrame, 1)
|
|---|
| 1434 | );
|
|---|
| 1435 | CVF_CopyPlane(
|
|---|
| 1436 | glob->frame->data[2], glob->frame->linesize[2], glob->codecCont->height,
|
|---|
| 1437 | CVF_GetPlaneBase(glob->cvfInFrame, 2),
|
|---|
| 1438 | CVF_GetPlaneStride(glob->cvfInFrame, 2), CVF_GetPlaneRow(glob->cvfInFrame, 2)
|
|---|
| 1439 | );
|
|---|
| 1440 | } else {
|
|---|
| 1441 | CVPixelBufferRef pixel_buffer = ICMCompressorSourceFrameGetPixelBuffer(source_frame);
|
|---|
| 1442 |
|
|---|
| 1443 | // Lock Pixel buffer
|
|---|
| 1444 | CVPixelBufferLockBaseAddress(pixel_buffer, 0);
|
|---|
| 1445 |
|
|---|
| 1446 | // 422 Direct processing; requires CoreVF support
|
|---|
| 1447 | CVF_CopyPlane(
|
|---|
| 1448 | CVPixelBufferGetBaseAddress(pixel_buffer), CVPixelBufferGetBytesPerRow(pixel_buffer),
|
|---|
| 1449 | glob->heightRoundedUp,
|
|---|
| 1450 | CVF_GetPlaneBase(glob->cvfInFrame, 0),
|
|---|
| 1451 | CVF_GetPlaneStride(glob->cvfInFrame, 0), CVF_GetPlaneRow(glob->cvfInFrame, 0)
|
|---|
| 1452 | );
|
|---|
| 1453 |
|
|---|
| 1454 | // Unlock PixelBuffer
|
|---|
| 1455 | CVPixelBufferUnlockBaseAddress(pixel_buffer, 0);
|
|---|
| 1456 | }
|
|---|
| 1457 |
|
|---|
| 1458 | // push source_frame for later use
|
|---|
| 1459 | CFArrayAppendValue(glob->cvfSourceArray, source_frame);
|
|---|
| 1460 |
|
|---|
| 1461 | // call filter chain
|
|---|
| 1462 | glob->cvfInFrame->index = glob->cvfCont->inputIndex + 1; /* not strict but enough */
|
|---|
| 1463 | glob->cvfOutFrame->index = -1;
|
|---|
| 1464 | int result = CVF_Context_Process(glob->cvfCont,
|
|---|
| 1465 | glob->cvfInFrame->buffer, glob->cvfInFrame->video,
|
|---|
| 1466 | glob->cvfOutFrame->buffer, glob->cvfOutFrame->video);
|
|---|
| 1467 |
|
|---|
| 1468 | if( result == CVF_ST_FRAMEISREADY || result == CVF_ST_REQMOREFRAME ) {
|
|---|
| 1469 | err = noErr; /* we should update this here ! */
|
|---|
| 1470 | } else {
|
|---|
| 1471 | fprintf(stderr, "ERROR: CVF_Context_Process() returned error(%d).\n", result);
|
|---|
| 1472 | err = paramErr;
|
|---|
| 1473 | goto bail;
|
|---|
| 1474 | }
|
|---|
| 1475 |
|
|---|
| 1476 | // process output frame(s)
|
|---|
| 1477 | while(CFArrayGetCount(glob->cvfCont->tempCache)) {
|
|---|
| 1478 | // take out CVF_Frames
|
|---|
| 1479 | result = CVF_Context_Extract(glob->cvfCont,
|
|---|
| 1480 | glob->cvfOutFrame->buffer, glob->cvfOutFrame->video);
|
|---|
| 1481 |
|
|---|
| 1482 | if(result == CVF_ST_FRAMEISREADY) {
|
|---|
| 1483 | // feed from XVF_Frame into libavcodec
|
|---|
| 1484 | CVF_CopyPlane(
|
|---|
| 1485 | CVF_GetPlaneBase(glob->cvfOutFrame, 0),
|
|---|
| 1486 | CVF_GetPlaneStride(glob->cvfOutFrame, 0), CVF_GetPlaneRow(glob->cvfOutFrame, 0),
|
|---|
| 1487 | glob->frame->data[0], glob->frame->linesize[0], glob->codecCont->height
|
|---|
| 1488 | );
|
|---|
| 1489 | CVF_CopyPlane(
|
|---|
| 1490 | CVF_GetPlaneBase(glob->cvfOutFrame, 1),
|
|---|
| 1491 | CVF_GetPlaneStride(glob->cvfOutFrame, 1), CVF_GetPlaneRow(glob->cvfOutFrame, 1),
|
|---|
| 1492 | glob->frame->data[1], glob->frame->linesize[1], glob->codecCont->height
|
|---|
| 1493 | );
|
|---|
| 1494 | CVF_CopyPlane(
|
|---|
| 1495 | CVF_GetPlaneBase(glob->cvfOutFrame, 2),
|
|---|
| 1496 | CVF_GetPlaneStride(glob->cvfOutFrame, 2), CVF_GetPlaneRow(glob->cvfOutFrame, 2),
|
|---|
| 1497 | glob->frame->data[2], glob->frame->linesize[2], glob->codecCont->height
|
|---|
| 1498 | );
|
|---|
| 1499 |
|
|---|
| 1500 | if(CFArrayGetCount(glob->cvfSourceArray)) {
|
|---|
| 1501 | source_frame = (ICMCompressorSourceFrameRef)CFArrayGetValueAtIndex(glob->cvfSourceArray, 0);
|
|---|
| 1502 | CFArrayRemoveValueAtIndex(glob->cvfSourceArray, 0);
|
|---|
| 1503 |
|
|---|
| 1504 | err = process_libAV(glob, source_frame);
|
|---|
| 1505 | if(err) goto bail;
|
|---|
| 1506 | } else {
|
|---|
| 1507 | // Broken filter output; drop output anyway
|
|---|
| 1508 | }
|
|---|
| 1509 | } else if(result != CVF_ST_REQMOREFRAME) {
|
|---|
| 1510 | // error condition
|
|---|
| 1511 | err = paramErr;
|
|---|
| 1512 | goto bail;
|
|---|
| 1513 | }
|
|---|
| 1514 | } // while(CFArrayGetCount(glob->cvfCont->tempCache))
|
|---|
| 1515 |
|
|---|
| 1516 | } // if(glob->cvfCont)
|
|---|
| 1517 | } else
|
|---|
| 1518 | #endif
|
|---|
| 1519 | {
|
|---|
| 1520 | err = process_libAV(glob, source_frame);
|
|---|
| 1521 | if(err) goto bail;
|
|---|
| 1522 | }
|
|---|
| 1523 |
|
|---|
| 1524 | bail:
|
|---|
| 1525 | if(err && !glob->meetsErr) {
|
|---|
| 1526 | AudioServicesPlayAlertSound(kUserPreferredAlert); glob->meetsErr = TRUE;
|
|---|
| 1527 | }
|
|---|
| 1528 | return err;
|
|---|
| 1529 | } // ComponentCall (EncodeFrame)
|
|---|
| 1530 |
|
|---|
| 1531 |
|
|---|
| 1532 | // ComponentCall (CompleteFrame) // 57
|
|---|
| 1533 | ComponentResult lavcEncoder_CompleteFrame(lavcEncoderGlobalRecord *glob,
|
|---|
| 1534 | ICMCompressorSourceFrameRef source_frame, UInt32 flags)
|
|---|
| 1535 | {
|
|---|
| 1536 | logDebug(glob, "lavcEncoder: [%08x %s]\n", glob, __FUNCTION__);
|
|---|
| 1537 |
|
|---|
| 1538 | ComponentResult err = noErr;
|
|---|
| 1539 |
|
|---|
| 1540 | if( glob->fakeMultipass && !glob->emit_frame ) {
|
|---|
| 1541 | // Skipping this pass... (QSCALE or CRF is enabled)
|
|---|
| 1542 | goto bail;
|
|---|
| 1543 | }
|
|---|
| 1544 |
|
|---|
| 1545 | #if USECoreVF
|
|---|
| 1546 | if(glob->filterPreset) {
|
|---|
| 1547 | int result = CVF_ST_NOERROR;
|
|---|
| 1548 | while(glob->cvfCont->inputIndex > glob->cvfCont->outputIndex) {
|
|---|
| 1549 | if(!CFArrayGetCount(glob->cvfSourceArray)) break;
|
|---|
| 1550 |
|
|---|
| 1551 | glob->cvfInFrame->index = -1;
|
|---|
| 1552 | glob->cvfOutFrame->index = -1;
|
|---|
| 1553 | result = CVF_Context_Process(glob->cvfCont, NULL, NULL,
|
|---|
| 1554 | glob->cvfOutFrame->buffer, glob->cvfOutFrame->video);
|
|---|
| 1555 |
|
|---|
| 1556 | if( result == CVF_ST_FRAMEISREADY || result == CVF_ST_REQMOREFRAME ) {
|
|---|
| 1557 | err = noErr; /* we should update this here ! */
|
|---|
| 1558 | } else {
|
|---|
| 1559 | fprintf(stderr, "ERROR: CVF_Context_Process() returned error(%d).\n", result);
|
|---|
| 1560 | err = paramErr;
|
|---|
| 1561 | goto bail;
|
|---|
| 1562 | }
|
|---|
| 1563 |
|
|---|
| 1564 | while( CFArrayGetCount(glob->cvfCont->tempCache) ) {
|
|---|
| 1565 | result = CVF_Context_Extract(glob->cvfCont,
|
|---|
| 1566 | glob->cvfOutFrame->buffer, glob->cvfOutFrame->video);
|
|---|
| 1567 |
|
|---|
| 1568 | if(result == CVF_ST_FRAMEISREADY) {
|
|---|
| 1569 | // feed from XVF_Frame into libavcodec
|
|---|
| 1570 | CVF_CopyPlane(
|
|---|
| 1571 | CVF_GetPlaneBase(glob->cvfOutFrame, 0),
|
|---|
| 1572 | CVF_GetPlaneStride(glob->cvfOutFrame, 0), CVF_GetPlaneRow(glob->cvfOutFrame, 0),
|
|---|
| 1573 | glob->frame->data[0], glob->frame->linesize[0], glob->codecCont->height
|
|---|
| 1574 | );
|
|---|
| 1575 | CVF_CopyPlane(
|
|---|
| 1576 | CVF_GetPlaneBase(glob->cvfOutFrame, 1),
|
|---|
| 1577 | CVF_GetPlaneStride(glob->cvfOutFrame, 1), CVF_GetPlaneRow(glob->cvfOutFrame, 1),
|
|---|
| 1578 | glob->frame->data[1], glob->frame->linesize[1], glob->codecCont->height
|
|---|
| 1579 | );
|
|---|
| 1580 | CVF_CopyPlane(
|
|---|
| 1581 | CVF_GetPlaneBase(glob->cvfOutFrame, 2),
|
|---|
| 1582 | CVF_GetPlaneStride(glob->cvfOutFrame, 2), CVF_GetPlaneRow(glob->cvfOutFrame, 2),
|
|---|
| 1583 | glob->frame->data[2], glob->frame->linesize[2], glob->codecCont->height
|
|---|
| 1584 | );
|
|---|
| 1585 |
|
|---|
| 1586 | if(CFArrayGetCount(glob->cvfSourceArray)) {
|
|---|
| 1587 | source_frame = (ICMCompressorSourceFrameRef)CFArrayGetValueAtIndex(glob->cvfSourceArray, 0);
|
|---|
| 1588 | CFArrayRemoveValueAtIndex(glob->cvfSourceArray, 0);
|
|---|
| 1589 |
|
|---|
| 1590 | err = process_libAV(glob, source_frame);
|
|---|
| 1591 | if(err) goto bail;
|
|---|
| 1592 | } else {
|
|---|
| 1593 | // Broken filter output; drop output anyway
|
|---|
| 1594 | }
|
|---|
| 1595 | } else if(result != CVF_ST_REQMOREFRAME) {
|
|---|
| 1596 | // error condition
|
|---|
| 1597 | err = paramErr;
|
|---|
| 1598 | goto bail;
|
|---|
| 1599 | }
|
|---|
| 1600 | } // while( CFArrayGetCount(glob->cvfCont->tempCache) )
|
|---|
| 1601 | }
|
|---|
| 1602 | }
|
|---|
| 1603 | #endif
|
|---|
| 1604 |
|
|---|
| 1605 | // Proceed to libavcodec call
|
|---|
| 1606 | int limit = FF_MAX_B_FRAMES;
|
|---|
| 1607 | while(glob->delayCount) {
|
|---|
| 1608 | // Pass NULL AVFrame into codec's buffer
|
|---|
| 1609 | glob->frame_size = avcodec_encode_video(glob->codecCont,
|
|---|
| 1610 | glob->encode_buffer, glob->encode_buffer_size, NULL);
|
|---|
| 1611 |
|
|---|
| 1612 | // Check encoded frame
|
|---|
| 1613 | if( glob->frame_size > 0 ) {
|
|---|
| 1614 | glob->delayCount--;
|
|---|
| 1615 |
|
|---|
| 1616 | if( glob->emit_frame ) {
|
|---|
| 1617 | err = emitFrameData(glob);
|
|---|
| 1618 | } else {
|
|---|
| 1619 | // last few frames of pass 1; ignore it.
|
|---|
| 1620 | }
|
|---|
| 1621 |
|
|---|
| 1622 | // log file support
|
|---|
| 1623 | if( glob->logfile ) fprintf( glob->logfile, "%s", glob->codecCont->stats_out );
|
|---|
| 1624 | } else {
|
|---|
| 1625 | if( --limit == 0 ) {
|
|---|
| 1626 | fprintf(stderr, "ERROR: No remaining frames found\n");
|
|---|
| 1627 | fprintf(stderr, "ERROR: array_source_frame still contains %d frame(s).\n"
|
|---|
| 1628 | , (int)CFArrayGetCount(glob->array_source_frame));
|
|---|
| 1629 | err = paramErr;
|
|---|
| 1630 | break;
|
|---|
| 1631 | }
|
|---|
| 1632 | }
|
|---|
| 1633 | }
|
|---|
| 1634 |
|
|---|
| 1635 | bail:
|
|---|
| 1636 | if(err && !glob->meetsErr) {
|
|---|
| 1637 | AudioServicesPlayAlertSound(kUserPreferredAlert); glob->meetsErr = TRUE;
|
|---|
| 1638 | }
|
|---|
| 1639 | return err;
|
|---|
| 1640 | } // ComponentCall (CompleteFrame)
|
|---|
| 1641 |
|
|---|
| 1642 |
|
|---|
| 1643 | #pragma mark -
|
|---|
| 1644 |
|
|---|
| 1645 |
|
|---|
| 1646 | // ComponentCall (BeginPass) // 58
|
|---|
| 1647 | ComponentResult lavcEncoder_BeginPass (lavcEncoderGlobalRecord *glob,
|
|---|
| 1648 | ICMCompressionPassModeFlags pass_mode_flags, UInt32 flags, ICMMultiPassStorageRef storage)
|
|---|
| 1649 | {
|
|---|
| 1650 | logDebug(glob, "lavcEncoder: [%08x %s] ; glob->ICM_passcount = %d\n", glob, __FUNCTION__, glob->ICM_passcount);
|
|---|
| 1651 |
|
|---|
| 1652 | ComponentResult err = paramErr;
|
|---|
| 1653 | glob->passDate = CFDateCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent());
|
|---|
| 1654 |
|
|---|
| 1655 | // Check
|
|---|
| 1656 | if( glob->codec_is_opened ) {
|
|---|
| 1657 | fprintf(stderr, "ERROR; Codec is already opend.\n");
|
|---|
| 1658 | goto bail;
|
|---|
| 1659 | }
|
|---|
| 1660 | if( !glob->params_opaque.log_file_path || 0 == strlen(glob->params_opaque.log_file_path) ) {
|
|---|
| 1661 | fprintf(stderr, "ERROR: Checking log file path failed\n");
|
|---|
| 1662 | goto bail;
|
|---|
| 1663 | }
|
|---|
| 1664 | if( glob->logfile ) {
|
|---|
| 1665 | fprintf(stderr, "ERROR: Log file is already opend.\n");
|
|---|
| 1666 | goto bail;
|
|---|
| 1667 | }
|
|---|
| 1668 |
|
|---|
| 1669 | logDebug(glob, "lavcEncoder: (IN) pass_mode_flags = %d glob->codecCont->flags= 0x%010x\n"
|
|---|
| 1670 | , pass_mode_flags, glob->codecCont->flags
|
|---|
| 1671 | );
|
|---|
| 1672 |
|
|---|
| 1673 | // Check ICM flags
|
|---|
| 1674 | glob->emit_frame = FALSE; // unset emit_frame before start
|
|---|
| 1675 | UInt32 flagMask = ( kICMCompressionPassMode_NoSourceFrames |
|
|---|
| 1676 | kICMCompressionPassMode_OutputEncodedFrames |
|
|---|
| 1677 | kICMCompressionPassMode_NotReadyToOutputEncodedFrames );
|
|---|
| 1678 |
|
|---|
| 1679 | switch( glob->ICM_passcount ) {
|
|---|
| 1680 | case -1:
|
|---|
| 1681 | if( (pass_mode_flags & flagMask) ==
|
|---|
| 1682 | (kICMCompressionPassMode_NoSourceFrames | kICMCompressionPassMode_NotReadyToOutputEncodedFrames) ) {
|
|---|
| 1683 | logInfo(glob, "lavcEncoder: Begin pass 0.\n");
|
|---|
| 1684 | glob->ICM_passcount = 0; // null pass
|
|---|
| 1685 | glob->emit_frame = FALSE;
|
|---|
| 1686 | glob->codecCont->flags &= ~CODEC_FLAG_PASS1;
|
|---|
| 1687 | glob->codecCont->flags &= ~CODEC_FLAG_PASS2;
|
|---|
| 1688 | err = noErr;
|
|---|
| 1689 | goto bail;
|
|---|
| 1690 | } else {
|
|---|
| 1691 | logInfo(glob, "lavcEncoder: Begin pass 0.\n");
|
|---|
| 1692 | fprintf(stderr, "ERROR: Invalid pass_mode_flags for this pass detected.\n");
|
|---|
| 1693 | goto bail;
|
|---|
| 1694 | }
|
|---|
| 1695 | break;
|
|---|
| 1696 | case 0:
|
|---|
| 1697 | if( (pass_mode_flags & flagMask) == kICMCompressionPassMode_NotReadyToOutputEncodedFrames ) {
|
|---|
| 1698 | logInfo(glob, "lavcEncoder: Begin pass 1.\n");
|
|---|
| 1699 | glob->ICM_passcount = 1; // analyzing pass
|
|---|
| 1700 | glob->emit_frame = FALSE;
|
|---|
| 1701 | glob->codecCont->flags |= CODEC_FLAG_PASS1;
|
|---|
| 1702 | glob->codecCont->flags &= ~CODEC_FLAG_PASS2;
|
|---|
| 1703 | } else if( (pass_mode_flags & flagMask) ==
|
|---|
| 1704 | (kICMCompressionPassMode_NoSourceFrames | kICMCompressionPassMode_NotReadyToOutputEncodedFrames) ) {
|
|---|
| 1705 | logInfo(glob, "lavcEncoder: Begin pass 1 as null pass.\n");
|
|---|
| 1706 | glob->ICM_passcount = 1; // analyzing, but null pass
|
|---|
| 1707 | glob->emit_frame = FALSE;
|
|---|
| 1708 | glob->codecCont->flags &= ~CODEC_FLAG_PASS1;
|
|---|
| 1709 | glob->codecCont->flags &= ~CODEC_FLAG_PASS2;
|
|---|
| 1710 | } else {
|
|---|
| 1711 | logInfo(glob, "lavcEncoder: Begin pass 1.\n");
|
|---|
| 1712 | fprintf(stderr, "ERROR: Invalid pass_mode_flags for this pass detected.\n");
|
|---|
| 1713 | goto bail;
|
|---|
| 1714 | }
|
|---|
| 1715 | break;
|
|---|
| 1716 | case 1:
|
|---|
| 1717 | if( (pass_mode_flags & flagMask) == kICMCompressionPassMode_OutputEncodedFrames) {
|
|---|
| 1718 | logInfo(glob, "lavcEncoder: Begin pass 2.\n");
|
|---|
| 1719 | glob->ICM_passcount = 2; // encoding pass
|
|---|
| 1720 | glob->emit_frame = TRUE;
|
|---|
| 1721 | glob->codecCont->flags &= ~CODEC_FLAG_PASS1;
|
|---|
| 1722 | glob->codecCont->flags |= CODEC_FLAG_PASS2;
|
|---|
| 1723 | } else if( (pass_mode_flags & flagMask) == kICMCompressionPassMode_NotReadyToOutputEncodedFrames ) {
|
|---|
| 1724 | logInfo(glob, "lavcEncoder: Begin pass 2 (1/2).\n");
|
|---|
| 1725 | glob->ICM_passcount = 3; // Additional encoding pass (optional)
|
|---|
| 1726 | glob->emit_frame = FALSE;
|
|---|
| 1727 | glob->codecCont->flags |= CODEC_FLAG_PASS1;
|
|---|
| 1728 | glob->codecCont->flags |= CODEC_FLAG_PASS2;
|
|---|
| 1729 | } else if( (pass_mode_flags & flagMask) ==
|
|---|
| 1730 | (kICMCompressionPassMode_NoSourceFrames | kICMCompressionPassMode_NotReadyToOutputEncodedFrames) ) {
|
|---|
| 1731 | logInfo(glob, "lavcEncoder: Begin pass 2 (1/2) as null pass.\n");
|
|---|
| 1732 | glob->ICM_passcount = 3; // Additional encoding, but null pass
|
|---|
| 1733 | glob->emit_frame = FALSE;
|
|---|
| 1734 | glob->codecCont->flags &= ~CODEC_FLAG_PASS1;
|
|---|
| 1735 | glob->codecCont->flags &= ~CODEC_FLAG_PASS2;
|
|---|
| 1736 | } else {
|
|---|
| 1737 | logInfo(glob, "lavcEncoder: Begin pass 2.\n");
|
|---|
| 1738 | fprintf(stderr, "ERROR: Invalid pass_mode_flags for this pass detected.\n");
|
|---|
| 1739 | goto bail;
|
|---|
| 1740 | }
|
|---|
| 1741 | break;
|
|---|
| 1742 | case 3: // Begin pass 3 of 3
|
|---|
| 1743 | if( (pass_mode_flags & flagMask) == kICMCompressionPassMode_OutputEncodedFrames) {
|
|---|
| 1744 | logInfo(glob, "lavcEncoder: Begin pass 2 (2/2).\n");
|
|---|
| 1745 | glob->ICM_passcount = 2; // last encoding pass
|
|---|
| 1746 | glob->emit_frame = TRUE;
|
|---|
| 1747 | glob->codecCont->flags &= ~CODEC_FLAG_PASS1;
|
|---|
| 1748 | glob->codecCont->flags |= CODEC_FLAG_PASS2;
|
|---|
| 1749 | } else if( (pass_mode_flags & flagMask) == kICMCompressionPassMode_NotReadyToOutputEncodedFrames ) {
|
|---|
| 1750 | logInfo(glob, "lavcEncoder: Begin pass 2 (1+/2+).\n");
|
|---|
| 1751 | glob->ICM_passcount = 3; // More additional encoding pass (optional)
|
|---|
| 1752 | glob->emit_frame = FALSE;
|
|---|
| 1753 | glob->codecCont->flags |= CODEC_FLAG_PASS1;
|
|---|
| 1754 | glob->codecCont->flags |= CODEC_FLAG_PASS2;
|
|---|
| 1755 | } else if( (pass_mode_flags & flagMask) ==
|
|---|
| 1756 | (kICMCompressionPassMode_NoSourceFrames | kICMCompressionPassMode_NotReadyToOutputEncodedFrames) ) {
|
|---|
| 1757 | logInfo(glob, "lavcEncoder: Begin pass 2 (1+/2+) as null pass.\n");
|
|---|
| 1758 | glob->ICM_passcount = 3; // More additional encoding, but null pass
|
|---|
| 1759 | glob->emit_frame = FALSE;
|
|---|
| 1760 | glob->codecCont->flags &= ~CODEC_FLAG_PASS1;
|
|---|
| 1761 | glob->codecCont->flags &= ~CODEC_FLAG_PASS2;
|
|---|
| 1762 | } else {
|
|---|
| 1763 | logInfo(glob, "lavcEncoder: Begin pass 2 (2/2).\n");
|
|---|
| 1764 | fprintf(stderr, "ERROR: Invalid pass_mode_flags for this pass detected.\n");
|
|---|
| 1765 | goto bail;
|
|---|
| 1766 | }
|
|---|
| 1767 | break;
|
|---|
| 1768 | default:
|
|---|
| 1769 | fprintf(stderr, "ERROR: Invalid pass count detected.\n");
|
|---|
| 1770 | goto bail;
|
|---|
| 1771 | break;
|
|---|
| 1772 | }
|
|---|
| 1773 |
|
|---|
| 1774 | if( glob->fakeMultipass ) {
|
|---|
| 1775 | glob->codecCont->flags &= ~CODEC_FLAG_PASS1;
|
|---|
| 1776 | glob->codecCont->flags &= ~CODEC_FLAG_PASS2;
|
|---|
| 1777 |
|
|---|
| 1778 | if( !glob->emit_frame ) {
|
|---|
| 1779 | logInfo(glob, "lavcEncoder: - Skipping this pass... (QSCALE or CRF is enabled)\n");
|
|---|
| 1780 | err = noErr;
|
|---|
| 1781 | goto bail;
|
|---|
| 1782 | }
|
|---|
| 1783 | }
|
|---|
| 1784 |
|
|---|
| 1785 | /* ================================================================================= */
|
|---|
| 1786 |
|
|---|
| 1787 | err = noErr;
|
|---|
| 1788 |
|
|---|
| 1789 | // Handle log file
|
|---|
| 1790 | if( !glob->fakeMultipass ) {
|
|---|
| 1791 | logDebug(glob, "lavcEncoder: path = %s\n", glob->params_opaque.log_file_path );
|
|---|
| 1792 |
|
|---|
| 1793 | #if WRITELOG
|
|---|
| 1794 | FILE *f;
|
|---|
| 1795 | int size, ret;
|
|---|
| 1796 | char *logbuffer;
|
|---|
| 1797 |
|
|---|
| 1798 | if( glob->ICM_passcount == 1 ) {
|
|---|
| 1799 |
|
|---|
| 1800 | // Pass 1; Open logfile for write
|
|---|
| 1801 | // logfile will be closed at EndPass()
|
|---|
| 1802 | f = fopen( glob->params_opaque.log_file_path, "w" );
|
|---|
| 1803 | if( !f ) {
|
|---|
| 1804 | fprintf(stderr, "ERROR: Opening log file for write failed.\n");
|
|---|
| 1805 | err = paramErr;
|
|---|
| 1806 | }
|
|---|
| 1807 | glob->logfile = f;
|
|---|
| 1808 |
|
|---|
| 1809 | } else if( glob->ICM_passcount == 2 ) {
|
|---|
| 1810 |
|
|---|
| 1811 | // Pass 2; Read from logfile into buffer
|
|---|
| 1812 | // Open, Read, Close, Remove it.
|
|---|
| 1813 | f = fopen( glob->params_opaque.log_file_path, "r" );
|
|---|
| 1814 | if( !f ) {
|
|---|
| 1815 | fprintf(stderr, "ERROR: Opening log file for read failed.\n");
|
|---|
| 1816 | err = paramErr;
|
|---|
| 1817 | } else {
|
|---|
| 1818 | fseek( f, 0, SEEK_END );
|
|---|
| 1819 | size = ftell( f );
|
|---|
| 1820 | fseek( f, 0, SEEK_SET );
|
|---|
| 1821 |
|
|---|
| 1822 | logbuffer = calloc( size + 1, 1 );
|
|---|
| 1823 | if( !logbuffer ) {
|
|---|
| 1824 | fprintf(stderr, "ERROR: Allocating log buffer failed.\n");
|
|---|
| 1825 | err = paramErr;
|
|---|
| 1826 | } else {
|
|---|
| 1827 | size = fread( logbuffer, 1, size, f );
|
|---|
| 1828 | logbuffer[size] = '\0';
|
|---|
| 1829 | glob->codecCont->stats_in = logbuffer;
|
|---|
| 1830 | }
|
|---|
| 1831 |
|
|---|
| 1832 | ret = fclose( f );
|
|---|
| 1833 | if( ret ) {
|
|---|
| 1834 | fprintf(stderr, "ERROR: Closing log file failed.(%d)\n", errno);
|
|---|
| 1835 | err = paramErr;
|
|---|
| 1836 | }
|
|---|
| 1837 | }
|
|---|
| 1838 | } else { // seems redundant...
|
|---|
| 1839 | fprintf(stderr, "ERROR: Invalid pass count detected.\n");
|
|---|
| 1840 | err = paramErr;
|
|---|
| 1841 | }
|
|---|
| 1842 | #endif
|
|---|
| 1843 | }
|
|---|
| 1844 |
|
|---|
| 1845 | // reset global values
|
|---|
| 1846 | glob->next_pts_value = 0; // seems redundant...
|
|---|
| 1847 | glob->video_size = 0;
|
|---|
| 1848 | glob->frame_count = 0;
|
|---|
| 1849 | glob->delayCount = 0;
|
|---|
| 1850 |
|
|---|
| 1851 | bail:
|
|---|
| 1852 | logDebug(glob, "lavcEncoder: emit_frame = %s\n", (glob->emit_frame ? "TRUE" : "FALSE" ));
|
|---|
| 1853 | logDebug(glob, "lavcEncoder: (OUT) pass_mode_flags = %d, glob->codecCont->flags= 0x%010x\n",
|
|---|
| 1854 | pass_mode_flags, glob->codecCont->flags);
|
|---|
| 1855 |
|
|---|
| 1856 | if(err && !glob->meetsErr) {
|
|---|
| 1857 | AudioServicesPlayAlertSound(kUserPreferredAlert); glob->meetsErr = TRUE;
|
|---|
| 1858 | }
|
|---|
| 1859 | return err;
|
|---|
| 1860 | } // ComponentCall (BeginPass)
|
|---|
| 1861 |
|
|---|
| 1862 |
|
|---|
| 1863 | // ComponentCall (EndPass) // 59
|
|---|
| 1864 | ComponentResult lavcEncoder_EndPass(lavcEncoderGlobalRecord *glob)
|
|---|
| 1865 | {
|
|---|
| 1866 | logDebug(glob, "lavcEncoder: [%08x %s]\n", glob, __FUNCTION__);
|
|---|
| 1867 |
|
|---|
| 1868 | ComponentResult err = noErr;
|
|---|
| 1869 |
|
|---|
| 1870 | // If pass 0, just print out total number of frames, and exit
|
|---|
| 1871 | if( glob->ICM_passcount <= 0 ) {
|
|---|
| 1872 | logInfo(glob, "lavcEncoder: - Total number of frames: %d.\n", glob->frame_count);
|
|---|
| 1873 | goto bail;
|
|---|
| 1874 | }
|
|---|
| 1875 |
|
|---|
| 1876 | if( glob->fakeMultipass && !glob->emit_frame ) {
|
|---|
| 1877 | // Skipping this pass... (QSCALE or CRF is enabled)
|
|---|
| 1878 | goto bail;
|
|---|
| 1879 | }
|
|---|
| 1880 |
|
|---|
| 1881 | #if USECoreVF
|
|---|
| 1882 | ICMCompressorSourceFrameRef source_frame;
|
|---|
| 1883 | if(glob->filterPreset) {
|
|---|
| 1884 | int result = CVF_ST_NOERROR;
|
|---|
| 1885 | while(glob->cvfCont->inputIndex > glob->cvfCont->outputIndex) {
|
|---|
| 1886 | if(!CFArrayGetCount(glob->cvfSourceArray)) break;
|
|---|
| 1887 |
|
|---|
| 1888 | glob->cvfInFrame->index = -1;
|
|---|
| 1889 | glob->cvfOutFrame->index = -1;
|
|---|
| 1890 | result = CVF_Context_Process(glob->cvfCont, NULL, NULL,
|
|---|
| 1891 | glob->cvfOutFrame->buffer, glob->cvfOutFrame->video);
|
|---|
| 1892 |
|
|---|
| 1893 | if( result == CVF_ST_FRAMEISREADY || result == CVF_ST_REQMOREFRAME ) {
|
|---|
| 1894 | err = noErr; /* we should update this here ! */
|
|---|
| 1895 | } else {
|
|---|
| 1896 | fprintf(stderr, "ERROR: CVF_Context_Process() returned error(%d).\n", result);
|
|---|
| 1897 | err = paramErr;
|
|---|
| 1898 | goto bail;
|
|---|
| 1899 | }
|
|---|
| 1900 |
|
|---|
| 1901 | while( CFArrayGetCount(glob->cvfCont->tempCache) ) {
|
|---|
| 1902 | result = CVF_Context_Extract(glob->cvfCont,
|
|---|
| 1903 | glob->cvfOutFrame->buffer, glob->cvfOutFrame->video);
|
|---|
| 1904 |
|
|---|
| 1905 | if(result == CVF_ST_FRAMEISREADY) {
|
|---|
| 1906 | // feed from XVF_Frame into libavcodec
|
|---|
| 1907 | CVF_CopyPlane(
|
|---|
| 1908 | CVF_GetPlaneBase(glob->cvfOutFrame, 0),
|
|---|
| 1909 | CVF_GetPlaneStride(glob->cvfOutFrame, 0), CVF_GetPlaneRow(glob->cvfOutFrame, 0),
|
|---|
| 1910 | glob->frame->data[0], glob->frame->linesize[0], glob->codecCont->height
|
|---|
| 1911 | );
|
|---|
| 1912 | CVF_CopyPlane(
|
|---|
| 1913 | CVF_GetPlaneBase(glob->cvfOutFrame, 1),
|
|---|
| 1914 | CVF_GetPlaneStride(glob->cvfOutFrame, 1), CVF_GetPlaneRow(glob->cvfOutFrame, 1),
|
|---|
| 1915 | glob->frame->data[1], glob->frame->linesize[1], glob->codecCont->height
|
|---|
| 1916 | );
|
|---|
| 1917 | CVF_CopyPlane(
|
|---|
| 1918 | CVF_GetPlaneBase(glob->cvfOutFrame, 2),
|
|---|
| 1919 | CVF_GetPlaneStride(glob->cvfOutFrame, 2), CVF_GetPlaneRow(glob->cvfOutFrame, 2),
|
|---|
| 1920 | glob->frame->data[2], glob->frame->linesize[2], glob->codecCont->height
|
|---|
| 1921 | );
|
|---|
| 1922 |
|
|---|
| 1923 | if(CFArrayGetCount(glob->cvfSourceArray)) {
|
|---|
| 1924 | source_frame = (ICMCompressorSourceFrameRef)CFArrayGetValueAtIndex(glob->cvfSourceArray, 0);
|
|---|
| 1925 | CFArrayRemoveValueAtIndex(glob->cvfSourceArray, 0);
|
|---|
| 1926 |
|
|---|
| 1927 | err = process_libAV(glob, source_frame);
|
|---|
| 1928 | if(err) goto bail;
|
|---|
| 1929 | } else {
|
|---|
| 1930 | // Broken filter output; drop output anyway
|
|---|
| 1931 | }
|
|---|
| 1932 | } else if(result != CVF_ST_REQMOREFRAME) {
|
|---|
| 1933 | // error condition
|
|---|
| 1934 | err = paramErr;
|
|---|
| 1935 | goto bail;
|
|---|
| 1936 | }
|
|---|
| 1937 | } // while( CFArrayGetCount(glob->cvfCont->tempCache) )
|
|---|
| 1938 | }
|
|---|
| 1939 | }
|
|---|
| 1940 | #endif
|
|---|
| 1941 |
|
|---|
| 1942 | // Some app does not call completeFrame at Pass 1... I need last logs, a few rows...
|
|---|
| 1943 | int limit = FF_MAX_B_FRAMES;
|
|---|
| 1944 | while( glob->delayCount ) {
|
|---|
| 1945 | // Pass NULL AVFrame into codec's buffer
|
|---|
| 1946 | glob->frame_size = avcodec_encode_video(glob->codecCont,
|
|---|
| 1947 | glob->encode_buffer, glob->encode_buffer_size, NULL);
|
|---|
| 1948 |
|
|---|
| 1949 | // Check encoded frame
|
|---|
| 1950 | if( glob->frame_size > 0 ) {
|
|---|
| 1951 | glob->delayCount--;
|
|---|
| 1952 |
|
|---|
| 1953 | // log file support
|
|---|
| 1954 | if( glob->logfile ) fprintf( glob->logfile, "%s", glob->codecCont->stats_out );
|
|---|
| 1955 | } else {
|
|---|
| 1956 | if( --limit == 0 ) {
|
|---|
| 1957 | fprintf(stderr, "ERROR: No remaining frames found\n");
|
|---|
| 1958 | fprintf(stderr, "ERROR: array_source_frame still contains %d frame(s).\n"
|
|---|
| 1959 | , (int)CFArrayGetCount(glob->array_source_frame));
|
|---|
| 1960 | err = paramErr;
|
|---|
| 1961 | break;
|
|---|
| 1962 | }
|
|---|
| 1963 | }
|
|---|
| 1964 | }
|
|---|
| 1965 |
|
|---|
| 1966 | #if WRITELOG
|
|---|
| 1967 | // Handle log file
|
|---|
| 1968 | if( glob->ICM_passcount == 1 ) { // After pass 1
|
|---|
| 1969 | if( (glob->codecCont->flags & CODEC_FLAG_PASS1) && glob->logfile ) {
|
|---|
| 1970 | logInfo(glob, "lavcEncoder: End pass 1.\n");
|
|---|
| 1971 |
|
|---|
| 1972 | fclose( glob->logfile );
|
|---|
| 1973 | glob->logfile = NULL;
|
|---|
| 1974 |
|
|---|
| 1975 | } else {
|
|---|
| 1976 | fprintf(stderr, "ERROR: Invalid flags or state detected.\n");
|
|---|
| 1977 | err = paramErr;
|
|---|
| 1978 | }
|
|---|
| 1979 | } else if( glob->ICM_passcount == 2 ) { // After pass 2
|
|---|
| 1980 | if( (glob->codecCont->flags & CODEC_FLAG_PASS2) && glob->codecCont->stats_in ) {
|
|---|
| 1981 | logInfo(glob, "lavcEncoder: End pass 2.\n");
|
|---|
| 1982 |
|
|---|
| 1983 | free(glob->codecCont->stats_in);
|
|---|
| 1984 | glob->codecCont->stats_in = NULL;
|
|---|
| 1985 |
|
|---|
| 1986 | } else if( glob->fakeMultipass ) {
|
|---|
| 1987 | ; // do nothing
|
|---|
| 1988 | } else {
|
|---|
| 1989 | fprintf(stderr, "ERROR: Invalid flags or state detected.\n");
|
|---|
| 1990 | err = paramErr;
|
|---|
| 1991 | }
|
|---|
| 1992 | } else {
|
|---|
| 1993 | fprintf(stderr, "ERROR: Invalid pass count detected.\n");
|
|---|
| 1994 | err = paramErr;
|
|---|
| 1995 | }
|
|---|
| 1996 | #endif
|
|---|
| 1997 |
|
|---|
| 1998 | bail:
|
|---|
| 1999 | // Close codec now
|
|---|
| 2000 | if( glob->codecCont ) {
|
|---|
| 2001 | if( glob->codec_is_opened ) {
|
|---|
| 2002 | avcodec_close( glob->codecCont );
|
|---|
| 2003 | glob->codec_is_opened = FALSE;
|
|---|
| 2004 | glob->extraDataReady = FALSE;
|
|---|
| 2005 | }
|
|---|
| 2006 |
|
|---|
| 2007 | #if USECoreVF
|
|---|
| 2008 | if( glob->cvfCont ) closeCoreVF( glob );
|
|---|
| 2009 | #endif
|
|---|
| 2010 |
|
|---|
| 2011 | if( glob->encode_buffer ) {
|
|---|
| 2012 | free( glob->encode_buffer );
|
|---|
| 2013 | glob->encode_buffer = NULL;
|
|---|
| 2014 | }
|
|---|
| 2015 | if( glob->planer_buffer ) {
|
|---|
| 2016 | free( glob->planer_buffer );
|
|---|
| 2017 | glob->planer_buffer = NULL;
|
|---|
| 2018 | }
|
|---|
| 2019 |
|
|---|
| 2020 | if( glob->frame ) {
|
|---|
| 2021 | av_free( glob->frame );
|
|---|
| 2022 | glob->frame = NULL;
|
|---|
| 2023 | }
|
|---|
| 2024 |
|
|---|
| 2025 | av_free( glob->codecCont );
|
|---|
| 2026 | glob->codecCont = NULL;
|
|---|
| 2027 | }
|
|---|
| 2028 |
|
|---|
| 2029 | // Show lap time
|
|---|
| 2030 | if( glob->passDate ) {
|
|---|
| 2031 | if( glob->ICM_passcount > 0 ) {
|
|---|
| 2032 | CFDateRef lastDate = CFDateCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent());
|
|---|
| 2033 | CFTimeInterval diff = CFDateGetTimeIntervalSinceDate(lastDate, glob->passDate);
|
|---|
| 2034 | CFRelease(lastDate);
|
|---|
| 2035 |
|
|---|
| 2036 | char* passstr = "";
|
|---|
| 2037 | if(glob->ICM_passcount == 1) passstr="1";
|
|---|
| 2038 | if(glob->ICM_passcount == 2) passstr="2";
|
|---|
| 2039 | if(glob->use3rdpass && glob->ICM_passcount == 3) passstr="2 (1/2)";
|
|---|
| 2040 | if(glob->use3rdpass && glob->ICM_passcount == 2) passstr="2 (2/2)";
|
|---|
| 2041 |
|
|---|
| 2042 | logInfo(glob, "lavcEncoder: - Pass %s is %.2f fps (%d frames / %.1f sec)\n"
|
|---|
| 2043 | , passstr
|
|---|
| 2044 | , (diff > 0.0 ? (double)glob->frame_count/diff : 0.0)
|
|---|
| 2045 | , glob->frame_count, (double)diff
|
|---|
| 2046 | );
|
|---|
| 2047 | }
|
|---|
| 2048 | CFRelease(glob->passDate);
|
|---|
| 2049 | glob->passDate = NULL;
|
|---|
| 2050 | }
|
|---|
| 2051 |
|
|---|
| 2052 | if(err && !glob->meetsErr) {
|
|---|
| 2053 | AudioServicesPlayAlertSound(kUserPreferredAlert); glob->meetsErr = TRUE;
|
|---|
| 2054 | }
|
|---|
| 2055 | return err;
|
|---|
| 2056 | } // ComponentCall (EndPass)
|
|---|
| 2057 |
|
|---|
| 2058 |
|
|---|
| 2059 | // ComponentCall (ProcessBetweenPasses) // 60
|
|---|
| 2060 | // We do not use ICM's default multi-pass storage file, but use temporary log file.
|
|---|
| 2061 | // This function should be called before every BeginPass...
|
|---|
| 2062 | ComponentResult lavcEncoder_ProcessBetweenPasses(lavcEncoderGlobalRecord *glob,
|
|---|
| 2063 | ICMMultiPassStorageRef storage, Boolean *done, ICMCompressionPassModeFlags *flags)
|
|---|
| 2064 | {
|
|---|
| 2065 | logDebug(glob, "lavcEncoder: [%08x %s]\n", glob, __FUNCTION__);
|
|---|
| 2066 |
|
|---|
| 2067 | ComponentResult err = noErr;
|
|---|
| 2068 | logDebug(glob, "lavcEncoder: (IN) pass_mode_flags = %d \n", *flags);
|
|---|
| 2069 |
|
|---|
| 2070 | // Check
|
|---|
| 2071 | switch (glob->ICM_passcount) {
|
|---|
| 2072 | case -1:
|
|---|
| 2073 | logDebug(glob, "lavcEncoder: Prepare pass 0 of 2.\n");
|
|---|
| 2074 | *flags = kICMCompressionPassMode_NotReadyToOutputEncodedFrames
|
|---|
| 2075 | | kICMCompressionPassMode_NoSourceFrames // null pass...
|
|---|
| 2076 | ;
|
|---|
| 2077 | break;
|
|---|
| 2078 | case 0:
|
|---|
| 2079 | logDebug(glob, "lavcEncoder: Prepare pass 1 of 2.\n");
|
|---|
| 2080 | *flags = kICMCompressionPassMode_NotReadyToOutputEncodedFrames
|
|---|
| 2081 | // | kICMCompressionPassMode_WriteToMultiPassStorage // pass 1 should be analysis pass...
|
|---|
| 2082 | ;
|
|---|
| 2083 | break;
|
|---|
| 2084 | case 1:
|
|---|
| 2085 | if( !glob->use3rdpass ) {
|
|---|
| 2086 | logDebug(glob, "lavcEncoder: Prepare pass 2 of 2.\n");
|
|---|
| 2087 | *flags = kICMCompressionPassMode_OutputEncodedFrames
|
|---|
| 2088 | // | kICMCompressionPassMode_ReadFromMultiPassStorage // pass 2 should be encoding pass...
|
|---|
| 2089 | ;
|
|---|
| 2090 | } else {
|
|---|
| 2091 | logDebug(glob, "lavcEncoder: Prepare 2 of 3.\n"); // next ICM_passcount is 3
|
|---|
| 2092 | *flags = kICMCompressionPassMode_NotReadyToOutputEncodedFrames
|
|---|
| 2093 | // | kICMCompressionPassMode_ReadFromMultiPassStorage // pass 3 is additional pass...
|
|---|
| 2094 | // | kICMCompressionPassMode_WriteToMultiPassStorage // pass 3 is additional pass...
|
|---|
| 2095 | ;
|
|---|
| 2096 | }
|
|---|
| 2097 | break;
|
|---|
| 2098 | case 3:
|
|---|
| 2099 | logDebug(glob, "lavcEncoder: Prepare pass 3 of 3.\n"); // next ICM_passcount is 2
|
|---|
| 2100 | *flags = kICMCompressionPassMode_OutputEncodedFrames
|
|---|
| 2101 | // | kICMCompressionPassMode_ReadFromMultiPassStorage // pass 2 should be encoding pass...
|
|---|
| 2102 | ;
|
|---|
| 2103 | break;
|
|---|
| 2104 | default:
|
|---|
| 2105 | fprintf(stderr, "ERROR: Invalid pass count detected.\n");
|
|---|
| 2106 | err = codecErr;
|
|---|
| 2107 | break;
|
|---|
| 2108 | }
|
|---|
| 2109 |
|
|---|
| 2110 | if( glob->fakeMultipass && !(*flags & kICMCompressionPassMode_OutputEncodedFrames) ) {
|
|---|
| 2111 | // Skipping this pass... (QSCALE or CRF is enabled)
|
|---|
| 2112 | *flags = kICMCompressionPassMode_NotReadyToOutputEncodedFrames
|
|---|
| 2113 | | kICMCompressionPassMode_NoSourceFrames // null pass...
|
|---|
| 2114 | ;
|
|---|
| 2115 | }
|
|---|
| 2116 |
|
|---|
| 2117 | logDebug(glob, "lavcEncoder: (OUT) pass_mode_flags = %d \n", *flags);
|
|---|
| 2118 | *done = TRUE;
|
|---|
| 2119 |
|
|---|
| 2120 | if(err && !glob->meetsErr) {
|
|---|
| 2121 | AudioServicesPlayAlertSound(kUserPreferredAlert); glob->meetsErr = TRUE;
|
|---|
| 2122 | }
|
|---|
| 2123 | return err;
|
|---|
| 2124 | } // ComponentCall (ProcessBetweenPasses)
|
|---|
| 2125 |
|
|---|
| 2126 |
|
|---|
| 2127 | #pragma mark -
|
|---|
| 2128 | #pragma mark Private Functions
|
|---|
| 2129 |
|
|---|
| 2130 |
|
|---|
| 2131 | static OSStatus setup_codecCont(lavcEncoderGlobalRecord *glob)
|
|---|
| 2132 | {
|
|---|
| 2133 | // logDebug(NULL, "lavcEncoder: [%08x %s]\n", glob, __FUNCTION__);
|
|---|
| 2134 |
|
|---|
| 2135 | OSStatus err = paramErr;
|
|---|
| 2136 |
|
|---|
| 2137 | #if X264
|
|---|
| 2138 | // Adjust values same as x264 default
|
|---|
| 2139 | glob->codecCont->partitions = X264_PART_I4X4 | X264_PART_I8X8 | X264_PART_P8X8 | X264_PART_B8X8;
|
|---|
| 2140 | #endif
|
|---|
| 2141 | #if XVID
|
|---|
| 2142 | glob->codecCont->rc_strategy = FF_RC_STRATEGY_XVID;
|
|---|
| 2143 | glob->codecCont->b_quant_offset = 1.0;
|
|---|
| 2144 | #endif
|
|---|
| 2145 |
|
|---|
| 2146 | /* ==================================== */
|
|---|
| 2147 |
|
|---|
| 2148 | // Update Flags
|
|---|
| 2149 | if( glob->params.FLAG_QSCALE ) glob->codecCont->flags |= CODEC_FLAG_QSCALE;
|
|---|
| 2150 | else glob->codecCont->flags &= ~ CODEC_FLAG_QSCALE;
|
|---|
| 2151 |
|
|---|
| 2152 | if( glob->params.FLAG_4MV ) glob->codecCont->flags |= CODEC_FLAG_4MV;
|
|---|
| 2153 | else glob->codecCont->flags &= ~ CODEC_FLAG_4MV;
|
|---|
| 2154 |
|
|---|
| 2155 | if( glob->params.FLAG_QPEL ) glob->codecCont->flags |= CODEC_FLAG_QPEL;
|
|---|
| 2156 | else glob->codecCont->flags &= ~ CODEC_FLAG_QPEL;
|
|---|
| 2157 |
|
|---|
| 2158 | if( glob->params.FLAG_GMC ) glob->codecCont->flags |= CODEC_FLAG_GMC;
|
|---|
| 2159 | else glob->codecCont->flags &= ~ CODEC_FLAG_GMC;
|
|---|
| 2160 |
|
|---|
| 2161 | if( glob->params.FLAG_MV0 ) glob->codecCont->flags |= CODEC_FLAG_MV0;
|
|---|
| 2162 | else glob->codecCont->flags &= ~ CODEC_FLAG_MV0;
|
|---|
| 2163 |
|
|---|
| 2164 | if( glob->params.FLAG_PART ) glob->codecCont->flags |= CODEC_FLAG_PART;
|
|---|
| 2165 | else glob->codecCont->flags &= ~ CODEC_FLAG_PART;
|
|---|
| 2166 |
|
|---|
| 2167 | if( glob->params.FLAG_LOOP_FILTER ) glob->codecCont->flags |= CODEC_FLAG_LOOP_FILTER;
|
|---|
| 2168 | else glob->codecCont->flags &= ~ CODEC_FLAG_LOOP_FILTER;
|
|---|
| 2169 |
|
|---|
| 2170 | if( glob->params.FLAG_PSNR ) glob->codecCont->flags |= CODEC_FLAG_PSNR;
|
|---|
| 2171 | else glob->codecCont->flags &= ~ CODEC_FLAG_PSNR;
|
|---|
| 2172 |
|
|---|
| 2173 | if( glob->params.FLAG_NORMALIZE_AQP ) glob->codecCont->flags |= CODEC_FLAG_NORMALIZE_AQP;
|
|---|
| 2174 | else glob->codecCont->flags &= ~ CODEC_FLAG_NORMALIZE_AQP;
|
|---|
| 2175 |
|
|---|
| 2176 | if( glob->params.FLAG_INTERLACED_DCT ) glob->codecCont->flags |= CODEC_FLAG_INTERLACED_DCT;
|
|---|
| 2177 | else glob->codecCont->flags &= ~ CODEC_FLAG_INTERLACED_DCT;
|
|---|
| 2178 |
|
|---|
| 2179 | if( glob->params.FLAG_AC_PRED ) glob->codecCont->flags |= CODEC_FLAG_AC_PRED;
|
|---|
| 2180 | else glob->codecCont->flags &= ~ CODEC_FLAG_AC_PRED;
|
|---|
| 2181 |
|
|---|
| 2182 | if( glob->params.FLAG_CBP_RD ) glob->codecCont->flags |= CODEC_FLAG_CBP_RD;
|
|---|
| 2183 | else glob->codecCont->flags &= ~ CODEC_FLAG_CBP_RD;
|
|---|
| 2184 |
|
|---|
| 2185 | if( glob->params.FLAG_QP_RD ) glob->codecCont->flags |= CODEC_FLAG_QP_RD;
|
|---|
| 2186 | else glob->codecCont->flags &= ~ CODEC_FLAG_QP_RD;
|
|---|
| 2187 |
|
|---|
| 2188 | if( glob->params.FLAG_CLOSED_GOP ) glob->codecCont->flags |= CODEC_FLAG_CLOSED_GOP;
|
|---|
| 2189 | else glob->codecCont->flags &= ~ CODEC_FLAG_CLOSED_GOP;
|
|---|
| 2190 |
|
|---|
| 2191 | if( glob->params.FLAG2_BPYRAMID ) glob->codecCont->flags2 |= CODEC_FLAG2_BPYRAMID;
|
|---|
| 2192 | else glob->codecCont->flags2 &= ~ CODEC_FLAG2_BPYRAMID;
|
|---|
| 2193 |
|
|---|
| 2194 | if( glob->params.FLAG2_WPRED ) glob->codecCont->flags2 |= CODEC_FLAG2_WPRED;
|
|---|
| 2195 | else glob->codecCont->flags2 &= ~ CODEC_FLAG2_WPRED;
|
|---|
| 2196 |
|
|---|
| 2197 | if( glob->params.FLAG2_MIXED_REFS ) glob->codecCont->flags2 |= CODEC_FLAG2_MIXED_REFS;
|
|---|
| 2198 | else glob->codecCont->flags2 &= ~ CODEC_FLAG2_MIXED_REFS;
|
|---|
| 2199 |
|
|---|
| 2200 | if( glob->params.FLAG2_8X8DCT ) glob->codecCont->flags2 |= CODEC_FLAG2_8X8DCT;
|
|---|
| 2201 | else glob->codecCont->flags2 &= ~ CODEC_FLAG2_8X8DCT;
|
|---|
| 2202 |
|
|---|
| 2203 | if( glob->params.FLAG2_FASTPSKIP ) glob->codecCont->flags2 |= CODEC_FLAG2_FASTPSKIP;
|
|---|
| 2204 | else glob->codecCont->flags2 &= ~ CODEC_FLAG2_FASTPSKIP;
|
|---|
| 2205 |
|
|---|
| 2206 | if( glob->params.FLAG2_AUD ) glob->codecCont->flags2 |= CODEC_FLAG2_AUD;
|
|---|
| 2207 | else glob->codecCont->flags2 &= ~ CODEC_FLAG2_AUD;
|
|---|
| 2208 |
|
|---|
| 2209 | if( glob->params.FLAG2_BRDO ) glob->codecCont->flags2 |= CODEC_FLAG2_BRDO;
|
|---|
| 2210 | else glob->codecCont->flags2 &= ~ CODEC_FLAG2_BRDO;
|
|---|
| 2211 |
|
|---|
| 2212 | if( glob->params.FLAG2_MBTREE ) glob->codecCont->flags2 |= CODEC_FLAG2_MBTREE;
|
|---|
| 2213 | else glob->codecCont->flags2 &= ~ CODEC_FLAG2_MBTREE;
|
|---|
| 2214 |
|
|---|
| 2215 | if( glob->params.FLAG2_PSY ) glob->codecCont->flags2 |= CODEC_FLAG2_PSY;
|
|---|
| 2216 | else glob->codecCont->flags2 &= ~ CODEC_FLAG2_PSY;
|
|---|
| 2217 |
|
|---|
| 2218 | if( glob->params.FLAG2_SSIM ) glob->codecCont->flags2 |= CODEC_FLAG2_SSIM;
|
|---|
| 2219 | else glob->codecCont->flags2 &= ~ CODEC_FLAG2_SSIM;
|
|---|
| 2220 |
|
|---|
| 2221 | /* ==================================== */
|
|---|
| 2222 |
|
|---|
| 2223 | // -mbd ; macroblock decision mode
|
|---|
| 2224 | switch( glob->params.MB_DECISION ) {
|
|---|
| 2225 | case 1:
|
|---|
| 2226 | glob->codecCont->mb_decision = FF_MB_DECISION_SIMPLE;
|
|---|
| 2227 | break;
|
|---|
| 2228 | case 2:
|
|---|
| 2229 | glob->codecCont->mb_decision = FF_MB_DECISION_BITS;
|
|---|
| 2230 | break;
|
|---|
| 2231 | case 3:
|
|---|
| 2232 | glob->codecCont->mb_decision = FF_MB_DECISION_RD;
|
|---|
| 2233 | break;
|
|---|
| 2234 | default:
|
|---|
| 2235 | glob->codecCont->mb_decision = FF_MB_DECISION_SIMPLE;
|
|---|
| 2236 | break;
|
|---|
| 2237 | }
|
|---|
| 2238 |
|
|---|
| 2239 | // -qsquish ; ratecontrol qmin qmax limiting method. 0 is clipping.
|
|---|
| 2240 | glob->codecCont->rc_qsquish = (glob->params.RC_QSQUISH ? 1 : 0);
|
|---|
| 2241 |
|
|---|
| 2242 | // -mpeg_quant ; quantizer h263/mpeg. 0 is h263 quant.
|
|---|
| 2243 | glob->codecCont->mpeg_quant = (glob->params.MPEG_QUANT ? 1 : 0);
|
|---|
| 2244 |
|
|---|
| 2245 | // -threads ; worker thread count
|
|---|
| 2246 | switch( glob->params.THREADS ) {
|
|---|
| 2247 | case 1:
|
|---|
| 2248 | glob->codecCont->thread_count = 1;
|
|---|
| 2249 | break;
|
|---|
| 2250 | case 2:
|
|---|
| 2251 | glob->codecCont->thread_count = 2;
|
|---|
| 2252 | break;
|
|---|
| 2253 | case 3:
|
|---|
| 2254 | glob->codecCont->thread_count = 4;
|
|---|
| 2255 | break;
|
|---|
| 2256 | case 4:
|
|---|
| 2257 | glob->codecCont->thread_count = 8;
|
|---|
| 2258 | break;
|
|---|
| 2259 | case 9:
|
|---|
| 2260 | glob->codecCont->thread_count = 0;
|
|---|
| 2261 | break;
|
|---|
| 2262 | default:
|
|---|
| 2263 | glob->codecCont->thread_count = 2;
|
|---|
| 2264 | break;
|
|---|
| 2265 | }
|
|---|
| 2266 |
|
|---|
| 2267 | // -me_method ; motion estimation algorithm used for video coding
|
|---|
| 2268 | switch( glob->params.ME_METHOD ) {
|
|---|
| 2269 | case 1:
|
|---|
| 2270 | glob->codecCont->me_method = ME_EPZS;
|
|---|
| 2271 | break;
|
|---|
| 2272 | case 2:
|
|---|
| 2273 | glob->codecCont->me_method = ME_HEX;
|
|---|
| 2274 | break;
|
|---|
| 2275 | case 3:
|
|---|
| 2276 | glob->codecCont->me_method = ME_UMH;
|
|---|
| 2277 | break;
|
|---|
| 2278 | case 4:
|
|---|
| 2279 | glob->codecCont->me_method = ME_FULL;
|
|---|
| 2280 | break;
|
|---|
| 2281 | case 5:
|
|---|
| 2282 | glob->codecCont->me_method = ME_X1;
|
|---|
| 2283 | break;
|
|---|
| 2284 | case 6:
|
|---|
| 2285 | glob->codecCont->me_method = ME_TESA;
|
|---|
| 2286 | break;
|
|---|
| 2287 | default:
|
|---|
| 2288 | glob->codecCont->me_method = ME_EPZS;
|
|---|
| 2289 | break;
|
|---|
| 2290 | }
|
|---|
| 2291 |
|
|---|
| 2292 | // -sc_threshold ; larger negative value uses Intra frames more frequently
|
|---|
| 2293 | glob->codecCont->scenechange_threshold = glob->params.SC_THRESHOLD;
|
|---|
| 2294 |
|
|---|
| 2295 | // -qcomp ; larger to use a lot of bit for hard scene
|
|---|
| 2296 | glob->codecCont->qcompress = glob->params.QCOMPRESS/100.0;
|
|---|
| 2297 |
|
|---|
| 2298 | // -nr ; noise reduction; larger value makes softer image
|
|---|
| 2299 | glob->codecCont->noise_reduction = glob->params.NOISE_REDUCTION;
|
|---|
| 2300 |
|
|---|
| 2301 | // -maxrate ; rate control max rate; Here it is in bps
|
|---|
| 2302 | glob->codecCont->rc_max_rate = glob->params.RC_MAXRATE * 1024;
|
|---|
| 2303 |
|
|---|
| 2304 | // -refs ; reference frames to consider for motion compensation
|
|---|
| 2305 | glob->codecCont->refs = glob->params.REFS;
|
|---|
| 2306 |
|
|---|
| 2307 | #if X264
|
|---|
| 2308 | // -me_range ; limit motion vectors range
|
|---|
| 2309 | glob->codecCont->me_range = glob->params.ME_RANGE;
|
|---|
| 2310 | #endif
|
|---|
| 2311 |
|
|---|
| 2312 | // -coder ; 1.CAVLC 2.CABAC
|
|---|
| 2313 | switch( glob->params.CODER_TYPE ) {
|
|---|
| 2314 | case 1:
|
|---|
| 2315 | glob->codecCont->coder_type = FF_CODER_TYPE_VLC;
|
|---|
| 2316 | break;
|
|---|
| 2317 | case 2:
|
|---|
| 2318 | glob->codecCont->coder_type = FF_CODER_TYPE_AC;
|
|---|
| 2319 | break;
|
|---|
| 2320 | default:
|
|---|
| 2321 | glob->codecCont->coder_type = FF_CODER_TYPE_VLC;
|
|---|
| 2322 | break;
|
|---|
| 2323 | }
|
|---|
| 2324 |
|
|---|
| 2325 | // -directpred ; direct mv prediction mode
|
|---|
| 2326 | switch( glob->params.DIRECTPRED ) {
|
|---|
| 2327 | case 1:
|
|---|
| 2328 | glob->codecCont->directpred = 0; // X264_DIRECT_PRED_NONE;
|
|---|
| 2329 | break;
|
|---|
| 2330 | case 2:
|
|---|
| 2331 | glob->codecCont->directpred = 1; // X264_DIRECT_PRED_SPATIAL;
|
|---|
| 2332 | break;
|
|---|
| 2333 | case 3:
|
|---|
| 2334 | glob->codecCont->directpred = 2; // X264_DIRECT_PRED_TEMPORAL;
|
|---|
| 2335 | break;
|
|---|
| 2336 | default:
|
|---|
| 2337 | glob->codecCont->directpred = 3; // X264_DIRECT_PRED_AUTO;
|
|---|
| 2338 | break;
|
|---|
| 2339 | }
|
|---|
| 2340 |
|
|---|
| 2341 | // -b_strategy ; strategy to choose between I/P/B-frames
|
|---|
| 2342 | glob->codecCont->b_frame_strategy = glob->params.ADAPTIVE_BFRAME;
|
|---|
| 2343 |
|
|---|
| 2344 | // -subq ; sub pel motion estimation quality
|
|---|
| 2345 | glob->codecCont->me_subpel_quality = glob->params.ME_SUBQ;
|
|---|
| 2346 |
|
|---|
| 2347 | // -trellis ; use trellis quantization
|
|---|
| 2348 | switch( glob->params.TRELLIS ) {
|
|---|
| 2349 | case 1:
|
|---|
| 2350 | glob->codecCont->trellis = 0; // Disabled
|
|---|
| 2351 | break;
|
|---|
| 2352 | case 2:
|
|---|
| 2353 | glob->codecCont->trellis = 1; // Final Only
|
|---|
| 2354 | break;
|
|---|
| 2355 | case 3:
|
|---|
| 2356 | glob->codecCont->trellis = 2; // All
|
|---|
| 2357 | break;
|
|---|
| 2358 | default:
|
|---|
| 2359 | glob->codecCont->trellis = 0; // Disabled
|
|---|
| 2360 | break;
|
|---|
| 2361 | }
|
|---|
| 2362 |
|
|---|
| 2363 | // (-turbo) ; Faster first pass mode
|
|---|
| 2364 | // no code here... but in EncodeFrame()
|
|---|
| 2365 |
|
|---|
| 2366 | // -cmp 256; chroma ME for subpel and mode decision in P-frames
|
|---|
| 2367 | if( glob->params.CHROMA_ME ) glob->codecCont->me_cmp |= FF_CMP_CHROMA;
|
|---|
| 2368 | else glob->codecCont->me_cmp &= ~ FF_CMP_CHROMA;
|
|---|
| 2369 |
|
|---|
| 2370 | // -partp4x4 ; Analyse p8x4, p4x8, p4x4
|
|---|
| 2371 | if( glob->params.PART_4X4 ) glob->codecCont->partitions |= X264_PART_P4X4;
|
|---|
| 2372 | else glob->codecCont->partitions &= ~ X264_PART_P4X4;
|
|---|
| 2373 |
|
|---|
| 2374 | // -bidir_refine ; jointly optimize both MVs in B-frames
|
|---|
| 2375 | glob->codecCont->bidir_refine = (glob->params.BIDIR_ME ? 4 : 1);
|
|---|
| 2376 |
|
|---|
| 2377 | // Use third pass mode
|
|---|
| 2378 | // no code here...
|
|---|
| 2379 |
|
|---|
| 2380 | // -level ; H.264/AVC Level
|
|---|
| 2381 | if( glob->params.LEVEL > 9 )
|
|---|
| 2382 | glob->codecCont->level = glob->params.LEVEL;
|
|---|
| 2383 | else {
|
|---|
| 2384 | assert(glob->params.LEVEL==9);
|
|---|
| 2385 | glob->codecCont->level = 0;
|
|---|
| 2386 | }
|
|---|
| 2387 |
|
|---|
| 2388 | // -aq_mode
|
|---|
| 2389 | glob->codecCont->aq_mode = glob->params.AQ_MODE - 1;
|
|---|
| 2390 |
|
|---|
| 2391 | // -lumi_mask; luminance masking
|
|---|
| 2392 | glob->codecCont->lumi_masking = glob->params.LUMI_MASKING * 1.0;
|
|---|
| 2393 |
|
|---|
| 2394 | // -bufsize ; rate control buffer size; Here it is in bit
|
|---|
| 2395 | glob->codecCont->rc_buffer_size = glob->params.RC_BUFSIZE * 1024;
|
|---|
| 2396 | if (glob->params.RC_BUFSIZE) {
|
|---|
| 2397 | #if X264
|
|---|
| 2398 | glob->codecCont->rc_initial_buffer_occupancy = glob->params.RC_BUFSIZE * 1024 * 0.90;
|
|---|
| 2399 | #else
|
|---|
| 2400 | glob->codecCont->rc_initial_buffer_occupancy = glob->params.RC_BUFSIZE * 1024 * 3 / 4;
|
|---|
| 2401 | #endif
|
|---|
| 2402 | }
|
|---|
| 2403 |
|
|---|
| 2404 | // -deblockalpha, -deblockbeta ;
|
|---|
| 2405 | glob->codecCont->deblockalpha = glob->params.DEBLOCK_ALPHA;
|
|---|
| 2406 | glob->codecCont->deblockbeta = glob->params.DEBLOCK_BETA;
|
|---|
| 2407 |
|
|---|
| 2408 | // -aq_strength
|
|---|
| 2409 | glob->codecCont->aq_strength = glob->codecCont->aq_mode ? glob->params.AQ_STRENGTH / 100.0 : 0;
|
|---|
| 2410 |
|
|---|
| 2411 | // -psy_rd
|
|---|
| 2412 | glob->codecCont->psy_rd = glob->params.PSYRD_RDO / 10.0;
|
|---|
| 2413 |
|
|---|
| 2414 | // -psy_trellis
|
|---|
| 2415 | glob->codecCont->psy_trellis = glob->params.PSYRD_TRELLIS / 10.0;
|
|---|
| 2416 |
|
|---|
| 2417 | // -keyint_min; KEYINT_MIN
|
|---|
| 2418 | glob->codecCont->keyint_min = glob->params.KEYINT_MIN;
|
|---|
| 2419 |
|
|---|
| 2420 | // x264; --cqm
|
|---|
| 2421 | glob->params_opaque.CQM_PRESET = glob->params.CQM_PRESET;
|
|---|
| 2422 |
|
|---|
| 2423 | // x264; --dct-decimate
|
|---|
| 2424 | glob->params_opaque.NO_DCT_DECIMATE = glob->params.NO_DCT_DECIMATE;
|
|---|
| 2425 |
|
|---|
| 2426 | // -qdiff;
|
|---|
| 2427 | glob->codecCont->max_qdiff = glob->params.MAX_QDIFF;
|
|---|
| 2428 |
|
|---|
| 2429 | // -chromaoffset;
|
|---|
| 2430 | glob->codecCont->chromaoffset = glob->params.CHROMAOFFSET;
|
|---|
| 2431 |
|
|---|
| 2432 | // x264; --profile
|
|---|
| 2433 | #if X264
|
|---|
| 2434 | glob->codecCont->profile = glob->params.X264PROFILE;
|
|---|
| 2435 | #endif
|
|---|
| 2436 |
|
|---|
| 2437 | // x264; --preset
|
|---|
| 2438 | glob->params_opaque.X264PRESET = glob->params.X264PRESET;
|
|---|
| 2439 |
|
|---|
| 2440 | // x264; --tune
|
|---|
| 2441 | glob->params_opaque.X264TUNE = glob->params.X264TUNE;
|
|---|
| 2442 |
|
|---|
| 2443 | // x264; --rc-lookahead
|
|---|
| 2444 | glob->codecCont->rc_lookahead = glob->params.RC_LOOKAHEAD;
|
|---|
| 2445 |
|
|---|
| 2446 | // inverse of -i_qfactor (1/n); not p-to-i but i-to-p; ex. IP_FACTOR = 1.4 * 100
|
|---|
| 2447 | glob->codecCont->i_quant_factor = 100.0 / glob->params.IP_FACTOR;
|
|---|
| 2448 |
|
|---|
| 2449 | // -b_qfactor; p-to-b; ex. PB_FACTOR = 1.3 * 100
|
|---|
| 2450 | glob->codecCont->b_quant_factor = glob->params.PB_FACTOR / 100.0;
|
|---|
| 2451 |
|
|---|
| 2452 | // x264; --weightp
|
|---|
| 2453 | glob->codecCont->weighted_p_pred = glob->params.WEIGHTP - 1;
|
|---|
| 2454 |
|
|---|
| 2455 | // -aspect
|
|---|
| 2456 | if( glob->params.USEASPECTRATIO ) {
|
|---|
| 2457 | glob->codecCont->sample_aspect_ratio.num = glob->params.hSpacing;
|
|---|
| 2458 | glob->codecCont->sample_aspect_ratio.den = glob->params.vSpacing;
|
|---|
| 2459 | } else {
|
|---|
| 2460 | glob->codecCont->sample_aspect_ratio = (AVRational){1,1};
|
|---|
| 2461 | }
|
|---|
| 2462 |
|
|---|
| 2463 | // Pass TOP Field First setting to libx264.c
|
|---|
| 2464 | glob->params_opaque.TOPFIELDFIRST = glob->params.TOPFIELDFIRST;
|
|---|
| 2465 |
|
|---|
| 2466 | // BD specific tuning flag
|
|---|
| 2467 | glob->params_opaque.BD_TUNE = glob->params.BD_TUNE;
|
|---|
| 2468 |
|
|---|
| 2469 | // x264; --fake-interlaced
|
|---|
| 2470 | glob->params_opaque.FAKEINTERLACED = glob->params.FAKEINTERLACED;
|
|---|
| 2471 |
|
|---|
| 2472 | /* ==================================== */
|
|---|
| 2473 |
|
|---|
| 2474 | // Only I frame?
|
|---|
| 2475 | glob->only_I_frame = !(ICMCompressionSessionOptionsGetAllowTemporalCompression( glob->sessionOptions ));
|
|---|
| 2476 |
|
|---|
| 2477 | // B frame support
|
|---|
| 2478 | glob->use_B_frame = ICMCompressionSessionOptionsGetAllowFrameReordering( glob->sessionOptions );
|
|---|
| 2479 |
|
|---|
| 2480 | // -g ; default 12 ; Key frame interval
|
|---|
| 2481 | if( glob->only_I_frame ) {
|
|---|
| 2482 | glob->codecCont->gop_size = 0;
|
|---|
| 2483 | } else {
|
|---|
| 2484 | int key_interval = ICMCompressionSessionOptionsGetMaxKeyFrameInterval( glob->sessionOptions );
|
|---|
| 2485 | if( key_interval ) {
|
|---|
| 2486 | key_interval = ((key_interval < 2) ? 2 : key_interval);
|
|---|
| 2487 | //key_interval = ((key_interval > 300) ? 300 : key_interval);
|
|---|
| 2488 |
|
|---|
| 2489 | glob->codecCont->gop_size = key_interval;
|
|---|
| 2490 | } else {
|
|---|
| 2491 | glob->codecCont->gop_size = 60;
|
|---|
| 2492 | }
|
|---|
| 2493 |
|
|---|
| 2494 | if (!glob->codecCont->keyint_min) glob->codecCont->keyint_min = glob->codecCont->gop_size / 10;
|
|---|
| 2495 | }
|
|---|
| 2496 |
|
|---|
| 2497 | // -bf ; use 'frames' B frames
|
|---|
| 2498 | if( glob->use_B_frame ) {
|
|---|
| 2499 | glob->codecCont->max_b_frames = glob->params.MAX_BFRAMES;
|
|---|
| 2500 | #if MPEG4
|
|---|
| 2501 | if(glob->codecCont->flags & CODEC_FLAG_CLOSED_GOP)
|
|---|
| 2502 | glob->codecCont->scenechange_threshold = INT32_MAX;
|
|---|
| 2503 | //glob->codecCont->flags2 |= CODEC_FLAG2_STRICT_GOP;
|
|---|
| 2504 | #endif
|
|---|
| 2505 | } else {
|
|---|
| 2506 | glob->codecCont->max_b_frames = 0;
|
|---|
| 2507 |
|
|---|
| 2508 | // should be off when no B-frame
|
|---|
| 2509 | glob->codecCont->flags &= ~ CODEC_FLAG_CLOSED_GOP;
|
|---|
| 2510 | glob->codecCont->flags2 &= ~ CODEC_FLAG2_BPYRAMID;
|
|---|
| 2511 | glob->codecCont->flags2 &= ~ CODEC_FLAG2_BRDO;
|
|---|
| 2512 | }
|
|---|
| 2513 |
|
|---|
| 2514 | // -b ; set video bitrate (in bits/s)
|
|---|
| 2515 | SInt32 data_rate = 0;
|
|---|
| 2516 | err = ICMCompressionSessionOptionsGetProperty(glob->sessionOptions,
|
|---|
| 2517 | kQTPropertyClass_ICMCompressionSessionOptions,
|
|---|
| 2518 | kICMCompressionSessionOptionsPropertyID_AverageDataRate,
|
|---|
| 2519 | sizeof(data_rate),
|
|---|
| 2520 | &data_rate,
|
|---|
| 2521 | NULL);
|
|---|
| 2522 | if( err ) {
|
|---|
| 2523 | fprintf(stderr, "ERROR: Get property average data rate failed.\n");
|
|---|
| 2524 | err = paramErr;
|
|---|
| 2525 | goto bail;
|
|---|
| 2526 | }
|
|---|
| 2527 | if( data_rate && !(glob->params.FLAG_QSCALE || glob->params.CRF) ) {
|
|---|
| 2528 | data_rate = ((data_rate < 8192) ? 8192 : data_rate); // 64Kbps = 8KByte/sec
|
|---|
| 2529 | data_rate = ((data_rate > 31457280) ? 31457280 : data_rate); // 240Mbps = 30MByte/sec
|
|---|
| 2530 |
|
|---|
| 2531 | glob->codecCont->bit_rate = data_rate * 8;
|
|---|
| 2532 | } else {
|
|---|
| 2533 | glob->codecCont->bit_rate = 786432; // 768Kbps = 128KByte/sec
|
|---|
| 2534 | #if X264
|
|---|
| 2535 | glob->params.CRF = TRUE;
|
|---|
| 2536 | if(glob->ICM_passcount != -1) {
|
|---|
| 2537 | glob->fakeMultipass = TRUE;
|
|---|
| 2538 | logDebug(glob, "lavcEncoder: - Force CRF; No data_rate is specified.\n");
|
|---|
| 2539 | }
|
|---|
| 2540 | #endif
|
|---|
| 2541 | #if MPEG4|XVID
|
|---|
| 2542 | glob->params.FLAG_QSCALE = TRUE;
|
|---|
| 2543 | glob->codecCont->flags |= CODEC_FLAG_QSCALE; // Force QSCALE flag on
|
|---|
| 2544 | if(glob->ICM_passcount != -1) {
|
|---|
| 2545 | glob->fakeMultipass = TRUE;
|
|---|
| 2546 | logDebug(glob, "lavcEncoder: - Force QSCALE; No data_rate is specified.\n");
|
|---|
| 2547 | }
|
|---|
| 2548 | #endif
|
|---|
| 2549 | }
|
|---|
| 2550 |
|
|---|
| 2551 | // -bt ; set video bitrate tolerance (in bits/s)
|
|---|
| 2552 | #if X264
|
|---|
| 2553 | glob->codecCont->bit_rate_tolerance = glob->codecCont->bit_rate;
|
|---|
| 2554 | #else
|
|---|
| 2555 | if( glob->codecCont->bit_rate_tolerance < glob->codecCont->bit_rate * 1.25 ) {
|
|---|
| 2556 | glob->codecCont->bit_rate_tolerance = glob->codecCont->bit_rate * 1.25;
|
|---|
| 2557 | }
|
|---|
| 2558 | #endif
|
|---|
| 2559 |
|
|---|
| 2560 | // Set quality values
|
|---|
| 2561 | CodecQ quality;
|
|---|
| 2562 | err = ICMCompressionSessionOptionsGetProperty(glob->sessionOptions,
|
|---|
| 2563 | kQTPropertyClass_ICMCompressionSessionOptions,
|
|---|
| 2564 | kICMCompressionSessionOptionsPropertyID_Quality,
|
|---|
| 2565 | sizeof(quality),
|
|---|
| 2566 | &quality,
|
|---|
| 2567 | NULL);
|
|---|
| 2568 | if( err ) {
|
|---|
| 2569 | fprintf(stderr, "ERROR: Get property quality failed.\n");
|
|---|
| 2570 | err = paramErr;
|
|---|
| 2571 | goto bail;
|
|---|
| 2572 | }
|
|---|
| 2573 |
|
|---|
| 2574 | // -qmin,-qmax ; mpeg4: 2-31 ; x264: 2-51
|
|---|
| 2575 | // crf ; x264:1.0-50.0?
|
|---|
| 2576 | // qscale ; mpeg4:>0.0, <=255.0
|
|---|
| 2577 |
|
|---|
| 2578 | #if X264
|
|---|
| 2579 | // -crf ; default 0 ; enables constant quality mode, and selects the quality
|
|---|
| 2580 | if( glob->params.LOSSLESS ) {
|
|---|
| 2581 | glob->codecCont->qmin = 0;
|
|---|
| 2582 | glob->codecCont->qmax = 51;
|
|---|
| 2583 | glob->codecCont->crf = 0;
|
|---|
| 2584 | glob->codecCont->cqp = 0;
|
|---|
| 2585 | } else if( glob->params.CRF ) {
|
|---|
| 2586 | // crf : L(33-28-23-18-13)H
|
|---|
| 2587 | if(glob->params.OVERRIDECRFQSCALE)
|
|---|
| 2588 | glob->codecCont->crf = glob->params.USERCRFQSCALE;
|
|---|
| 2589 | else
|
|---|
| 2590 | glob->codecCont->crf = 33.0 - (20.0 * quality ) / codecLosslessQuality;
|
|---|
| 2591 |
|
|---|
| 2592 | if(glob->params.OVERRIDEQMIN)
|
|---|
| 2593 | glob->codecCont->qmin = glob->params.USERQMIN;
|
|---|
| 2594 | else
|
|---|
| 2595 | glob->codecCont->qmin = 4; // 0 is x264 default, but Apple H.264 decoder is XXXX...
|
|---|
| 2596 | glob->codecCont->qmax = 51; // x264 default
|
|---|
| 2597 | } else {
|
|---|
| 2598 | // qmin : L(33-28-23-18-13)H
|
|---|
| 2599 | // qmax : L(51-51-51-51-51)H
|
|---|
| 2600 | if(glob->params.OVERRIDEQMIN)
|
|---|
| 2601 | glob->codecCont->qmin = glob->params.USERQMIN;
|
|---|
| 2602 | else
|
|---|
| 2603 | glob->codecCont->qmin = 33.0 - (20.0 * quality ) / codecLosslessQuality;
|
|---|
| 2604 |
|
|---|
| 2605 | glob->codecCont->qmax = 51; // x264 default
|
|---|
| 2606 | }
|
|---|
| 2607 |
|
|---|
| 2608 | #endif
|
|---|
| 2609 | #if MPEG4|XVID
|
|---|
| 2610 | // -qscale ; default 0 ; use fixed qscale
|
|---|
| 2611 | if( glob->params.FLAG_QSCALE ) {
|
|---|
| 2612 | // global_quality : L(10.0- -6.0- -2.0)H
|
|---|
| 2613 | if(glob->params.OVERRIDECRFQSCALE)
|
|---|
| 2614 | glob->codecCont->global_quality = glob->params.USERCRFQSCALE;
|
|---|
| 2615 | else {
|
|---|
| 2616 | float video_qscale = 10.0-8.0*quality/codecLosslessQuality;
|
|---|
| 2617 | glob->codecCont->global_quality = FF_QP2LAMBDA * video_qscale;
|
|---|
| 2618 | }
|
|---|
| 2619 |
|
|---|
| 2620 | glob->codecCont->qmin = 2; // ffmpeg default
|
|---|
| 2621 | glob->codecCont->qmax = 31; // ffmpeg default
|
|---|
| 2622 | } else {
|
|---|
| 2623 | // qmin : L(10- 8- 6- 4- 2)H
|
|---|
| 2624 | // qmax : L(16-14-12-10- 8)H
|
|---|
| 2625 | if(glob->params.OVERRIDEQMIN)
|
|---|
| 2626 | glob->codecCont->qmin = glob->params.USERQMIN;
|
|---|
| 2627 | else
|
|---|
| 2628 | glob->codecCont->qmin = 10.5 - (8.0 * quality) / codecLosslessQuality;
|
|---|
| 2629 |
|
|---|
| 2630 | glob->codecCont->qmax = 31; // ffmpeg default
|
|---|
| 2631 | }
|
|---|
| 2632 | #endif
|
|---|
| 2633 |
|
|---|
| 2634 | // Set frame rate
|
|---|
| 2635 | // -r ; default 25/1 ; constant frame rate
|
|---|
| 2636 | Fixed frame_rate;
|
|---|
| 2637 | err = ICMCompressionSessionOptionsGetProperty(glob->sessionOptions,
|
|---|
| 2638 | kQTPropertyClass_ICMCompressionSessionOptions,
|
|---|
| 2639 | kICMCompressionSessionOptionsPropertyID_ExpectedFrameRate,
|
|---|
| 2640 | sizeof(frame_rate),
|
|---|
| 2641 | &frame_rate,
|
|---|
| 2642 | NULL);
|
|---|
| 2643 | if( err ) {
|
|---|
| 2644 | fprintf(stderr, "ERROR: Get property expected frame rate failed.\n");
|
|---|
| 2645 | err = paramErr;
|
|---|
| 2646 | goto bail;
|
|---|
| 2647 | }
|
|---|
| 2648 | if( !frame_rate ) {
|
|---|
| 2649 | // this is a temporal value just when codec is not opened
|
|---|
| 2650 | // If user does not specify expected framerate, rate control may not work well
|
|---|
| 2651 |
|
|---|
| 2652 | switch( glob->params.NATIVE_FPS ) {
|
|---|
| 2653 | case 1:
|
|---|
| 2654 | frame_rate=FloatToFixed(30000.0/1001);
|
|---|
| 2655 | break;
|
|---|
| 2656 | case 2:
|
|---|
| 2657 | frame_rate=FloatToFixed(25.0);
|
|---|
| 2658 | break;
|
|---|
| 2659 | case 3:
|
|---|
| 2660 | frame_rate=FloatToFixed(24000.0/1001);
|
|---|
| 2661 | break;
|
|---|
| 2662 | case 11:
|
|---|
| 2663 | frame_rate=FloatToFixed(30000.0/1001/2);
|
|---|
| 2664 | break;
|
|---|
| 2665 | case 12:
|
|---|
| 2666 | frame_rate=FloatToFixed(25.0/2);
|
|---|
| 2667 | break;
|
|---|
| 2668 | case 13:
|
|---|
| 2669 | frame_rate=FloatToFixed(24000.0/1001/2);
|
|---|
| 2670 | break;
|
|---|
| 2671 | case 21:
|
|---|
| 2672 | frame_rate=FloatToFixed(30000.0/1001*2);
|
|---|
| 2673 | break;
|
|---|
| 2674 | case 22:
|
|---|
| 2675 | frame_rate=FloatToFixed(25.0*2);
|
|---|
| 2676 | break;
|
|---|
| 2677 | case 23:
|
|---|
| 2678 | frame_rate=FloatToFixed(24000.0/1001*2);
|
|---|
| 2679 | break;
|
|---|
| 2680 | default:
|
|---|
| 2681 | frame_rate=FloatToFixed(30000.0/1001);
|
|---|
| 2682 | break;
|
|---|
| 2683 | }
|
|---|
| 2684 | }
|
|---|
| 2685 |
|
|---|
| 2686 | // Fixed frame rate
|
|---|
| 2687 | float fr = FixedToFloat(frame_rate);
|
|---|
| 2688 | if( abs(1000*fr - 29970) < 10 ) {
|
|---|
| 2689 | glob->codecCont->time_base = (AVRational){1001, 30000}; // pts count up by 1
|
|---|
| 2690 | } else
|
|---|
| 2691 | if( abs(1000*fr - 23976) < 10 ) {
|
|---|
| 2692 | glob->codecCont->time_base = (AVRational){1001, 24000}; // pts count up by 1
|
|---|
| 2693 | } else
|
|---|
| 2694 | if( abs(1000*fr - 59940) < 10 ) {
|
|---|
| 2695 | glob->codecCont->time_base = (AVRational){1001, 60000}; // pts count up by 1
|
|---|
| 2696 | } else
|
|---|
| 2697 | if( abs(1000*fr - 47952) < 10 ) {
|
|---|
| 2698 | glob->codecCont->time_base = (AVRational){1001, 48000}; // pts count up by 1
|
|---|
| 2699 | } else {
|
|---|
| 2700 | glob->codecCont->time_base = (AVRational){30000.0/fr, 30000}; // pts count up by 1
|
|---|
| 2701 | }
|
|---|
| 2702 |
|
|---|
| 2703 | int i= av_gcd(glob->codecCont->time_base.den, glob->codecCont->time_base.num);
|
|---|
| 2704 | if(i > 1){
|
|---|
| 2705 | glob->codecCont->time_base.den /= i;
|
|---|
| 2706 | glob->codecCont->time_base.num /= i;
|
|---|
| 2707 | }
|
|---|
| 2708 |
|
|---|
| 2709 | // Update color information in codecCont
|
|---|
| 2710 | if( glob->add_nclc ) {
|
|---|
| 2711 | switch (glob->params.NCLC) {
|
|---|
| 2712 | case 3: // 616
|
|---|
| 2713 | glob->codecCont->color_primaries = AVCOL_PRI_SMPTE170M; // kQTPrimaries_SMPTE_C;
|
|---|
| 2714 | glob->codecCont->color_trc = AVCOL_TRC_BT709; // kQTTransferFunction_ITU_R709_2;
|
|---|
| 2715 | glob->codecCont->colorspace = AVCOL_SPC_SMPTE170M; // kQTMatrix_ITU_R_601_4;
|
|---|
| 2716 | break;
|
|---|
| 2717 | case 4: // 516
|
|---|
| 2718 | glob->codecCont->color_primaries = AVCOL_PRI_BT470BG; // kQTPrimaries_EBU_3213;
|
|---|
| 2719 | glob->codecCont->color_trc = AVCOL_TRC_BT709; // kQTTransferFunction_ITU_R709_2;
|
|---|
| 2720 | glob->codecCont->colorspace = AVCOL_SPC_SMPTE170M; // kQTMatrix_ITU_R_601_4;
|
|---|
| 2721 | break;
|
|---|
| 2722 | case 5: // 677
|
|---|
| 2723 | glob->codecCont->color_primaries = AVCOL_PRI_SMPTE170M; // kQTPrimaries_SMPTE_C;
|
|---|
| 2724 | glob->codecCont->color_trc = 7; // kQTTransferFunction_SMPTE_240M_1995;
|
|---|
| 2725 | glob->codecCont->colorspace = AVCOL_SPC_SMPTE240M; // kQTMatrix_SMPTE_240M_1995;
|
|---|
| 2726 | break;
|
|---|
| 2727 | case 6: // 111
|
|---|
| 2728 | glob->codecCont->color_primaries = AVCOL_PRI_BT709; // kQTPrimaries_ITU_R709_2;
|
|---|
| 2729 | glob->codecCont->color_trc = AVCOL_TRC_BT709; // kQTTransferFunction_ITU_R709_2;
|
|---|
| 2730 | glob->codecCont->colorspace = AVCOL_SPC_BT709; // kQTMatrix_ITU_R_709_2;
|
|---|
| 2731 | break;
|
|---|
| 2732 | case 7: // 222
|
|---|
| 2733 | glob->codecCont->color_primaries = AVCOL_PRI_UNSPECIFIED; // kQTPrimaries_Unknown;
|
|---|
| 2734 | glob->codecCont->color_trc = AVCOL_TRC_UNSPECIFIED; // kQTTransferFunction_Unknown;
|
|---|
| 2735 | glob->codecCont->colorspace = AVCOL_SPC_UNSPECIFIED; // kQTMatrix_Unknown;
|
|---|
| 2736 | break;
|
|---|
| 2737 | default:
|
|---|
| 2738 | break;
|
|---|
| 2739 | }
|
|---|
| 2740 | }
|
|---|
| 2741 |
|
|---|
| 2742 | err = noErr;
|
|---|
| 2743 | bail:
|
|---|
| 2744 | return err;
|
|---|
| 2745 | }
|
|---|
| 2746 |
|
|---|
| 2747 | static OSStatus open_libAV(lavcEncoderGlobalRecord *glob)
|
|---|
| 2748 | {
|
|---|
| 2749 | // logDebug(NULL, "lavcEncoder: [%08x %s]\n", glob, __FUNCTION__);
|
|---|
| 2750 |
|
|---|
| 2751 | OSStatus err = paramErr;
|
|---|
| 2752 |
|
|---|
| 2753 | // In case 'specified bit rate is too low', EncodeFrame failed at EVERY frame at pass 2.
|
|---|
| 2754 | if( glob->codec_open_failed ) return codecErr;
|
|---|
| 2755 |
|
|---|
| 2756 | logDebug(glob, "lavcEncoder: Open codec...\n");
|
|---|
| 2757 |
|
|---|
| 2758 | if( glob->ICM_passcount == 1 ) {
|
|---|
| 2759 | #if X264
|
|---|
| 2760 | int turbo=glob->params.TURBO - 1;
|
|---|
| 2761 | // Faster first-pass mode (would be same effect as: mplayer/libmpcodecs/ve_x264.c:x264enc_set_param)
|
|---|
| 2762 | if( turbo == 1 ) {
|
|---|
| 2763 | glob->codecCont->refs = (glob->codecCont->refs + 1) >> 1;
|
|---|
| 2764 | glob->codecCont->me_subpel_quality = FFMAX(FFMIN(3, glob->codecCont->me_subpel_quality-1), 1);
|
|---|
| 2765 | glob->codecCont->partitions &= ~ X264_PART_P4X4;
|
|---|
| 2766 | glob->codecCont->partitions &= ~ X264_PART_B8X8;
|
|---|
| 2767 | glob->codecCont->trellis = 0;
|
|---|
| 2768 | } else
|
|---|
| 2769 | if( turbo == 2 ) {
|
|---|
| 2770 | glob->codecCont->refs = 1; // param.i_frame_reference = 1;
|
|---|
| 2771 | glob->codecCont->flags2 &= ~ CODEC_FLAG2_8X8DCT; // param.analyse.b_transform_8x8 = 0;
|
|---|
| 2772 | glob->codecCont->partitions = 0; // param.analyse.inter = 0;
|
|---|
| 2773 | glob->codecCont->me_method = ME_EPZS; // param.analyse.i_me_method = X264_ME_DIA;
|
|---|
| 2774 | glob->codecCont->me_subpel_quality = FFMIN(2, glob->codecCont->me_subpel_quality);
|
|---|
| 2775 | // param.analyse.i_subpel_refine = X264_MIN( 2, param->analyse.i_subpel_refine );
|
|---|
| 2776 | glob->codecCont->trellis = 0; // param.analyse.i_trellis = 0;
|
|---|
| 2777 | glob->codecCont->flags2 |= CODEC_FLAG2_FASTPSKIP; // param->analyse.b_fast_pskip = 1;
|
|---|
| 2778 | }
|
|---|
| 2779 | if( turbo ) logInfo(glob, "lavcEncoder: - Faster FirstPass: Mode %d\n", turbo);
|
|---|
| 2780 | #endif
|
|---|
| 2781 | #if MPEG4
|
|---|
| 2782 | int turbo=glob->params.TURBO - 1;
|
|---|
| 2783 | // Faster first-pass mode (would be same effect as: mplayer/libmpcodecs/ve_lavc.c:config)
|
|---|
| 2784 | if( turbo ) {
|
|---|
| 2785 | glob->codecCont->me_pre_cmp = 0; // lavc_venc_context->me_pre_cmp = 0;
|
|---|
| 2786 | glob->codecCont->me_cmp = 0; // lavc_venc_context->me_cmp = 0;
|
|---|
| 2787 | glob->codecCont->me_sub_cmp = 0; // lavc_venc_context->me_sub_cmp = 0;
|
|---|
| 2788 | glob->codecCont->mb_cmp = 2; // lavc_venc_context->mb_cmp = 2;
|
|---|
| 2789 |
|
|---|
| 2790 | glob->codecCont->pre_dia_size = 0; // lavc_venc_context->pre_dia_size = 0;
|
|---|
| 2791 | glob->codecCont->dia_size = 1; // lavc_venc_context->dia_size = 1;
|
|---|
| 2792 |
|
|---|
| 2793 | glob->codecCont->quantizer_noise_shaping = 0; // lavc_venc_context->quantizer_noise_shaping = 0; // qns=0
|
|---|
| 2794 | glob->codecCont->noise_reduction = 0; // lavc_venc_context->noise_reduction = 0; // nr=0
|
|---|
| 2795 | glob->codecCont->mb_decision = 0; // lavc_venc_context->mb_decision = 0; // mbd=0
|
|---|
| 2796 |
|
|---|
| 2797 | glob->codecCont->flags &= ~ CODEC_FLAG_QPEL; // lavc_venc_context->flags &= ~CODEC_FLAG_QPEL;
|
|---|
| 2798 | glob->codecCont->flags &= ~ CODEC_FLAG_4MV; // lavc_venc_context->flags &= ~CODEC_FLAG_4MV;
|
|---|
| 2799 | glob->codecCont->trellis = 0; // lavc_venc_context->trellis = 0;
|
|---|
| 2800 | glob->codecCont->flags &= ~ CODEC_FLAG_CBP_RD; // lavc_venc_context->flags &= ~CODEC_FLAG_CBP_RD;
|
|---|
| 2801 | glob->codecCont->flags &= ~ CODEC_FLAG_QP_RD; // lavc_venc_context->flags &= ~CODEC_FLAG_QP_RD;
|
|---|
| 2802 | glob->codecCont->flags &= ~ CODEC_FLAG_MV0; // lavc_venc_context->flags &= ~CODEC_FLAG_MV0;
|
|---|
| 2803 | }
|
|---|
| 2804 | if( turbo ) logInfo(glob, "lavcEncoder: - Faster FirstPass: Enabled\n");
|
|---|
| 2805 | #endif
|
|---|
| 2806 | }
|
|---|
| 2807 | #if MPEG4
|
|---|
| 2808 | if( glob->ICM_passcount == 2 ) {
|
|---|
| 2809 | glob->codecCont->b_frame_strategy = 0;
|
|---|
| 2810 | }
|
|---|
| 2811 | #endif
|
|---|
| 2812 |
|
|---|
| 2813 | //
|
|---|
| 2814 | logInfo(glob, "lavcEncoder: - Source PixelBuffer: Native {%d/%d}, RoundedUp16 {%d/%d}\n",
|
|---|
| 2815 | glob->width, glob->height, glob->widthRoundedUp, glob->heightRoundedUp);
|
|---|
| 2816 | logInfo(glob, "lavcEncoder: - {width/height}: {%d/%d} ; time_base: {%d/%d} ; rate: %.3f\n",
|
|---|
| 2817 | glob->codecCont->width, glob->codecCont->height,
|
|---|
| 2818 | glob->codecCont->time_base.num, glob->codecCont->time_base.den,
|
|---|
| 2819 | (double)glob->codecCont->time_base.den / glob->codecCont->time_base.num
|
|---|
| 2820 | );
|
|---|
| 2821 | logInfo(glob, "lavcEncoder: - bit_rate: %d Kbps; {qmin/qmax/qscale/crf}: {%d/%d/%.2f/%.2f}\n",
|
|---|
| 2822 | glob->codecCont->bit_rate/1024, glob->codecCont->qmin, glob->codecCont->qmax,
|
|---|
| 2823 | (float)glob->codecCont->global_quality/FF_QP2LAMBDA, glob->codecCont->crf);
|
|---|
| 2824 | logInfo(glob, "lavcEncoder: - gop_size: %d ; max_b_frames: %d ; qcomp: %0.2f ; sc_threshold: %d\n",
|
|---|
| 2825 | glob->codecCont->gop_size, glob->codecCont->max_b_frames,
|
|---|
| 2826 | glob->codecCont->qcompress, glob->codecCont->scenechange_threshold);
|
|---|
| 2827 | logInfo(glob, "lavcEncoder: - thread_count: %d ; add_nclc: %s ; add_gamma: %s\n",
|
|---|
| 2828 | glob->codecCont->thread_count,
|
|---|
| 2829 | (glob->add_nclc ? "ON" : "OFF"), (glob->add_gamma ? "ON" : "OFF"));
|
|---|
| 2830 | logInfo(glob, "lavcEncoder: - bit_rate_tolerance: %d Kbit ; rc_buffer_size: %d Kbit. ; rc_max_rate = %d Kbps\n"
|
|---|
| 2831 | , glob->codecCont->bit_rate_tolerance/1024
|
|---|
| 2832 | , glob->codecCont->rc_buffer_size/1024, glob->codecCont->rc_max_rate/1024);
|
|---|
| 2833 |
|
|---|
| 2834 | #if USECoreVF
|
|---|
| 2835 | if( glob->filterString ) {
|
|---|
| 2836 | CFIndex len = CFStringGetLength(glob->filterString);
|
|---|
| 2837 | if(len) {
|
|---|
| 2838 | CFIndex max = CFStringGetMaximumSizeForEncoding(len, kCFStringEncodingASCII);
|
|---|
| 2839 | char* filterCString = calloc(1, max + 1);
|
|---|
| 2840 | CFStringGetCString(glob->filterString, filterCString, max + 1, kCFStringEncodingASCII);
|
|---|
| 2841 | logInfo(glob, "lavcEncoder: - filter: [ %s ]\n", filterCString);
|
|---|
| 2842 | free(filterCString);
|
|---|
| 2843 | }
|
|---|
| 2844 | }
|
|---|
| 2845 | #endif
|
|---|
| 2846 | #if !WRITELOG
|
|---|
| 2847 | // Pass log-file-path to x264 (with patched x264.c); log file is handled by x264 itself
|
|---|
| 2848 | // Pass AQ values to x264 (with patched x264.c); AQ is not implemented in libavcodec/libx264.c yet.
|
|---|
| 2849 | glob->codecCont->opaque = &(glob->params_opaque);
|
|---|
| 2850 | #endif
|
|---|
| 2851 |
|
|---|
| 2852 | {
|
|---|
| 2853 | // Set x264 Log level (set before opening codec)
|
|---|
| 2854 | av_log_set_level(AV_LOG_QUIET);
|
|---|
| 2855 | if( glob->params.LOG_INFO )
|
|---|
| 2856 | av_log_set_level(AV_LOG_INFO);
|
|---|
| 2857 | if( glob->params.LOG_DEBUG )
|
|---|
| 2858 | av_log_set_level(AV_LOG_VERBOSE);
|
|---|
| 2859 |
|
|---|
| 2860 | #if !X264
|
|---|
| 2861 | // Thread support
|
|---|
| 2862 | if (glob->codecCont->thread_count == 0) {
|
|---|
| 2863 | int numCpu = 0;
|
|---|
| 2864 | size_t length = sizeof(numCpu);
|
|---|
| 2865 | int select[2] = { CTL_HW, HW_NCPU };
|
|---|
| 2866 | int result = sysctl(select, 2, &numCpu, &length, NULL, 0);
|
|---|
| 2867 | if(!result && numCpu) {
|
|---|
| 2868 | glob->codecCont->thread_count = numCpu; // Ex. Two core -> two thread
|
|---|
| 2869 | } else {
|
|---|
| 2870 | glob->codecCont->thread_count = 2;
|
|---|
| 2871 | }
|
|---|
| 2872 | }
|
|---|
| 2873 | #endif
|
|---|
| 2874 |
|
|---|
| 2875 | // Make it ON before opening codec to get extradata; No SPS/PPS in data stream
|
|---|
| 2876 | glob->codecCont->flags |= CODEC_FLAG_GLOBAL_HEADER;
|
|---|
| 2877 |
|
|---|
| 2878 | // libavcodec open codec
|
|---|
| 2879 | glob->codecCont->codec_id = glob->codec->id;
|
|---|
| 2880 | glob->codecCont->codec_type = glob->codec->type;
|
|---|
| 2881 | err = avcodec_open2(glob->codecCont, glob->codec, NULL);
|
|---|
| 2882 | if( err < 0 ) {
|
|---|
| 2883 | fprintf(stderr, "ERROR: Opening codec failed.\n");
|
|---|
| 2884 | glob->codec_open_failed = TRUE;
|
|---|
| 2885 | goto bail;
|
|---|
| 2886 | }
|
|---|
| 2887 | glob->codec_is_opened = TRUE;
|
|---|
| 2888 |
|
|---|
| 2889 | // Some decoder like 3ivx needs esds info with every I-frame...sigh.
|
|---|
| 2890 | // xvidcore does not support on-the-fly update of this flag.
|
|---|
| 2891 | //glob->codecCont->flags &= ~CODEC_FLAG_GLOBAL_HEADER;
|
|---|
| 2892 |
|
|---|
| 2893 | // Adjust libavcodec default log level
|
|---|
| 2894 | av_log_set_level(AV_LOG_QUIET);
|
|---|
| 2895 | if( glob->params.LOG_INFO )
|
|---|
| 2896 | av_log_set_level(AV_LOG_INFO);
|
|---|
| 2897 | if( glob->params.LOG_DEBUG )
|
|---|
| 2898 | av_log_set_level(AV_LOG_VERBOSE);
|
|---|
| 2899 | }
|
|---|
| 2900 |
|
|---|
| 2901 | err = noErr;
|
|---|
| 2902 | bail:
|
|---|
| 2903 | return err;
|
|---|
| 2904 | }
|
|---|
| 2905 |
|
|---|
| 2906 | static OSStatus process_libAV(lavcEncoderGlobalRecord *glob, ICMCompressorSourceFrameRef source_frame)
|
|---|
| 2907 | {
|
|---|
| 2908 | // logDebug(NULL, "lavcEncoder: [%08x %s]\n", glob, __FUNCTION__);
|
|---|
| 2909 |
|
|---|
| 2910 | OSStatus err = noErr;
|
|---|
| 2911 |
|
|---|
| 2912 | #if TESTVFR
|
|---|
| 2913 | TimeValue64 displayTimeStamp, displayDuration;
|
|---|
| 2914 | TimeScale timeScale;
|
|---|
| 2915 | ICMCompressorSourceFrameGetDisplayTimeStampAndDuration( source_frame, &displayTimeStamp, &displayDuration, &timeScale, NULL);
|
|---|
| 2916 |
|
|---|
| 2917 | // Pass a AVFrame into codec's buffer
|
|---|
| 2918 | glob->frame->pts = displayTimeStamp;
|
|---|
| 2919 | #endif
|
|---|
| 2920 | #if MPEG4|XVID
|
|---|
| 2921 | glob->frame->quality = ( glob->params.FLAG_QSCALE ? glob->codecCont->global_quality : glob->frame->quality );
|
|---|
| 2922 | #endif
|
|---|
| 2923 | glob->frame_size = avcodec_encode_video(glob->codecCont,
|
|---|
| 2924 | glob->encode_buffer, glob->encode_buffer_size, glob->frame);
|
|---|
| 2925 |
|
|---|
| 2926 | /* ==================================== */
|
|---|
| 2927 |
|
|---|
| 2928 | // Prepare ExtraData(avcC/esds) ImageDescription extension
|
|---|
| 2929 | if( !glob->extraDataReady && glob->codecCont->extradata_size ) {
|
|---|
| 2930 | // remove previous ExtraData atom
|
|---|
| 2931 | while(TRUE) {
|
|---|
| 2932 | if( RemoveImageDescriptionExtension(glob->imageDescription, kExtraDataTag, 1) ) break;
|
|---|
| 2933 | }
|
|---|
| 2934 |
|
|---|
| 2935 | // Add extradata atom as ImageDescription extension
|
|---|
| 2936 | Handle extraDataHdl = NULL;
|
|---|
| 2937 | #if X264
|
|---|
| 2938 | extraDataHdl = avcCExtension(glob);
|
|---|
| 2939 | #endif
|
|---|
| 2940 | #if MPEG4|XVID
|
|---|
| 2941 | extraDataHdl = esdsExtension(glob);
|
|---|
| 2942 | #endif
|
|---|
| 2943 | if( extraDataHdl ) {
|
|---|
| 2944 | HLock(extraDataHdl);
|
|---|
| 2945 | err = AddImageDescriptionExtension(glob->imageDescription, extraDataHdl, kExtraDataTag);
|
|---|
| 2946 | if( err ) {
|
|---|
| 2947 | fprintf(stderr, "ERROR: Adding extradata failed.\n");
|
|---|
| 2948 | err = paramErr;
|
|---|
| 2949 | }
|
|---|
| 2950 | HUnlock(extraDataHdl);
|
|---|
| 2951 | DisposeHandle(extraDataHdl);
|
|---|
| 2952 | } else {
|
|---|
| 2953 | fprintf(stderr, "ERROR: Getting extradata failed.\n");
|
|---|
| 2954 | err = paramErr;
|
|---|
| 2955 | }
|
|---|
| 2956 | if( err ) goto bail;
|
|---|
| 2957 |
|
|---|
| 2958 | glob->extraDataReady = TRUE;
|
|---|
| 2959 | } // ( !glob->extraDataReady && glob->codecCont->extradata_size )
|
|---|
| 2960 |
|
|---|
| 2961 | /* ==================================== */
|
|---|
| 2962 |
|
|---|
| 2963 | // Check encoded frame
|
|---|
| 2964 | if( glob->frame_size > 0 ) {
|
|---|
| 2965 | if( glob->emit_frame ) { // Pass 2
|
|---|
| 2966 | err = emitFrameData(glob);
|
|---|
| 2967 | } else { // Pass 1
|
|---|
| 2968 | Boolean ret = removeSourceFrameForEncodedFrame(glob);
|
|---|
| 2969 | if( ret ) err = noErr;
|
|---|
| 2970 | }
|
|---|
| 2971 |
|
|---|
| 2972 | // log file support
|
|---|
| 2973 | if( glob->logfile ) fprintf( glob->logfile, "%s", glob->codecCont->stats_out );
|
|---|
| 2974 | } else {
|
|---|
| 2975 | // Encoded frames may be emitted later
|
|---|
| 2976 | err = noErr;
|
|---|
| 2977 | glob->delayCount++;
|
|---|
| 2978 | }
|
|---|
| 2979 |
|
|---|
| 2980 | bail:
|
|---|
| 2981 | return err;
|
|---|
| 2982 | }
|
|---|
| 2983 |
|
|---|
| 2984 |
|
|---|
| 2985 | // Write out encoded AVFrame into storage
|
|---|
| 2986 | static OSStatus emitFrameData(lavcEncoderGlobalRecord *glob)
|
|---|
| 2987 | {
|
|---|
| 2988 | // logDebug(NULL, "lavcEncoder: [%08x %s]\n", glob, __FUNCTION__);
|
|---|
| 2989 |
|
|---|
| 2990 | OSStatus err = noErr;
|
|---|
| 2991 | ICMCompressorSourceFrameRef source_frame = NULL;
|
|---|
| 2992 | ICMMutableEncodedFrameRef encoded_frame = NULL;
|
|---|
| 2993 |
|
|---|
| 2994 | ICMFrameType frame_type = kICMFrameType_Unknown;
|
|---|
| 2995 | MediaSampleFlags media_sample_flags = 0;
|
|---|
| 2996 |
|
|---|
| 2997 | TimeValue64 displayDurationOut, displayTimeStampOut;
|
|---|
| 2998 | TimeScale timeScaleOut;
|
|---|
| 2999 | ICMValidTimeFlags valid_time_flag;
|
|---|
| 3000 |
|
|---|
| 3001 | //
|
|---|
| 3002 | if( glob->codecCont->coded_frame == NULL ) {
|
|---|
| 3003 | // Returned non-frame data??? header or trailer?
|
|---|
| 3004 | fprintf(stderr, "ERROR: Non-frame data found.\n");
|
|---|
| 3005 | err = paramErr;
|
|---|
| 3006 | goto bail;
|
|---|
| 3007 | }
|
|---|
| 3008 |
|
|---|
| 3009 | /* ==================================== */
|
|---|
| 3010 |
|
|---|
| 3011 | {
|
|---|
| 3012 | // Get the source frame from array_source_frame using glob->codecCont->coded_frame->pts
|
|---|
| 3013 | source_frame = getSourceFrameForEncodedFrame(glob);
|
|---|
| 3014 | if( !source_frame ) {
|
|---|
| 3015 | fprintf(stderr, "ERROR: getSourceFrameForEncodedFrame() failed.\n");
|
|---|
| 3016 | err = paramErr;
|
|---|
| 3017 | goto bail;
|
|---|
| 3018 | }
|
|---|
| 3019 |
|
|---|
| 3020 | // Get source frame stats
|
|---|
| 3021 | err = ICMCompressorSourceFrameGetDisplayTimeStampAndDuration(source_frame,
|
|---|
| 3022 | &displayTimeStampOut, &displayDurationOut, &timeScaleOut, &valid_time_flag);
|
|---|
| 3023 | if( err ) {
|
|---|
| 3024 | fprintf(stderr, "ERROR: ICMCompressorSourceFrameGetDisplayTimeStampAndDuration() failed.\n");
|
|---|
| 3025 | err = paramErr;
|
|---|
| 3026 | goto bail;
|
|---|
| 3027 | }
|
|---|
| 3028 |
|
|---|
| 3029 | #if TESTVFR
|
|---|
| 3030 | // update fields; x264 wrapper does not update these field
|
|---|
| 3031 | long displayNumber = ICMCompressorSourceFrameGetDisplayNumber(source_frame);
|
|---|
| 3032 | glob->codecCont->coded_frame->display_picture_number = displayNumber - 1;
|
|---|
| 3033 | glob->codecCont->coded_frame->coded_picture_number = glob->frame_count - glob->delayCount - 1;
|
|---|
| 3034 | #if 0
|
|---|
| 3035 | logDebug(glob, "lavcEncoder: [%s] (%d, %lld, %lld, %d)\n", __FUNCTION__
|
|---|
| 3036 | , displayNumber, displayTimeStampOut, displayDurationOut, timeScaleOut);
|
|---|
| 3037 | #endif
|
|---|
| 3038 | #endif
|
|---|
| 3039 | #if 0
|
|---|
| 3040 | logDebug(glob,
|
|---|
| 3041 | "lavcEncoder: encoded pts = %lld"
|
|---|
| 3042 | " coded num = %d"
|
|---|
| 3043 | " display num = %d"
|
|---|
| 3044 | " frame = %c"
|
|---|
| 3045 | " keyframe = %s"
|
|---|
| 3046 | " quality = %d"
|
|---|
| 3047 | " \n"
|
|---|
| 3048 | , glob->codecCont->coded_frame->pts
|
|---|
| 3049 | , glob->codecCont->coded_frame->coded_picture_number
|
|---|
| 3050 | , glob->codecCont->coded_frame->display_picture_number
|
|---|
| 3051 | , av_get_picture_type_char(glob->codecCont->coded_frame->pict_type)
|
|---|
| 3052 | , ( glob->codecCont->coded_frame->key_frame ? "TRUE" : "FALSE" )
|
|---|
| 3053 | , glob->codecCont->coded_frame->quality
|
|---|
| 3054 | );
|
|---|
| 3055 | #endif
|
|---|
| 3056 | }
|
|---|
| 3057 |
|
|---|
| 3058 | /* ==================================== */
|
|---|
| 3059 |
|
|---|
| 3060 | if( glob->params.LOG_STATS ) {
|
|---|
| 3061 | char tmp[256] = {0};
|
|---|
| 3062 | char buf[4096] = {0};
|
|---|
| 3063 | snprintf(tmp,256, "STAT :%5d/%3lld+%8lld;", (int)timeScaleOut, displayDurationOut, displayTimeStampOut);
|
|---|
| 3064 | strncat(buf, tmp, 4096);
|
|---|
| 3065 |
|
|---|
| 3066 | // Show stats of every frame
|
|---|
| 3067 | double ti1, ti2, bitrate, avg_bitrate;
|
|---|
| 3068 |
|
|---|
| 3069 | if (glob->codecCont->coded_frame->quality > 100*(float)FF_QP2LAMBDA) {
|
|---|
| 3070 | snprintf(tmp,256, " frame=%6d q=**.* ",
|
|---|
| 3071 | glob->codecCont->coded_frame->display_picture_number + 1);
|
|---|
| 3072 | } else {
|
|---|
| 3073 | snprintf(tmp,256, " frame=%6d q=%4.1f ",
|
|---|
| 3074 | glob->codecCont->coded_frame->display_picture_number + 1,
|
|---|
| 3075 | glob->codecCont->coded_frame->quality/(float)FF_QP2LAMBDA);
|
|---|
| 3076 | }
|
|---|
| 3077 | strncat(buf, tmp, 4096);
|
|---|
| 3078 | #if MPEG4
|
|---|
| 3079 | if (glob->codecCont->flags&CODEC_FLAG_PSNR) {
|
|---|
| 3080 | // ref: ffmpeg.c do_video_stats()
|
|---|
| 3081 | snprintf(tmp,256, "PSNR= %6.2f ",
|
|---|
| 3082 | psnr(glob->codecCont->coded_frame->error[0]
|
|---|
| 3083 | / (glob->codecCont->width * glob->codecCont->height * 255.0 * 255.0)));
|
|---|
| 3084 | strncat(buf, tmp, 4096);
|
|---|
| 3085 | }
|
|---|
| 3086 | #endif
|
|---|
| 3087 | snprintf(tmp,256,"f_size=%6d ", glob->frame_size);
|
|---|
| 3088 | strncat(buf, tmp, 4096);
|
|---|
| 3089 |
|
|---|
| 3090 | ti1 = glob->codecCont->coded_frame->display_picture_number
|
|---|
| 3091 | * av_q2d(glob->codecCont->time_base);
|
|---|
| 3092 | ti2 = (glob->codecCont->coded_frame->display_picture_number + 1)
|
|---|
| 3093 | * av_q2d(glob->codecCont->time_base);
|
|---|
| 3094 |
|
|---|
| 3095 | glob->video_size += glob->frame_size;
|
|---|
| 3096 | bitrate = (glob->frame_size * 8) / av_q2d(glob->codecCont->time_base) / 1024.0;
|
|---|
| 3097 | avg_bitrate = (double)(glob->video_size * 8) / ti2 / 1024.0;
|
|---|
| 3098 |
|
|---|
| 3099 | snprintf(tmp,256, "s_size=%9.0fKB time= %7.2f br= %7.1fKbps avg_br= %7.1fKbps ",
|
|---|
| 3100 | (double)glob->video_size / 1024, ti1, bitrate, avg_bitrate);
|
|---|
| 3101 | strncat(buf, tmp, 4096);
|
|---|
| 3102 |
|
|---|
| 3103 | snprintf(tmp,256,"type= %c%s"
|
|---|
| 3104 | , av_get_picture_type_char(glob->codecCont->coded_frame->pict_type)
|
|---|
| 3105 | , ((glob->codecCont->coded_frame->key_frame>0) ? "DR" : "")
|
|---|
| 3106 | );
|
|---|
| 3107 | strncat(buf, tmp, 4096);
|
|---|
| 3108 | fprintf(stderr, "%s\n", buf);
|
|---|
| 3109 | }
|
|---|
| 3110 |
|
|---|
| 3111 | /* ==================================== */
|
|---|
| 3112 |
|
|---|
| 3113 | {
|
|---|
| 3114 | int droppable_frame = false;
|
|---|
| 3115 | int partial_sync_frame = false;
|
|---|
| 3116 |
|
|---|
| 3117 | // Specify frame properties from encoded AVFrame
|
|---|
| 3118 | int pict_type = 0;
|
|---|
| 3119 | int key_frame = 0;
|
|---|
| 3120 |
|
|---|
| 3121 | pict_type = glob->codecCont->coded_frame->pict_type;
|
|---|
| 3122 | key_frame = glob->codecCont->coded_frame->key_frame;
|
|---|
| 3123 | Boolean reordering = doesQueueContainEarlierDisplayNumbers(glob, ICMCompressorSourceFrameGetDisplayNumber(source_frame));
|
|---|
| 3124 |
|
|---|
| 3125 | if( key_frame && reordering )
|
|---|
| 3126 | key_frame = FALSE;
|
|---|
| 3127 | #if X264
|
|---|
| 3128 | if( !key_frame && pict_type == AV_PICTURE_TYPE_I) {
|
|---|
| 3129 | /* QuickTime always treats partial sync as MPEG-4 ASP style; i.e. OpenGOP decoding. */
|
|---|
| 3130 | /* When seek, it start decoding from sync or two partial sync frame to target frame*/
|
|---|
| 3131 | /* This is not suitable for H.264 stream. */
|
|---|
| 3132 | /* Non-IDR I frame should NOT be tagged as partial sync. */
|
|---|
| 3133 | pict_type = AV_PICTURE_TYPE_P;
|
|---|
| 3134 | }
|
|---|
| 3135 | #endif
|
|---|
| 3136 |
|
|---|
| 3137 | //
|
|---|
| 3138 | if( key_frame ) { // 1st I frame (of closed gop)
|
|---|
| 3139 | frame_type = kICMFrameType_I; // Diff btw lavc and ICM
|
|---|
| 3140 | partial_sync_frame = false;
|
|---|
| 3141 | droppable_frame = false;
|
|---|
| 3142 | } else if( pict_type == AV_PICTURE_TYPE_I ) { // 1st I frame (of open gop) or Non IDR I frame
|
|---|
| 3143 | frame_type = kICMFrameType_I; // Diff btw lavc and ICM
|
|---|
| 3144 | partial_sync_frame = true;
|
|---|
| 3145 | droppable_frame = false;
|
|---|
| 3146 | } else if( pict_type == AV_PICTURE_TYPE_P ) { // P frame (Predictive)
|
|---|
| 3147 | frame_type = kICMFrameType_P;
|
|---|
| 3148 | partial_sync_frame = false;
|
|---|
| 3149 | droppable_frame = false;
|
|---|
| 3150 | } else if( pict_type == AV_PICTURE_TYPE_B ) { // B frame (Bi-directional predictive)
|
|---|
| 3151 | frame_type = kICMFrameType_B;
|
|---|
| 3152 | partial_sync_frame = false;
|
|---|
| 3153 | #if MPEG4|XVID
|
|---|
| 3154 | droppable_frame = TRUE;
|
|---|
| 3155 | #endif
|
|---|
| 3156 | #if X264
|
|---|
| 3157 | if((glob->encode_buffer[4]==0x01) // nal_ref_idc==0 && nal_unit_type==1 (0000 0001 01..)
|
|---|
| 3158 | || (glob->encode_buffer[4]==0x09 && glob->encode_buffer[10]==0x01)
|
|---|
| 3159 | // After Access Unit Delimiter NAL (0000 0001 09xx 0000 0001 01..)
|
|---|
| 3160 | || (glob->encode_buffer[4]==0x09 && glob->encode_buffer[9]==0x01)
|
|---|
| 3161 | // After Access Unit Delimiter NAL (0000 0001 09xx 0000 0101 ..) and shortStartCode
|
|---|
| 3162 | ) {
|
|---|
| 3163 | droppable_frame = TRUE;
|
|---|
| 3164 | } else {
|
|---|
| 3165 | droppable_frame = FALSE;
|
|---|
| 3166 | }
|
|---|
| 3167 | #endif
|
|---|
| 3168 | } else if( pict_type == FF_S_TYPE ) { // Not sure
|
|---|
| 3169 | frame_type = kICMFrameType_P;
|
|---|
| 3170 | partial_sync_frame = false;
|
|---|
| 3171 | droppable_frame = false;
|
|---|
| 3172 | } else if( pict_type == FF_SI_TYPE ) { // Not sure
|
|---|
| 3173 | fprintf(stderr, "ERROR: FF_SI_TYPE data returned at %010lld\n",
|
|---|
| 3174 | (long long int)glob->codecCont->coded_frame->display_picture_number+1);
|
|---|
| 3175 | err = paramErr;
|
|---|
| 3176 | goto bail;
|
|---|
| 3177 | } else if( pict_type == FF_SP_TYPE ) { // Not sure
|
|---|
| 3178 | fprintf(stderr, "ERROR: FF_SP_TYPE data returned at %010lld\n",
|
|---|
| 3179 | (long long int)glob->codecCont->coded_frame->display_picture_number+1);
|
|---|
| 3180 | err = paramErr;
|
|---|
| 3181 | goto bail;
|
|---|
| 3182 | } else { // Not sure...
|
|---|
| 3183 | fprintf(stderr, "ERROR: Unknown TYPE data returned at %010lld\n",
|
|---|
| 3184 | (long long int)glob->codecCont->coded_frame->display_picture_number+1);
|
|---|
| 3185 | err = paramErr;
|
|---|
| 3186 | goto bail;
|
|---|
| 3187 | }
|
|---|
| 3188 |
|
|---|
| 3189 | // Set up ICM media_sample_flags
|
|---|
| 3190 | if( ! key_frame )
|
|---|
| 3191 | media_sample_flags |= mediaSampleNotSync;
|
|---|
| 3192 |
|
|---|
| 3193 | // Partial Sync; Support Open-GOP/Non-IDR I frame
|
|---|
| 3194 | if( partial_sync_frame )
|
|---|
| 3195 | media_sample_flags |= mediaSamplePartialSync;
|
|---|
| 3196 |
|
|---|
| 3197 | // Droppable; seems to be imcompatible with B-Pyramid
|
|---|
| 3198 | #if STRICTFLAG
|
|---|
| 3199 | if( droppable_frame )
|
|---|
| 3200 | media_sample_flags |= mediaSampleIsNotDependedOnByOthers; // = mediaSampleDroppable;
|
|---|
| 3201 | else
|
|---|
| 3202 | media_sample_flags |= mediaSampleIsDependedOnByOthers;
|
|---|
| 3203 | #else
|
|---|
| 3204 | if( droppable_frame )
|
|---|
| 3205 | media_sample_flags |= mediaSampleDroppable;
|
|---|
| 3206 | #endif
|
|---|
| 3207 |
|
|---|
| 3208 | // Reordering support
|
|---|
| 3209 | if( reordering )
|
|---|
| 3210 | media_sample_flags |= mediaSampleEarlierDisplayTimesAllowed;
|
|---|
| 3211 |
|
|---|
| 3212 | #if STRICTFLAG
|
|---|
| 3213 | // Sample Dependencies
|
|---|
| 3214 | if(key_frame || partial_sync_frame)
|
|---|
| 3215 | media_sample_flags |= mediaSampleDoesNotDependOnOthers; // I slice or IDR slice
|
|---|
| 3216 | else
|
|---|
| 3217 | media_sample_flags |= mediaSampleDependsOnOthers; // P slice or B slice
|
|---|
| 3218 | #endif
|
|---|
| 3219 | }
|
|---|
| 3220 |
|
|---|
| 3221 | /* ==================================== */
|
|---|
| 3222 |
|
|---|
| 3223 | {
|
|---|
| 3224 | #if X264
|
|---|
| 3225 | // Get temp NAL buffer
|
|---|
| 3226 | int tempSize = glob->frame_size;
|
|---|
| 3227 |
|
|---|
| 3228 | UInt8* tempPtr = av_malloc(tempSize);
|
|---|
| 3229 | if( !tempPtr ) {
|
|---|
| 3230 | fprintf(stderr, "ERROR: av_malloc() failed.\n");
|
|---|
| 3231 | err = memFullErr;
|
|---|
| 3232 | goto bail;
|
|---|
| 3233 | }
|
|---|
| 3234 |
|
|---|
| 3235 | // Re-format NAL unit.
|
|---|
| 3236 | memcpy(tempPtr, glob->encode_buffer, tempSize);
|
|---|
| 3237 |
|
|---|
| 3238 | avc_parse_nal_units(&tempPtr, &tempSize); // This call does realloc buffer; may also be re-sized
|
|---|
| 3239 | if( !tempSize ) {
|
|---|
| 3240 | fprintf(stderr, "ERROR: avc_parse_nal_units() failed.\n");
|
|---|
| 3241 | err = paramErr;
|
|---|
| 3242 | av_free(tempPtr);
|
|---|
| 3243 | goto bail;
|
|---|
| 3244 | }
|
|---|
| 3245 |
|
|---|
| 3246 | // Create a ICMEncodedFrame for source_frame
|
|---|
| 3247 | err = ICMEncodedFrameCreateMutable(glob->session, source_frame, tempSize, &encoded_frame);
|
|---|
| 3248 | if (err || !encoded_frame) {
|
|---|
| 3249 | fprintf(stderr, "ERROR: ICMEncodedFrameCreateMutable() failed.\n");
|
|---|
| 3250 | err = paramErr;
|
|---|
| 3251 | av_free(tempPtr);
|
|---|
| 3252 | goto bail;
|
|---|
| 3253 | }
|
|---|
| 3254 |
|
|---|
| 3255 | // Put buffer from formated NAL unit into ICMEndoedFrame's buffer
|
|---|
| 3256 | memcpy(ICMEncodedFrameGetDataPtr(encoded_frame), tempPtr, tempSize);
|
|---|
| 3257 | av_free(tempPtr);
|
|---|
| 3258 |
|
|---|
| 3259 | err = ICMEncodedFrameSetDataSize(encoded_frame, tempSize);
|
|---|
| 3260 | if( err ) {
|
|---|
| 3261 | fprintf(stderr, "ERROR: ICMEncodedFrameSetDataSize() failed.\n");
|
|---|
| 3262 | err = paramErr;
|
|---|
| 3263 | goto bail;
|
|---|
| 3264 | }
|
|---|
| 3265 | #endif
|
|---|
| 3266 | #if MPEG4|XVID
|
|---|
| 3267 | // Create a ICMEncodedFrame for source_frame
|
|---|
| 3268 | err = ICMEncodedFrameCreateMutable(glob->session, source_frame, glob->frame_size, &encoded_frame);
|
|---|
| 3269 | if (err || !encoded_frame) {
|
|---|
| 3270 | fprintf(stderr, "ERROR: ICMEncodedFrameCreateMutable() failed.\n");
|
|---|
| 3271 | err = paramErr;
|
|---|
| 3272 | goto bail;
|
|---|
| 3273 | }
|
|---|
| 3274 |
|
|---|
| 3275 | // Put buffer from encoded AVFrame* into ICMEndoedFrame's buffer
|
|---|
| 3276 | memcpy(ICMEncodedFrameGetDataPtr(encoded_frame), glob->encode_buffer, glob->frame_size);
|
|---|
| 3277 |
|
|---|
| 3278 | err = ICMEncodedFrameSetDataSize(encoded_frame, glob->frame_size);
|
|---|
| 3279 | if( err ) {
|
|---|
| 3280 | fprintf(stderr, "ERROR: ICMEncodedFrameSetDataSize() failed.\n");
|
|---|
| 3281 | err = paramErr;
|
|---|
| 3282 | goto bail;
|
|---|
| 3283 | }
|
|---|
| 3284 | #endif
|
|---|
| 3285 |
|
|---|
| 3286 | // Set up encoded_frame
|
|---|
| 3287 | err = ICMEncodedFrameSetMediaSampleFlags(encoded_frame, media_sample_flags);
|
|---|
| 3288 | if( err ) {
|
|---|
| 3289 | fprintf(stderr, "ERROR: ICMEncodedFrameSetMediaSampleFlags() failed.\n");
|
|---|
| 3290 | err = paramErr;
|
|---|
| 3291 | goto bail;
|
|---|
| 3292 | }
|
|---|
| 3293 |
|
|---|
| 3294 | err = ICMEncodedFrameSetFrameType(encoded_frame, frame_type);
|
|---|
| 3295 | if( err ) {
|
|---|
| 3296 | fprintf(stderr, "ERROR: ICMEncodedFrameSetFrameType() failed.,\n");
|
|---|
| 3297 | err = paramErr;
|
|---|
| 3298 | goto bail;
|
|---|
| 3299 | }
|
|---|
| 3300 | }
|
|---|
| 3301 |
|
|---|
| 3302 | /* ==================================== */
|
|---|
| 3303 |
|
|---|
| 3304 | {
|
|---|
| 3305 | // Ready to emit data
|
|---|
| 3306 | //CFShow(encoded_frame);
|
|---|
| 3307 | //CFShow(source_frame);
|
|---|
| 3308 |
|
|---|
| 3309 | // Output the encoded frame.
|
|---|
| 3310 | err = ICMCompressorSessionEmitEncodedFrame( glob->session, encoded_frame, 1, &source_frame );
|
|---|
| 3311 |
|
|---|
| 3312 | // done with this source frame
|
|---|
| 3313 | Boolean ret;
|
|---|
| 3314 | ret = removeSourceFrame(glob, source_frame);
|
|---|
| 3315 |
|
|---|
| 3316 | if( err ) {
|
|---|
| 3317 | fprintf(stderr, "ERROR: ICMCompressorSessionEmitEncodedFrame() failed.(%d)\n", (int)err);
|
|---|
| 3318 | err = paramErr;
|
|---|
| 3319 | goto bail;
|
|---|
| 3320 | }
|
|---|
| 3321 | if( !ret ) {
|
|---|
| 3322 | fprintf(stderr, "ERROR: removeSourceFrame() failed.\n");
|
|---|
| 3323 | err = paramErr;
|
|---|
| 3324 | goto bail;
|
|---|
| 3325 | }
|
|---|
| 3326 | }
|
|---|
| 3327 |
|
|---|
| 3328 | bail:
|
|---|
| 3329 | if( encoded_frame ) ICMEncodedFrameRelease( encoded_frame );
|
|---|
| 3330 | return err;
|
|---|
| 3331 | } // emitFrameData()
|
|---|
| 3332 |
|
|---|
| 3333 |
|
|---|
| 3334 | // Create a dictionary that describes the kinds of pixel buffers that we want to receive.
|
|---|
| 3335 | static OSStatus createPixelBufferAttributesDictionary( lavcEncoderGlobalRecord *glob,
|
|---|
| 3336 | const OSType *pixelFormatList, int pixelFormatCount, CFMutableDictionaryRef *pixelBufferAttributesOut )
|
|---|
| 3337 | {
|
|---|
| 3338 | // logDebug(NULL, "lavcEncoder: [%08x %s]\n", glob, __FUNCTION__);
|
|---|
| 3339 |
|
|---|
| 3340 | OSStatus err = memFullErr;
|
|---|
| 3341 | int i;
|
|---|
| 3342 | CFMutableDictionaryRef pixelBufferAttributes = NULL;
|
|---|
| 3343 | CFNumberRef number = NULL;
|
|---|
| 3344 | CFMutableArrayRef array = NULL;
|
|---|
| 3345 | SInt32 width, height, widthRoundedUp, heightRoundedUp, extendRight, extendBottom;
|
|---|
| 3346 |
|
|---|
| 3347 | // Create Dictionary and Array
|
|---|
| 3348 | pixelBufferAttributes = CFDictionaryCreateMutable(
|
|---|
| 3349 | NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks );
|
|---|
| 3350 | if( ! pixelBufferAttributes ) goto bail;
|
|---|
| 3351 |
|
|---|
| 3352 | array = CFArrayCreateMutable( NULL, 0, &kCFTypeArrayCallBacks );
|
|---|
| 3353 | if( ! array ) goto bail;
|
|---|
| 3354 |
|
|---|
| 3355 | // Build pixel format list Array
|
|---|
| 3356 | for( i = 0; i < pixelFormatCount; i++ ) {
|
|---|
| 3357 | number = CFNumberCreate( NULL, kCFNumberSInt32Type, &pixelFormatList[i] );
|
|---|
| 3358 | CFArrayAppendValue( array, number );
|
|---|
| 3359 | CFRelease( number );
|
|---|
| 3360 | number = NULL;
|
|---|
| 3361 | }
|
|---|
| 3362 |
|
|---|
| 3363 | // Add it into Dictionary
|
|---|
| 3364 | CFDictionaryAddValue( pixelBufferAttributes, kCVPixelBufferPixelFormatTypeKey, array );
|
|---|
| 3365 | CFRelease( array );
|
|---|
| 3366 | array = NULL;
|
|---|
| 3367 |
|
|---|
| 3368 | // Add kCVPixelBufferWidthKey and kCVPixelBufferHeightKey.
|
|---|
| 3369 | width = glob->width;
|
|---|
| 3370 | height = glob->height;
|
|---|
| 3371 |
|
|---|
| 3372 | addNumberToDictionary( pixelBufferAttributes, kCVPixelBufferWidthKey, width );
|
|---|
| 3373 | addNumberToDictionary( pixelBufferAttributes, kCVPixelBufferHeightKey, height );
|
|---|
| 3374 |
|
|---|
| 3375 | // Add kCVPixelBufferExtendedPixels{Left,Top,Right,Bottom}Keys
|
|---|
| 3376 | widthRoundedUp = glob->widthRoundedUp;
|
|---|
| 3377 | heightRoundedUp = glob->heightRoundedUp;
|
|---|
| 3378 | extendRight = widthRoundedUp - width;
|
|---|
| 3379 | extendBottom = heightRoundedUp - height;
|
|---|
| 3380 |
|
|---|
| 3381 | if( extendRight || extendBottom ) {
|
|---|
| 3382 | addNumberToDictionary( pixelBufferAttributes, kCVPixelBufferExtendedPixelsRightKey, extendRight );
|
|---|
| 3383 | addNumberToDictionary( pixelBufferAttributes, kCVPixelBufferExtendedPixelsBottomKey, extendBottom );
|
|---|
| 3384 | }
|
|---|
| 3385 |
|
|---|
| 3386 | // Add kCVPixelBufferBytesPerRowAlignmentKey.
|
|---|
| 3387 | addNumberToDictionary( pixelBufferAttributes, kCVPixelBufferBytesPerRowAlignmentKey, 16 );
|
|---|
| 3388 |
|
|---|
| 3389 | // Add gamma level and YCbCr matrix.
|
|---|
| 3390 | if( glob->add_gamma ) {
|
|---|
| 3391 | addDoubleToDictionary( pixelBufferAttributes, kCVImageBufferGammaLevelKey, 2.2 );
|
|---|
| 3392 | }
|
|---|
| 3393 | if( glob->add_nclc ) {
|
|---|
| 3394 | CFStringRef ColorPrimaries = NULL;
|
|---|
| 3395 | CFStringRef TransferFunction = NULL;
|
|---|
| 3396 | CFStringRef YCbCrMatrix = NULL;
|
|---|
| 3397 | switch( glob->params.NCLC ) {
|
|---|
| 3398 | case 3: // 616
|
|---|
| 3399 | ColorPrimaries = kCVImageBufferColorPrimaries_SMPTE_C; /* AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER */
|
|---|
| 3400 | TransferFunction = kCVImageBufferTransferFunction_ITU_R_709_2; /* AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER */
|
|---|
| 3401 | YCbCrMatrix = kCVImageBufferYCbCrMatrix_ITU_R_601_4;
|
|---|
| 3402 | break;
|
|---|
| 3403 | case 4: // 516
|
|---|
| 3404 | ColorPrimaries = kCVImageBufferColorPrimaries_EBU_3213; /* AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER */
|
|---|
| 3405 | TransferFunction = kCVImageBufferTransferFunction_ITU_R_709_2; /* AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER */
|
|---|
| 3406 | YCbCrMatrix = kCVImageBufferYCbCrMatrix_ITU_R_601_4;
|
|---|
| 3407 | break;
|
|---|
| 3408 | case 5: // 677
|
|---|
| 3409 | #if 0 // Legacy 10.5.SDK on Xcode 3.1; seems to be CoreVideo header error.
|
|---|
| 3410 | ColorPrimaries = kCVImageBufferColorPrimaries_SMPTE_C; /* AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER */
|
|---|
| 3411 | TransferFunction = kCVImageBufferTransferFunction_SMPTE_C; /* AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER_BUT_DEPRECATED */
|
|---|
| 3412 | YCbCrMatrix = kCVImageBufferYCbCrMatrix_SMPTE_240M_1995;
|
|---|
| 3413 | #else // 10.6? But this const is defined inside "10.5.SDK" in Xcode 3.2!!
|
|---|
| 3414 | ColorPrimaries = kCVImageBufferColorPrimaries_SMPTE_C; /* AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER */
|
|---|
| 3415 | TransferFunction = kCVImageBufferTransferFunction_SMPTE_240M_1995; /* AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER */
|
|---|
| 3416 | YCbCrMatrix = kCVImageBufferYCbCrMatrix_SMPTE_240M_1995;
|
|---|
| 3417 | #endif
|
|---|
| 3418 | break;
|
|---|
| 3419 | case 6: // 111
|
|---|
| 3420 | ColorPrimaries = kCVImageBufferColorPrimaries_ITU_R_709_2; /* AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER */
|
|---|
| 3421 | TransferFunction = kCVImageBufferTransferFunction_ITU_R_709_2; /* AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER */
|
|---|
| 3422 | YCbCrMatrix = kCVImageBufferYCbCrMatrix_ITU_R_709_2;
|
|---|
| 3423 | break;
|
|---|
| 3424 | case 7: // 222
|
|---|
| 3425 | default:
|
|---|
| 3426 | ColorPrimaries = NULL;
|
|---|
| 3427 | TransferFunction = NULL;
|
|---|
| 3428 | YCbCrMatrix = NULL;
|
|---|
| 3429 | break;
|
|---|
| 3430 | }
|
|---|
| 3431 | if( ColorPrimaries ) /* AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER */
|
|---|
| 3432 | CFDictionaryAddValue( pixelBufferAttributes, kCVImageBufferColorPrimariesKey, ColorPrimaries);
|
|---|
| 3433 | if( TransferFunction ) /* AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER */
|
|---|
| 3434 | CFDictionaryAddValue( pixelBufferAttributes, kCVImageBufferTransferFunctionKey, TransferFunction);
|
|---|
| 3435 | if( YCbCrMatrix )
|
|---|
| 3436 | CFDictionaryAddValue( pixelBufferAttributes, kCVImageBufferYCbCrMatrixKey, YCbCrMatrix);
|
|---|
| 3437 | }
|
|---|
| 3438 |
|
|---|
| 3439 | err = noErr;
|
|---|
| 3440 | *pixelBufferAttributesOut = pixelBufferAttributes;
|
|---|
| 3441 | pixelBufferAttributes = NULL;
|
|---|
| 3442 |
|
|---|
| 3443 | bail:
|
|---|
| 3444 | if( pixelBufferAttributes ) CFRelease( pixelBufferAttributes );
|
|---|
| 3445 | if( number ) CFRelease( number );
|
|---|
| 3446 | if( array ) CFRelease( array );
|
|---|
| 3447 | return err;
|
|---|
| 3448 | } // createPixelBufferAttributesDictionary()
|
|---|
| 3449 |
|
|---|
| 3450 |
|
|---|
| 3451 | #pragma mark -
|
|---|
| 3452 |
|
|---|
| 3453 |
|
|---|
| 3454 | // Get ICMCompressorSourceFrame for encoded AVFrame from source frame queue
|
|---|
| 3455 | static ICMCompressorSourceFrameRef getSourceFrameForEncodedFrame(lavcEncoderGlobalRecord *glob)
|
|---|
| 3456 | {
|
|---|
| 3457 | // logDebug(NULL, "lavcEncoder: [%08x %s]\n", glob, __FUNCTION__);
|
|---|
| 3458 |
|
|---|
| 3459 | int index = 0;
|
|---|
| 3460 | ICMCompressorSourceFrameRef CF_value = NULL;
|
|---|
| 3461 | int count = CFArrayGetCount(glob->array_source_frame);
|
|---|
| 3462 |
|
|---|
| 3463 | // Get encoded frame's pts value
|
|---|
| 3464 | int64_t pts = glob->codecCont->coded_frame->pts;
|
|---|
| 3465 | if( pts == AV_NOPTS_VALUE )
|
|---|
| 3466 | pts = glob->next_pts_value;
|
|---|
| 3467 |
|
|---|
| 3468 | #if TESTVFR
|
|---|
| 3469 | TimeValue64 displayTimeStamp, displayDuration;
|
|---|
| 3470 | TimeScale timeScale;
|
|---|
| 3471 | for( index = 0; index < count; index++ ) {
|
|---|
| 3472 | CF_value = (ICMCompressorSourceFrameRef)CFArrayGetValueAtIndex(glob->array_source_frame, index);
|
|---|
| 3473 | ICMCompressorSourceFrameGetDisplayTimeStampAndDuration(CF_value, &displayTimeStamp, &displayDuration, &timeScale, NULL);
|
|---|
| 3474 | if( displayTimeStamp == pts ) {
|
|---|
| 3475 | glob->next_pts_value = displayTimeStamp + displayDuration;
|
|---|
| 3476 | return CF_value;
|
|---|
| 3477 | }
|
|---|
| 3478 | }
|
|---|
| 3479 | #else
|
|---|
| 3480 | for( index = 0; index < count; index++ ) {
|
|---|
| 3481 | CF_value = (ICMCompressorSourceFrameRef)CFArrayGetValueAtIndex(glob->array_source_frame, index);
|
|---|
| 3482 | if( ICMCompressorSourceFrameGetDisplayNumber(CF_value) == (pts+1) ) {
|
|---|
| 3483 | glob->next_pts_value++;
|
|---|
| 3484 | return CF_value;
|
|---|
| 3485 | }
|
|---|
| 3486 | }
|
|---|
| 3487 | #endif
|
|---|
| 3488 |
|
|---|
| 3489 | return NULL;
|
|---|
| 3490 | } // getSourceFrameForEncodedFrame()
|
|---|
| 3491 |
|
|---|
| 3492 |
|
|---|
| 3493 | // Remove specified ICMCompressorSourceFrame from source frame queue
|
|---|
| 3494 | static Boolean removeSourceFrame(lavcEncoderGlobalRecord *glob, ICMCompressorSourceFrameRef source_frame)
|
|---|
| 3495 | {
|
|---|
| 3496 | // logDebug(NULL, "lavcEncoder: [%08x %s]\n", glob, __FUNCTION__);
|
|---|
| 3497 |
|
|---|
| 3498 | int index = 0;
|
|---|
| 3499 | ICMCompressorSourceFrameRef CF_value = NULL;
|
|---|
| 3500 | int count = CFArrayGetCount(glob->array_source_frame);
|
|---|
| 3501 |
|
|---|
| 3502 | for( index = 0; index < count; index++ ) {
|
|---|
| 3503 | CF_value = (ICMCompressorSourceFrameRef)CFArrayGetValueAtIndex(glob->array_source_frame, index);
|
|---|
| 3504 | if( CF_value == source_frame ) {
|
|---|
| 3505 | CFArrayRemoveValueAtIndex(glob->array_source_frame, index);
|
|---|
| 3506 | return TRUE;
|
|---|
| 3507 | }
|
|---|
| 3508 | }
|
|---|
| 3509 |
|
|---|
| 3510 | return FALSE;
|
|---|
| 3511 | }
|
|---|
| 3512 |
|
|---|
| 3513 |
|
|---|
| 3514 | // Check if source frame queue has the frame for encoded AVFrame
|
|---|
| 3515 | static Boolean doesQueueContainEarlierDisplayNumbers( lavcEncoderGlobalRecord *glob, long display_number )
|
|---|
| 3516 | {
|
|---|
| 3517 | // logDebug(NULL, "lavcEncoder: [%08x %s]\n", glob, __FUNCTION__);
|
|---|
| 3518 |
|
|---|
| 3519 | int index = 0;
|
|---|
| 3520 | ICMCompressorSourceFrameRef CF_value = NULL;
|
|---|
| 3521 | int count = CFArrayGetCount(glob->array_source_frame);
|
|---|
| 3522 |
|
|---|
| 3523 | for( index = 0; index < count; index++ ) {
|
|---|
| 3524 | CF_value = (ICMCompressorSourceFrameRef)CFArrayGetValueAtIndex(glob->array_source_frame, index);
|
|---|
| 3525 | if( ICMCompressorSourceFrameGetDisplayNumber(CF_value) < display_number ) {
|
|---|
| 3526 | return TRUE;
|
|---|
| 3527 | }
|
|---|
| 3528 | }
|
|---|
| 3529 |
|
|---|
| 3530 | return FALSE;
|
|---|
| 3531 | }
|
|---|
| 3532 |
|
|---|
| 3533 |
|
|---|
| 3534 | // Remove ICMCompressorSourceFrame for encoded AVFrame from source frame queue
|
|---|
| 3535 | static Boolean removeSourceFrameForEncodedFrame( lavcEncoderGlobalRecord *glob )
|
|---|
| 3536 | {
|
|---|
| 3537 | // logDebug(NULL, "lavcEncoder: [%08x %s]\n", glob, __FUNCTION__);
|
|---|
| 3538 |
|
|---|
| 3539 | ICMCompressorSourceFrameRef source_frame = NULL;
|
|---|
| 3540 | Boolean ret = FALSE;
|
|---|
| 3541 |
|
|---|
| 3542 | // Here we get the source from array_source_frame by glob->codecCont->coded_frame->pts
|
|---|
| 3543 | source_frame = getSourceFrameForEncodedFrame(glob);
|
|---|
| 3544 | if( !source_frame ) {
|
|---|
| 3545 | fprintf(stderr, "ERROR: getSourceFrameForEncodedFrame() failed.\n");
|
|---|
| 3546 | goto bail;
|
|---|
| 3547 | }
|
|---|
| 3548 |
|
|---|
| 3549 | // done with this source frame
|
|---|
| 3550 | ret = removeSourceFrame(glob, source_frame);
|
|---|
| 3551 | if( !ret ) {
|
|---|
| 3552 | fprintf(stderr, "ERROR: removeSourceFrame() failed.\n");
|
|---|
| 3553 | goto bail;
|
|---|
| 3554 | }
|
|---|
| 3555 |
|
|---|
| 3556 | bail:
|
|---|
| 3557 | return ret;
|
|---|
| 3558 | }
|
|---|
| 3559 |
|
|---|
| 3560 |
|
|---|
| 3561 | #pragma mark -
|
|---|
| 3562 |
|
|---|
| 3563 |
|
|---|
| 3564 | // Prepare avcC atom for ImageDescription Extension.
|
|---|
| 3565 | static Handle avcCExtension( lavcEncoderGlobalRecord *glob )
|
|---|
| 3566 | {
|
|---|
| 3567 | // logDebug(NULL, "lavcEncoder: [%08x %s]\n", glob, __FUNCTION__);
|
|---|
| 3568 |
|
|---|
| 3569 | // This code strongly depends onto x264/encoder/encoder.c:x264_encoder_headers()
|
|---|
| 3570 | // We suppose all nal are byte aligned, and start with 0x000001(BE) ... shortstartcode
|
|---|
| 3571 | Handle avcCHdl = NULL;
|
|---|
| 3572 |
|
|---|
| 3573 | UInt8 *pSEI=NULL, *pSPS=NULL, *pPPS=NULL;
|
|---|
| 3574 | int lenOfSEI=0, lenOfSPS=0, lenOfPPS=0;
|
|---|
| 3575 | UInt8* p = (UInt8*)glob->codecCont->extradata;
|
|---|
| 3576 | UInt8* end = p+glob->codecCont->extradata_size;
|
|---|
| 3577 |
|
|---|
| 3578 | // TODO; This loop works only with single SEI/PPS/SPS. Multiple NAL not supported...
|
|---|
| 3579 | while( p + 4 < end ) {
|
|---|
| 3580 | if( 0x000001 == EndianU32_BtoN(*(UInt32*)p) >> 8) {
|
|---|
| 3581 | // NAL Start
|
|---|
| 3582 | p+=3;
|
|---|
| 3583 | switch (p[0]) {
|
|---|
| 3584 | case 0x06: // SEI NAL
|
|---|
| 3585 | if(!pSEI) pSEI = p;
|
|---|
| 3586 | if( pSPS && !lenOfSPS ) lenOfSPS = p - 3 - pSPS;
|
|---|
| 3587 | if( pPPS && !lenOfPPS ) lenOfPPS = p - 3 - pPPS;
|
|---|
| 3588 | break;
|
|---|
| 3589 | case 0x67: // SPS NAL
|
|---|
| 3590 | if( pSEI && !lenOfSEI ) lenOfSEI = p - 3 - pSEI;
|
|---|
| 3591 | if(!pSPS) pSPS = p;
|
|---|
| 3592 | if( pPPS && !lenOfPPS ) lenOfPPS = p - 3 - pPPS;
|
|---|
| 3593 | break;
|
|---|
| 3594 | case 0x68: // PPS NAL
|
|---|
| 3595 | if( pSEI && !lenOfSEI ) lenOfSEI = p - 3 - pSEI;
|
|---|
| 3596 | if( pSPS && !lenOfSPS ) lenOfSPS = p - 3 - pSPS;
|
|---|
| 3597 | if(!pPPS) pPPS = p;
|
|---|
| 3598 | break;
|
|---|
| 3599 | default:
|
|---|
| 3600 | break; // ignore
|
|---|
| 3601 | }
|
|---|
| 3602 | }
|
|---|
| 3603 | p++;
|
|---|
| 3604 | }
|
|---|
| 3605 | if( pSEI && !lenOfSEI ) lenOfSEI = end-pSEI;
|
|---|
| 3606 | if( pSPS && !lenOfSPS ) lenOfSPS = end-pSPS;
|
|---|
| 3607 | if( pPPS && !lenOfPPS ) lenOfPPS = end-pPPS;
|
|---|
| 3608 |
|
|---|
| 3609 | // Check SPS and PPS
|
|---|
| 3610 | if( !(pSPS && lenOfSPS) ) {
|
|---|
| 3611 | fprintf(stderr, "ERROR: Failed to get SPS NAL unit.\n");
|
|---|
| 3612 | goto bail;
|
|---|
| 3613 | }
|
|---|
| 3614 | if( !(pPPS && lenOfPPS) ) {
|
|---|
| 3615 | fprintf(stderr, "ERROR: Failed to get PPS NAL unit.\n");
|
|---|
| 3616 | goto bail;
|
|---|
| 3617 | }
|
|---|
| 3618 | if( !(pSEI && lenOfSEI) ) {
|
|---|
| 3619 | fprintf(stderr, "ERROR: Failed to get SEI NAL unit.\n");
|
|---|
| 3620 | /* do nothing; SEI is not mandatory */goto bail;
|
|---|
| 3621 | }
|
|---|
| 3622 |
|
|---|
| 3623 | //
|
|---|
| 3624 | int lengthOfAVCC = (1 + 3 + 1) + (1 + 2 + lenOfSPS) + (1 + 2 + lenOfPPS);
|
|---|
| 3625 | avcCHdl = NewHandleClear(lengthOfAVCC);
|
|---|
| 3626 | if( avcCHdl ) {
|
|---|
| 3627 | HLock(avcCHdl);
|
|---|
| 3628 |
|
|---|
| 3629 | char* avcC = *avcCHdl;
|
|---|
| 3630 | avcC[0] = 0x01; // version
|
|---|
| 3631 | avcC[1] = pSPS[1]; // profile
|
|---|
| 3632 | avcC[2] = pSPS[2]; // profile compatibility
|
|---|
| 3633 | avcC[3] = pSPS[3]; // level
|
|---|
| 3634 | avcC[4] = 0xFF; // 0x3F<<2 + 0x11
|
|---|
| 3635 |
|
|---|
| 3636 | avcC[5] = 0xE1; // 0x07<<5 + 1 (count of sps)
|
|---|
| 3637 | avcC[6] = lenOfSPS>>8; //
|
|---|
| 3638 | avcC[7] = lenOfSPS&0xFF; //
|
|---|
| 3639 |
|
|---|
| 3640 | memcpy(&avcC[8], pSPS, lenOfSPS);
|
|---|
| 3641 |
|
|---|
| 3642 | avcC[8+lenOfSPS] = 0x01; // 1 (count of pps)
|
|---|
| 3643 | avcC[9+lenOfSPS] = lenOfPPS>>8; //
|
|---|
| 3644 | avcC[10+lenOfSPS] = lenOfPPS&0xFF; //
|
|---|
| 3645 |
|
|---|
| 3646 | memcpy(&avcC[11+lenOfSPS], pPPS, lenOfPPS);
|
|---|
| 3647 |
|
|---|
| 3648 | HUnlock(avcCHdl);
|
|---|
| 3649 | // This handle should be released by caller
|
|---|
| 3650 | } else {
|
|---|
| 3651 | fprintf(stderr, "ERROR: NewHandleClear() failed.\n");
|
|---|
| 3652 | }
|
|---|
| 3653 |
|
|---|
| 3654 | bail:
|
|---|
| 3655 | return avcCHdl;
|
|---|
| 3656 | } // avcCExtension()
|
|---|
| 3657 |
|
|---|
| 3658 |
|
|---|
| 3659 | // Prepare elementary stream description atom for ImageDescription Extension.
|
|---|
| 3660 | static Handle esdsExtension( lavcEncoderGlobalRecord *glob )
|
|---|
| 3661 | {
|
|---|
| 3662 | // logDebug(NULL, "lavcEncoder: [%08x %s]\n", glob, __FUNCTION__);
|
|---|
| 3663 |
|
|---|
| 3664 | Handle esdsHdl = NULL;
|
|---|
| 3665 | int lengthOfHeader = 2;
|
|---|
| 3666 | int lengthOfData05 = glob->codecCont->extradata_size;
|
|---|
| 3667 | int lengthOfData04 = 1 + 1 + 3 + 4 + 4 + lengthOfHeader + lengthOfData05;
|
|---|
| 3668 | int lengthOfData06 = 1;
|
|---|
| 3669 | int lengthOfData03 = 2 + 1 + lengthOfHeader + lengthOfData04 + lengthOfHeader + lengthOfData06;
|
|---|
| 3670 | int lengthOfDataEsds = 1 + 3 + lengthOfHeader + lengthOfData03;
|
|---|
| 3671 |
|
|---|
| 3672 | if( !lengthOfData05 ) {
|
|---|
| 3673 | fprintf(stderr, "ERROR: No codec extradata found.\n");
|
|---|
| 3674 | return NULL;
|
|---|
| 3675 | }
|
|---|
| 3676 |
|
|---|
| 3677 | //
|
|---|
| 3678 | esdsHdl = NewHandleClear(lengthOfDataEsds);
|
|---|
| 3679 | if( esdsHdl ) {
|
|---|
| 3680 | HLock(esdsHdl);
|
|---|
| 3681 | char* esds = *esdsHdl; // ES Descriptor box
|
|---|
| 3682 |
|
|---|
| 3683 | esds[0] = 0; // ES Descriptor box version (1)
|
|---|
| 3684 | esds[1] = 0; // ES Descriptor box flag 0 (3) BE
|
|---|
| 3685 | esds[2] = 0;
|
|---|
| 3686 | esds[3] = 0;
|
|---|
| 3687 |
|
|---|
| 3688 | esds[4] = 0x03; // Desc03 Type ES descriptor (1)
|
|---|
| 3689 | esds[5] = lengthOfData03; // Desc03 Length (1)
|
|---|
| 3690 |
|
|---|
| 3691 | esds[6] = 0x00; // ES ID 0 (2) BE
|
|---|
| 3692 | esds[7] = 0x00;
|
|---|
| 3693 | esds[8] = 0x10; // ES Priority 16 (1) ; 00-1f available; default is 10.
|
|---|
| 3694 |
|
|---|
| 3695 | esds[9] = 0x04; // Desc04 Type Decoder config descriptor (1)
|
|---|
| 3696 | esds[10] = lengthOfData04; // Desc04 Length (1)
|
|---|
| 3697 |
|
|---|
| 3698 | esds[11] = 0x20; // Object Type ID MPEG-4 Video(1)
|
|---|
| 3699 | esds[12] = 0x11; // Stream Type Visual[6] + upstream flag0[1] + reserved1[1]
|
|---|
| 3700 |
|
|---|
| 3701 | esds[13] = 0x00; // Buffer size undefined (3) BE
|
|---|
| 3702 | esds[14] = 0x00; // Similar to ffmpeg's mp4 format default value
|
|---|
| 3703 | esds[15] = 0x00;
|
|---|
| 3704 |
|
|---|
| 3705 | esds[16] = 0x00; // Maximum bit rate 4Mbps(4) BE
|
|---|
| 3706 | esds[17] = 0x0B; // Similar to ffmpeg's mp4 format default value
|
|---|
| 3707 | esds[18] = 0xB8;
|
|---|
| 3708 | esds[19] = 0x00;
|
|---|
| 3709 |
|
|---|
| 3710 | esds[20] = 0x00; // Average bit rate undefined (4) BE
|
|---|
| 3711 | esds[21] = 0x00; // Similar to ffmpeg's mp4 format default value
|
|---|
| 3712 | esds[22] = 0x00;
|
|---|
| 3713 | esds[23] = 0x00;
|
|---|
| 3714 |
|
|---|
| 3715 | esds[24] = 0x05; // Desc05 Type Decoder specific info descriptor (1)
|
|---|
| 3716 | esds[25] = lengthOfData05; // Desc05 Length (varialble)
|
|---|
| 3717 |
|
|---|
| 3718 | esds[26+lengthOfData05] = 0x06; // Desc06 Type SL Descriptor (1)
|
|---|
| 3719 | esds[27+lengthOfData05] = lengthOfData06; // Desc06 Length (1)
|
|---|
| 3720 |
|
|---|
| 3721 | esds[28+lengthOfData05] = 0x02; //SL value 2 (1)
|
|---|
| 3722 |
|
|---|
| 3723 | memcpy(esds+26, glob->codecCont->extradata, lengthOfData05);
|
|---|
| 3724 |
|
|---|
| 3725 | HUnlock(esdsHdl);
|
|---|
| 3726 | } else {
|
|---|
| 3727 | fprintf(stderr, "ERROR: NewHandleClear() failed.\n");
|
|---|
| 3728 | }
|
|---|
| 3729 |
|
|---|
| 3730 | return esdsHdl;
|
|---|
| 3731 | } // esdsExtension()
|
|---|
| 3732 |
|
|---|
| 3733 |
|
|---|
| 3734 | //
|
|---|
| 3735 | static OSStatus prepareImageDescriptionExtensions(lavcEncoderGlobalRecord *glob)
|
|---|
| 3736 | {
|
|---|
| 3737 | // logDebug(NULL, "lavcEncoder: [%08x %s]\n", glob, __FUNCTION__);
|
|---|
| 3738 |
|
|---|
| 3739 | OSStatus err = noErr;
|
|---|
| 3740 |
|
|---|
| 3741 | #if X264
|
|---|
| 3742 | if(glob->add_uuid) {
|
|---|
| 3743 | // Special UUID atom support for iPod H.264
|
|---|
| 3744 | while(TRUE) {
|
|---|
| 3745 | if( RemoveImageDescriptionExtension(glob->imageDescription, 'uuid', 1) ) break;
|
|---|
| 3746 | }
|
|---|
| 3747 | static UInt8 specialuuid[20] = {0x6B,0x68,0x40,0xF2,0x5F,0x24,0x4F,0xC5,
|
|---|
| 3748 | 0xBA,0x39,0xA5,0x1B,0xCF,0x03,0x23,0xF3,
|
|---|
| 3749 | 0x00,0x00,0x00,0x01};
|
|---|
| 3750 | Handle specialHndl = NewHandle(20);
|
|---|
| 3751 | PtrToHand(specialuuid,&specialHndl,20);
|
|---|
| 3752 | if(specialHndl) {
|
|---|
| 3753 | HLock(specialHndl);
|
|---|
| 3754 | err = AddImageDescriptionExtension(glob->imageDescription, specialHndl, 'uuid');
|
|---|
| 3755 | if( err ) {
|
|---|
| 3756 | fprintf(stderr, "ERROR: Adding special uuid failed.\n");
|
|---|
| 3757 | err = paramErr;
|
|---|
| 3758 | }
|
|---|
| 3759 | HUnlock(specialHndl);
|
|---|
| 3760 | DisposeHandle(specialHndl);
|
|---|
| 3761 | } else {
|
|---|
| 3762 | fprintf(stderr, "ERROR: Getting special uuid failed.\n");
|
|---|
| 3763 | err = paramErr;
|
|---|
| 3764 | }
|
|---|
| 3765 | if( err ) goto bail;
|
|---|
| 3766 | } // glob->add_uuid
|
|---|
| 3767 | #endif
|
|---|
| 3768 |
|
|---|
| 3769 | /* ==================================== */
|
|---|
| 3770 |
|
|---|
| 3771 | // add imagedescription extension gamma info
|
|---|
| 3772 | if( glob->add_gamma ) {
|
|---|
| 3773 | // Set gamma level to image description
|
|---|
| 3774 | Fixed gamma_level = kQTCCIR601VideoGammaLevel; /* 2.2, standard television video gamma.*/
|
|---|
| 3775 |
|
|---|
| 3776 | err = ICMImageDescriptionSetProperty( glob->imageDescription,
|
|---|
| 3777 | kQTPropertyClass_ImageDescription,
|
|---|
| 3778 | kICMImageDescriptionPropertyID_GammaLevel,
|
|---|
| 3779 | sizeof(gamma_level),
|
|---|
| 3780 | &gamma_level);
|
|---|
| 3781 | if( err ) {
|
|---|
| 3782 | fprintf(stderr, "ERROR: Setting gamma level failed.\n");
|
|---|
| 3783 | err = paramErr;
|
|---|
| 3784 | goto bail;
|
|---|
| 3785 | }
|
|---|
| 3786 | } // glob->add_gamma
|
|---|
| 3787 |
|
|---|
| 3788 | /* ==================================== */
|
|---|
| 3789 |
|
|---|
| 3790 | // add imagedescription extension nclc info
|
|---|
| 3791 | if( glob->add_nclc ) {
|
|---|
| 3792 | Handle nclcHdl = NULL;
|
|---|
| 3793 | nclcHdl = NewHandleClear(sizeof(NCLCColorInfoImageDescriptionExtension));
|
|---|
| 3794 | if( nclcHdl ) {
|
|---|
| 3795 | HLock( nclcHdl );
|
|---|
| 3796 |
|
|---|
| 3797 | NCLCColorInfoImageDescriptionExtension* nclc = (NCLCColorInfoImageDescriptionExtension*)(*nclcHdl);
|
|---|
| 3798 | nclc->colorParamType = kVideoColorInfoImageDescriptionExtensionType;
|
|---|
| 3799 | glob->add_nclc = TRUE;
|
|---|
| 3800 |
|
|---|
| 3801 | switch (glob->params.NCLC) {
|
|---|
| 3802 | case 3: // 616
|
|---|
| 3803 | nclc->primaries = kQTPrimaries_SMPTE_C;
|
|---|
| 3804 | nclc->transferFunction = kQTTransferFunction_ITU_R709_2;
|
|---|
| 3805 | nclc->matrix = kQTMatrix_ITU_R_601_4;
|
|---|
| 3806 | break;
|
|---|
| 3807 | case 4: // 516
|
|---|
| 3808 | nclc->primaries = kQTPrimaries_EBU_3213;
|
|---|
| 3809 | nclc->transferFunction = kQTTransferFunction_ITU_R709_2;
|
|---|
| 3810 | nclc->matrix = kQTMatrix_ITU_R_601_4;
|
|---|
| 3811 | break;
|
|---|
| 3812 | case 5: // 677
|
|---|
| 3813 | nclc->primaries = kQTPrimaries_SMPTE_C;
|
|---|
| 3814 | nclc->transferFunction = kQTTransferFunction_SMPTE_240M_1995;
|
|---|
| 3815 | nclc->matrix = kQTMatrix_SMPTE_240M_1995;
|
|---|
| 3816 | break;
|
|---|
| 3817 | case 6: // 111
|
|---|
| 3818 | nclc->primaries = kQTPrimaries_ITU_R709_2;
|
|---|
| 3819 | nclc->transferFunction = kQTTransferFunction_ITU_R709_2;
|
|---|
| 3820 | nclc->matrix = kQTMatrix_ITU_R_709_2;
|
|---|
| 3821 | break;
|
|---|
| 3822 | case 7: // 222
|
|---|
| 3823 | nclc->primaries = kQTPrimaries_Unknown;
|
|---|
| 3824 | nclc->transferFunction = kQTTransferFunction_Unknown;
|
|---|
| 3825 | nclc->matrix = kQTMatrix_Unknown;
|
|---|
| 3826 | break;
|
|---|
| 3827 | default:
|
|---|
| 3828 | glob->add_nclc = FALSE;
|
|---|
| 3829 | break;
|
|---|
| 3830 | }
|
|---|
| 3831 | if( glob->add_nclc ) {
|
|---|
| 3832 | logDebug(glob, "lavcEncoder: glob->params.NCLC(%d) = %d%d%d\n"
|
|---|
| 3833 | , glob->params.NCLC, nclc->primaries, nclc->transferFunction, nclc->matrix);
|
|---|
| 3834 | err = ICMImageDescriptionSetProperty( glob->imageDescription,
|
|---|
| 3835 | kQTPropertyClass_ImageDescription,
|
|---|
| 3836 | kICMImageDescriptionPropertyID_NCLCColorInfo,
|
|---|
| 3837 | sizeof(NCLCColorInfoImageDescriptionExtension),
|
|---|
| 3838 | nclc);
|
|---|
| 3839 | if( err ) {
|
|---|
| 3840 | fprintf(stderr, "ERROR: Adding nclc extension failed.\n");
|
|---|
| 3841 | err = paramErr;
|
|---|
| 3842 | }
|
|---|
| 3843 | }
|
|---|
| 3844 |
|
|---|
| 3845 | HUnlock(nclcHdl);
|
|---|
| 3846 | DisposeHandle(nclcHdl);
|
|---|
| 3847 | if( err ) goto bail;
|
|---|
| 3848 | }
|
|---|
| 3849 | } // glob->add_nclc
|
|---|
| 3850 |
|
|---|
| 3851 | /* ==================================== */
|
|---|
| 3852 |
|
|---|
| 3853 | // add imagedescription FieldInfo
|
|---|
| 3854 | if( glob->params.FLAG_INTERLACED_DCT ) {
|
|---|
| 3855 | // Set field info to image description
|
|---|
| 3856 | Handle fielHdl = NULL;
|
|---|
| 3857 | fielHdl = NewHandleClear(sizeof(FieldInfoImageDescriptionExtension2));
|
|---|
| 3858 | if( fielHdl ) {
|
|---|
| 3859 | HLock( fielHdl );
|
|---|
| 3860 | FieldInfoImageDescriptionExtension2* fiel = (FieldInfoImageDescriptionExtension2*)(*fielHdl);
|
|---|
| 3861 |
|
|---|
| 3862 | // x264 uses mbaff, not paff; two field is contained in one sample. i.e. combined.
|
|---|
| 3863 | fiel->fields = kQTFieldsInterlaced;
|
|---|
| 3864 | if(glob->params.TOPFIELDFIRST)
|
|---|
| 3865 | fiel->detail = kQTFieldDetailSpatialFirstLineEarly; // Top field first combined
|
|---|
| 3866 | else
|
|---|
| 3867 | fiel->detail = kQTFieldDetailSpatialFirstLineLate; // Bottom field first combined
|
|---|
| 3868 |
|
|---|
| 3869 | logDebug(glob, "lavcEncoder: FieldInfoImageDescriptionExtension2 = (%d,%d)\n"
|
|---|
| 3870 | , fiel->fields, fiel->detail);
|
|---|
| 3871 | err = ICMImageDescriptionSetProperty( glob->imageDescription,
|
|---|
| 3872 | kQTPropertyClass_ImageDescription,
|
|---|
| 3873 | kICMImageDescriptionPropertyID_FieldInfo,
|
|---|
| 3874 | sizeof(FieldInfoImageDescriptionExtension2),
|
|---|
| 3875 | fiel);
|
|---|
| 3876 | if( err ) {
|
|---|
| 3877 | fprintf(stderr, "ERROR: Setting field info failed.\n");
|
|---|
| 3878 | err = paramErr;
|
|---|
| 3879 | }
|
|---|
| 3880 |
|
|---|
| 3881 | HUnlock(fielHdl);
|
|---|
| 3882 | DisposeHandle(fielHdl);
|
|---|
| 3883 | if( err ) goto bail;
|
|---|
| 3884 | }
|
|---|
| 3885 | } // glob->params.FLAG_INTERLACED_DCT
|
|---|
| 3886 |
|
|---|
| 3887 | /* ==================================== */
|
|---|
| 3888 |
|
|---|
| 3889 | // add imagedescription PixelAspectRatio
|
|---|
| 3890 | if( glob->params.USEASPECTRATIO ) {
|
|---|
| 3891 | if( glob->params.hSpacing == 0
|
|---|
| 3892 | || glob->params.vSpacing == 0
|
|---|
| 3893 | ){
|
|---|
| 3894 | fprintf(stderr, "ERROR: Invalid parameter for pixel aspect ratio.\n");
|
|---|
| 3895 | err = paramErr;
|
|---|
| 3896 | goto bail;
|
|---|
| 3897 | }
|
|---|
| 3898 |
|
|---|
| 3899 | // Set pixel aspect ratio to image description
|
|---|
| 3900 | Handle paspHdl = NULL;
|
|---|
| 3901 | paspHdl = NewHandleClear(sizeof(PixelAspectRatioImageDescriptionExtension));
|
|---|
| 3902 | if( paspHdl ) {
|
|---|
| 3903 | HLock( paspHdl );
|
|---|
| 3904 | PixelAspectRatioImageDescriptionExtension* pasp = (PixelAspectRatioImageDescriptionExtension*)(*paspHdl);
|
|---|
| 3905 |
|
|---|
| 3906 | pasp->hSpacing = glob->params.hSpacing;
|
|---|
| 3907 | pasp->vSpacing = glob->params.vSpacing;
|
|---|
| 3908 |
|
|---|
| 3909 | logDebug(glob, "lavcEncoder: PixelAspectRatioImageDescriptionExtension = (%d,%d)\n"
|
|---|
| 3910 | , pasp->hSpacing, pasp->vSpacing);
|
|---|
| 3911 | err = ICMImageDescriptionSetProperty( glob->imageDescription,
|
|---|
| 3912 | kQTPropertyClass_ImageDescription,
|
|---|
| 3913 | kICMImageDescriptionPropertyID_PixelAspectRatio,
|
|---|
| 3914 | sizeof(PixelAspectRatioImageDescriptionExtension),
|
|---|
| 3915 | pasp);
|
|---|
| 3916 | if( err ) {
|
|---|
| 3917 | fprintf(stderr, "ERROR: Setting pixel aspect ratio failed.\n");
|
|---|
| 3918 | err = paramErr;
|
|---|
| 3919 | }
|
|---|
| 3920 |
|
|---|
| 3921 | HUnlock(paspHdl);
|
|---|
| 3922 | DisposeHandle(paspHdl);
|
|---|
| 3923 | if( err ) goto bail;
|
|---|
| 3924 | }
|
|---|
| 3925 | } // glob->params.USEASPECTRATIO
|
|---|
| 3926 |
|
|---|
| 3927 | /* ==================================== */
|
|---|
| 3928 |
|
|---|
| 3929 | // add imagedescription CleanAperture
|
|---|
| 3930 | if( glob->params.USECLEANAPERTURE ) {
|
|---|
| 3931 | // Check "divide by 0" error
|
|---|
| 3932 | if( glob->params.cleanApertureWidthD == 0 || glob->params.cleanApertureHeightD == 0
|
|---|
| 3933 | || glob->params.horizOffD == 0 || glob->params.vertOffD == 0
|
|---|
| 3934 | ){
|
|---|
| 3935 | fprintf(stderr, "NOTICE: Skip to apply clean aperture. (denominator is 0)\n");
|
|---|
| 3936 | AudioServicesPlayAlertSound(kUserPreferredAlert);
|
|---|
| 3937 | goto bail;
|
|---|
| 3938 | }
|
|---|
| 3939 |
|
|---|
| 3940 | // Check zero size rectangle error
|
|---|
| 3941 | if( glob->params.cleanApertureWidthN == 0 || glob->params.cleanApertureHeightN == 0 ) {
|
|---|
| 3942 | fprintf(stderr, "NOTICE: Skip to apply clean aperture. (zero size apreture)\n");
|
|---|
| 3943 | AudioServicesPlayAlertSound(kUserPreferredAlert);
|
|---|
| 3944 | goto bail;
|
|---|
| 3945 | }
|
|---|
| 3946 |
|
|---|
| 3947 | // Set clean aperture to image description
|
|---|
| 3948 | Handle clapHdl = NULL;
|
|---|
| 3949 | clapHdl = NewHandleClear(sizeof(CleanApertureImageDescriptionExtension));
|
|---|
| 3950 | if( clapHdl ) {
|
|---|
| 3951 | HLock( clapHdl );
|
|---|
| 3952 | CleanApertureImageDescriptionExtension* clap = (CleanApertureImageDescriptionExtension*)(*clapHdl);
|
|---|
| 3953 |
|
|---|
| 3954 | clap->cleanApertureWidthN = glob->params.cleanApertureWidthN;
|
|---|
| 3955 | clap->cleanApertureWidthD = glob->params.cleanApertureWidthD;
|
|---|
| 3956 | clap->cleanApertureHeightN = glob->params.cleanApertureHeightN;
|
|---|
| 3957 | clap->cleanApertureHeightD = glob->params.cleanApertureHeightD;
|
|---|
| 3958 | clap->horizOffN = glob->params.horizOffN;
|
|---|
| 3959 | clap->horizOffD = glob->params.horizOffD;
|
|---|
| 3960 | clap->vertOffN = glob->params.vertOffN;
|
|---|
| 3961 | clap->vertOffD = glob->params.vertOffD;
|
|---|
| 3962 |
|
|---|
| 3963 | logDebug(glob, "lavcEncoder: CleanApertureImageDescriptionExtension = "
|
|---|
| 3964 | "rectangle(%d/%d, %d,%d), offset(%d/%d, %d,%d)\n"
|
|---|
| 3965 | , clap->cleanApertureWidthN, clap->cleanApertureWidthD
|
|---|
| 3966 | , clap->cleanApertureHeightN, clap->cleanApertureHeightD
|
|---|
| 3967 | , clap->horizOffN, clap->horizOffD
|
|---|
| 3968 | , clap->vertOffN, clap->vertOffD
|
|---|
| 3969 | );
|
|---|
| 3970 | err = ICMImageDescriptionSetProperty( glob->imageDescription,
|
|---|
| 3971 | kQTPropertyClass_ImageDescription,
|
|---|
| 3972 | kICMImageDescriptionPropertyID_CleanAperture,
|
|---|
| 3973 | sizeof(CleanApertureImageDescriptionExtension),
|
|---|
| 3974 | clap);
|
|---|
| 3975 | if( err ) {
|
|---|
| 3976 | fprintf(stderr, "ERROR: Setting clean aperture failed.\n");
|
|---|
| 3977 | err = paramErr;
|
|---|
| 3978 | }
|
|---|
| 3979 |
|
|---|
| 3980 | HUnlock(clapHdl);
|
|---|
| 3981 | DisposeHandle(clapHdl);
|
|---|
| 3982 | if( err ) goto bail;
|
|---|
| 3983 | }
|
|---|
| 3984 | } // glob->params.USECLEANAPERTURE
|
|---|
| 3985 |
|
|---|
| 3986 | bail:
|
|---|
| 3987 | return err;
|
|---|
| 3988 | }
|
|---|
| 3989 |
|
|---|
| 3990 |
|
|---|
| 3991 | #pragma mark -
|
|---|
| 3992 |
|
|---|
| 3993 |
|
|---|
| 3994 | // log Debug support
|
|---|
| 3995 | static void logDebug(lavcEncoderGlobalRecord *glob, char* fmt, ...)
|
|---|
| 3996 | {
|
|---|
| 3997 | if( glob && !(glob->params.LOG_DEBUG) ) return;
|
|---|
| 3998 |
|
|---|
| 3999 | char buf[4096];
|
|---|
| 4000 | va_list argp;
|
|---|
| 4001 | va_start(argp, fmt);
|
|---|
| 4002 | vsnprintf(buf, 4096, fmt, argp);
|
|---|
| 4003 | va_end(argp);
|
|---|
| 4004 |
|
|---|
| 4005 | fprintf(stderr, "DEBUG: %s", buf);
|
|---|
| 4006 | }
|
|---|
| 4007 |
|
|---|
| 4008 |
|
|---|
| 4009 | // log Info support
|
|---|
| 4010 | static void logInfo(lavcEncoderGlobalRecord *glob, char* fmt, ...)
|
|---|
| 4011 | {
|
|---|
| 4012 | if( glob && !glob->params.LOG_INFO ) return;
|
|---|
| 4013 |
|
|---|
| 4014 | char buf[4096];
|
|---|
| 4015 | va_list argp;
|
|---|
| 4016 | va_start(argp, fmt);
|
|---|
| 4017 | vsnprintf(buf, 4096, fmt, argp);
|
|---|
| 4018 | va_end(argp);
|
|---|
| 4019 |
|
|---|
| 4020 | fprintf(stderr, "INFO : %s", buf);
|
|---|
| 4021 | }
|
|---|
| 4022 |
|
|---|
| 4023 |
|
|---|
| 4024 | #pragma mark -
|
|---|
| 4025 |
|
|---|
| 4026 |
|
|---|
| 4027 | #if USECoreVF
|
|---|
| 4028 | // Prepare CoreVF Framework
|
|---|
| 4029 | static OSStatus openCoreVF( lavcEncoderGlobals glob )
|
|---|
| 4030 | {
|
|---|
| 4031 | logDebug(glob, "lavcEncoder: [%08x %s]\n", glob, __FUNCTION__);
|
|---|
| 4032 |
|
|---|
| 4033 | OSStatus err = noErr;
|
|---|
| 4034 |
|
|---|
| 4035 | if( CVF_Context_Create == NULL ) {
|
|---|
| 4036 | err = paramErr;
|
|---|
| 4037 | goto bail;
|
|---|
| 4038 | }
|
|---|
| 4039 |
|
|---|
| 4040 | if(glob->filterPreset) {
|
|---|
| 4041 | CFStringRef appID = CFSTR("com.MyCometG3.CoreVF");
|
|---|
| 4042 | //CFPreferencesAppSynchronize(appID); /* cal this at SetSettings */
|
|---|
| 4043 | CFStringRef keyStr = NULL;
|
|---|
| 4044 | CFIndex index = glob->filterPreset;
|
|---|
| 4045 | if(glob->filterPreset == -1) {
|
|---|
| 4046 | CFNumberRef indexRef = (CFNumberRef)CFPreferencesCopyAppValue(CFSTR("filterPreset"), appID);
|
|---|
| 4047 | if(indexRef) {
|
|---|
| 4048 | if(!CFNumberGetValue(indexRef, kCFNumberCFIndexType, &index))
|
|---|
| 4049 | index = 1;
|
|---|
| 4050 | CFRelease(indexRef);
|
|---|
| 4051 | } else {
|
|---|
| 4052 | index = 1;
|
|---|
| 4053 | }
|
|---|
| 4054 | }
|
|---|
| 4055 |
|
|---|
| 4056 | keyStr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("Preset%d"), CVF_CLIP(index, 1, 8));
|
|---|
| 4057 | if(keyStr) {
|
|---|
| 4058 | glob->filterString = (CFStringRef)CFPreferencesCopyAppValue(keyStr, appID);
|
|---|
| 4059 | CFRelease(keyStr);
|
|---|
| 4060 | }
|
|---|
| 4061 | }
|
|---|
| 4062 | if(!glob->filterString || (glob->filterString && !CFStringGetLength(glob->filterString)) ) {
|
|---|
| 4063 | err = paramErr;
|
|---|
| 4064 | goto bail;
|
|---|
| 4065 | }
|
|---|
| 4066 |
|
|---|
| 4067 | if(!glob->cvfCont) {
|
|---|
| 4068 | int cvfLogLevel = CVF_LOGLEVEL_NONE;
|
|---|
| 4069 | if( glob->params.LOG_INFO ) cvfLogLevel = CVF_LOGLEVEL_LESS;
|
|---|
| 4070 | if( glob->params.LOG_DEBUG ) cvfLogLevel = CVF_LOGLEVEL_MORE;
|
|---|
| 4071 |
|
|---|
| 4072 | glob->cvfCont = CVF_Context_Create(cvfLogLevel);
|
|---|
| 4073 | if(!glob->cvfCont) {
|
|---|
| 4074 | err = paramErr;
|
|---|
| 4075 | goto bail;
|
|---|
| 4076 | }
|
|---|
| 4077 |
|
|---|
| 4078 | int result = FALSE;
|
|---|
| 4079 | result = CVF_Context_BuildFilterChain(glob->cvfCont, glob->filterString, NULL);
|
|---|
| 4080 | if(!result) {
|
|---|
| 4081 | err = paramErr;
|
|---|
| 4082 | goto bail;
|
|---|
| 4083 | }
|
|---|
| 4084 |
|
|---|
| 4085 | CVF_Video *tempV = CVF_Video_CreateDefault(glob->width, glob->height,
|
|---|
| 4086 | CVF_PT_I420, CVF_FT_FRAMEBASED); // Is it CVF_PT_YV12, or CVF_PT_I420 ?
|
|---|
| 4087 | assert(tempV);
|
|---|
| 4088 | glob->cvfOutVideo = CVF_Context_GetVideoRep(glob->cvfCont, tempV);
|
|---|
| 4089 | assert(glob->cvfOutVideo);
|
|---|
| 4090 | if(tempV != glob->cvfOutVideo) CVF_Video_Release(tempV);
|
|---|
| 4091 |
|
|---|
| 4092 | if(glob->subsampling >= 0) { // input and output uses planar yuv 420 format
|
|---|
| 4093 | glob->cvfInVideo = glob->cvfOutVideo; // Broken support on CoreVideo
|
|---|
| 4094 | } else { // -1:422-Direct input;
|
|---|
| 4095 | tempV = CVF_Video_CreateDefault(
|
|---|
| 4096 | glob->width, glob->height, CVF_PT_UYVY, CVF_FT_FRAMEBASED);
|
|---|
| 4097 | assert(tempV);
|
|---|
| 4098 | glob->cvfInVideo = CVF_Context_GetVideoRep(glob->cvfCont, tempV);
|
|---|
| 4099 | assert(glob->cvfInVideo);
|
|---|
| 4100 | if(tempV != glob->cvfInVideo) CVF_Video_Release(tempV);
|
|---|
| 4101 | }
|
|---|
| 4102 |
|
|---|
| 4103 | glob->cvfInFrame = CVF_Context_GetNewFrame(glob->cvfCont, glob->cvfInVideo);
|
|---|
| 4104 | glob->cvfOutFrame = CVF_Context_GetNewFrame(glob->cvfCont, glob->cvfOutVideo);
|
|---|
| 4105 | assert(glob->cvfInFrame) ; assert(glob->cvfOutFrame);
|
|---|
| 4106 |
|
|---|
| 4107 | glob->cvfSourceArray = CFArrayCreateMutable(kCFAllocatorDefault, 128, &kCFTypeArrayCallBacks);
|
|---|
| 4108 | } // if(!glob->cvfCont)
|
|---|
| 4109 |
|
|---|
| 4110 | bail:
|
|---|
| 4111 | if(err) {
|
|---|
| 4112 | glob->filterPreset = 0; // Not available
|
|---|
| 4113 | if(glob->filterString) {
|
|---|
| 4114 | CFRelease(glob->filterString); glob->filterString = NULL;
|
|---|
| 4115 | }
|
|---|
| 4116 | }
|
|---|
| 4117 | return err;
|
|---|
| 4118 | }
|
|---|
| 4119 |
|
|---|
| 4120 |
|
|---|
| 4121 | // Clean up CoreVF Framework
|
|---|
| 4122 | static OSStatus closeCoreVF( lavcEncoderGlobals glob )
|
|---|
| 4123 | {
|
|---|
| 4124 | logDebug(glob, "lavcEncoder: [%08x %s]\n", glob, __FUNCTION__);
|
|---|
| 4125 |
|
|---|
| 4126 | OSStatus err = noErr;
|
|---|
| 4127 |
|
|---|
| 4128 | if( glob->cvfCont ) {
|
|---|
| 4129 | if(glob->cvfSourceArray) CFRelease(glob->cvfSourceArray);
|
|---|
| 4130 | if(glob->filterString) CFRelease(glob->filterString);
|
|---|
| 4131 |
|
|---|
| 4132 | if(glob->cvfInFrame) CVF_Context_UnlockFrame(glob->cvfCont, glob->cvfInFrame);
|
|---|
| 4133 | if(glob->cvfOutFrame) CVF_Context_UnlockFrame(glob->cvfCont, glob->cvfOutFrame);
|
|---|
| 4134 |
|
|---|
| 4135 | CVF_Context_Release(glob->cvfCont);
|
|---|
| 4136 | glob->cvfCont = NULL;
|
|---|
| 4137 | }
|
|---|
| 4138 |
|
|---|
| 4139 | return err;
|
|---|
| 4140 | }
|
|---|
| 4141 | #endif
|
|---|
| 4142 |
|
|---|
| 4143 |
|
|---|
| 4144 | #pragma mark -
|
|---|
| 4145 |
|
|---|
| 4146 |
|
|---|
| 4147 | // Check param range and reset if needed
|
|---|
| 4148 | static void checkValues( lavcEncoderGlobals glob )
|
|---|
| 4149 | {
|
|---|
| 4150 | // logDebug(NULL, "lavcEncoder: [%08x %s]\n", glob, __FUNCTION__);
|
|---|
| 4151 |
|
|---|
| 4152 | #if X264
|
|---|
| 4153 | // In case that app passed older struct ; Some params' zero value are not allowed;
|
|---|
| 4154 | // glob->params.CQM_PRESET
|
|---|
| 4155 | // glob->params.NO_DCT_DECIMATE
|
|---|
| 4156 |
|
|---|
| 4157 | if( !glob->params.MB_DECISION ) glob->params.MB_DECISION=1; // SIMPLE
|
|---|
| 4158 | if( !glob->params.ME_METHOD ) glob->params.ME_METHOD=2; // HEX
|
|---|
| 4159 | if( !glob->params.CODER_TYPE ) glob->params.CODER_TYPE=2; // CABAC
|
|---|
| 4160 | if( !glob->params.DIRECTPRED ) glob->params.DIRECTPRED=2; // Spatial
|
|---|
| 4161 | if( !glob->params.TRELLIS ) glob->params.TRELLIS=2; // FinalOnly
|
|---|
| 4162 | if( !glob->params.THREADS ) glob->params.THREADS=9; // Auto thread
|
|---|
| 4163 | if( !glob->params.TURBO ) glob->params.TURBO=3; // Turbo 2
|
|---|
| 4164 | if( !glob->params.LEVEL ) glob->params.LEVEL=9; // Level auto
|
|---|
| 4165 | if( !glob->params.AQ_MODE ) glob->params.AQ_MODE=2; // VARIANCE
|
|---|
| 4166 | // glob->params.ADAPTIVE_BFRAME
|
|---|
| 4167 | if( !glob->params.X264PROFILE ) glob->params.X264PROFILE=3; // 3:High Profile
|
|---|
| 4168 | if( !glob->params.WEIGHTP ) glob->params.WEIGHTP = 3; // Smart analysis
|
|---|
| 4169 |
|
|---|
| 4170 | if( !glob->params.REFS ) glob->params.REFS = 3; // 3
|
|---|
| 4171 | // if( !glob->params.ME_SUBQ ) glob->params.ME_SUBQ = 7; // 7
|
|---|
| 4172 | if( !glob->params.ME_RANGE ) glob->params.ME_RANGE = 16; // 16
|
|---|
| 4173 | // if( !glob->params.MAX_BFRAMES ) glob->params.MAX_BFRAMES = 3; // 3
|
|---|
| 4174 | // glob->params.SC_THRESHOLD
|
|---|
| 4175 | if( !glob->params.QCOMPRESS ) glob->params.QCOMPRESS = 60; // 0.60
|
|---|
| 4176 | // glob->params.NOISE_REDUCTION
|
|---|
| 4177 | // glob->params.RC_BUFSIZE
|
|---|
| 4178 | // glob->params.RC_MAXRATE
|
|---|
| 4179 | // glob->params.DEBLOCK_ALPHA
|
|---|
| 4180 | // glob->params.DEBLOCK_BETA
|
|---|
| 4181 | if( !glob->params.AQ_STRENGTH ) glob->params.AQ_STRENGTH = 100; // 1.0
|
|---|
| 4182 | // if( !glob->params.KEYINT_MIN ) glob->params.KEYINT_MIN = 25; // 25
|
|---|
| 4183 | // glob->params.PSYRD_RDO
|
|---|
| 4184 | // glob->params.PSYRD_TRELLIS
|
|---|
| 4185 | if( !glob->params.MAX_QDIFF ) glob->params.MAX_QDIFF = 4; // 4
|
|---|
| 4186 | // glob->params.CHROMAOFFSET
|
|---|
| 4187 |
|
|---|
| 4188 | if( !glob->params.NCLC ) glob->params.NCLC = 1; // no nclc
|
|---|
| 4189 | if( !glob->params.NATIVE_FPS ) glob->params.NATIVE_FPS=1; // NTSC
|
|---|
| 4190 | // glob->params.USE3RDPASS
|
|---|
| 4191 | // glob->params.EMBEDUUID
|
|---|
| 4192 | // glob->params.FILTERPRESET
|
|---|
| 4193 | // glob->params.SUBSAMPLING
|
|---|
| 4194 |
|
|---|
| 4195 | // // glob->params.MBTREE
|
|---|
| 4196 | // // glob->params.PSY
|
|---|
| 4197 | // glob->params.RC_LOOKAHEAD
|
|---|
| 4198 | if( !glob->params.IP_FACTOR ) glob->params.IP_FACTOR = 140; // 1.40
|
|---|
| 4199 | if( !glob->params.PB_FACTOR ) glob->params.PB_FACTOR = 130; // 1.30
|
|---|
| 4200 |
|
|---|
| 4201 | if( !glob->params.hSpacing ) glob->params.hSpacing = 1; // 1
|
|---|
| 4202 | if( !glob->params.vSpacing ) glob->params.vSpacing = 1; // 1
|
|---|
| 4203 |
|
|---|
| 4204 | if( !glob->params.cleanApertureWidthD ) glob->params.cleanApertureWidthD = 1; // 1
|
|---|
| 4205 | if( !glob->params.cleanApertureHeightD ) glob->params.cleanApertureHeightD = 1; // 1
|
|---|
| 4206 | if( !glob->params.horizOffD ) glob->params.horizOffD = 1; // 1
|
|---|
| 4207 | if( !glob->params.vertOffD ) glob->params.vertOffD = 1; // 1
|
|---|
| 4208 |
|
|---|
| 4209 | // glob->params.OVERRIDECRFQSCALE
|
|---|
| 4210 | if( !glob->params.USERCRFQSCALE ) glob->params.USERCRFQSCALE = 23; // 23
|
|---|
| 4211 | // glob->params.OVERRIDEQMIN
|
|---|
| 4212 | // glob->params.USERQMIN // x264 r1795 changed default qmin from 10 to 0, thus 0 is acceptable now
|
|---|
| 4213 | #endif
|
|---|
| 4214 | #if MPEG4
|
|---|
| 4215 | // In case that app passed older struct ; Some params' zero value are not allowed;
|
|---|
| 4216 | // glob->params.CQM_PRESET
|
|---|
| 4217 | // glob->params.NO_DCT_DECIMATE
|
|---|
| 4218 |
|
|---|
| 4219 | if( !glob->params.MB_DECISION ) glob->params.MB_DECISION=2; // BITS
|
|---|
| 4220 | if( !glob->params.ME_METHOD ) glob->params.ME_METHOD=1; // DIA(EPZS)
|
|---|
| 4221 | if( !glob->params.CODER_TYPE ) glob->params.CODER_TYPE=1; // CAVLC
|
|---|
| 4222 | if( !glob->params.DIRECTPRED ) glob->params.DIRECTPRED=3; // Temporal
|
|---|
| 4223 | if( !glob->params.TRELLIS ) glob->params.TRELLIS=1; // Disabled
|
|---|
| 4224 | if( !glob->params.THREADS ) glob->params.THREADS=9; // Auto thread
|
|---|
| 4225 | if( !glob->params.TURBO ) glob->params.TURBO=2; // Turbo 1
|
|---|
| 4226 | if( !glob->params.LEVEL ) glob->params.LEVEL=9; // Level auto
|
|---|
| 4227 | if( !glob->params.AQ_MODE ) glob->params.AQ_MODE=2; // VARIANCE
|
|---|
| 4228 | // glob->params.ADAPTIVE_BFRAME
|
|---|
| 4229 | if( !glob->params.X264PROFILE ) glob->params.X264PROFILE=3; // 3:High Profile
|
|---|
| 4230 | if( !glob->params.WEIGHTP ) glob->params.WEIGHTP = 1; // Disabled
|
|---|
| 4231 |
|
|---|
| 4232 | if( !glob->params.REFS ) glob->params.REFS = 1; // 1
|
|---|
| 4233 | // if( !glob->params.ME_SUBQ ) glob->params.ME_SUBQ = 8; // 8
|
|---|
| 4234 | if( !glob->params.ME_RANGE ) glob->params.ME_RANGE = 16; // 16
|
|---|
| 4235 | // if( !glob->params.MAX_BFRAMES ) glob->params.MAX_BFRAMES = 1; // 1
|
|---|
| 4236 | // glob->params.SC_THRESHOLD
|
|---|
| 4237 | if( !glob->params.QCOMPRESS ) glob->params.QCOMPRESS = 60; // 0.60
|
|---|
| 4238 | // glob->params.NOISE_REDUCTION
|
|---|
| 4239 | // glob->params.RC_BUFSIZE
|
|---|
| 4240 | // glob->params.RC_MAXRATE
|
|---|
| 4241 | // glob->params.DEBLOCK_ALPHA
|
|---|
| 4242 | // glob->params.DEBLOCK_BETA
|
|---|
| 4243 | if( !glob->params.AQ_STRENGTH ) glob->params.AQ_STRENGTH = 100; // 1.0
|
|---|
| 4244 | if( !glob->params.KEYINT_MIN ) glob->params.KEYINT_MIN = 25; // 25
|
|---|
| 4245 | // glob->params.PSYRD_RDO
|
|---|
| 4246 | // glob->params.PSYRD_TRELLIS
|
|---|
| 4247 | if( !glob->params.MAX_QDIFF ) glob->params.MAX_QDIFF = 3; // 3
|
|---|
| 4248 | // glob->params.CHROMAOFFSET
|
|---|
| 4249 |
|
|---|
| 4250 | if( !glob->params.NCLC ) glob->params.NCLC = 1; // no nclc
|
|---|
| 4251 | if( !glob->params.NATIVE_FPS ) glob->params.NATIVE_FPS=1; // NTSC
|
|---|
| 4252 | // glob->params.USE3RDPASS
|
|---|
| 4253 | // glob->params.EMBEDUUID
|
|---|
| 4254 | // glob->params.FILTERPRESET
|
|---|
| 4255 | // glob->params.SUBSAMPLING
|
|---|
| 4256 |
|
|---|
| 4257 | // // glob->params.MBTREE
|
|---|
| 4258 | // // glob->params.PSY
|
|---|
| 4259 | // glob->params.RC_LOOKAHEAD
|
|---|
| 4260 | if( !glob->params.IP_FACTOR ) glob->params.IP_FACTOR = 125; // 1.25
|
|---|
| 4261 | if( !glob->params.PB_FACTOR ) glob->params.PB_FACTOR = 125; // 1.25
|
|---|
| 4262 |
|
|---|
| 4263 | if( !glob->params.hSpacing ) glob->params.hSpacing = 1; // 1
|
|---|
| 4264 | if( !glob->params.vSpacing ) glob->params.vSpacing = 1; // 1
|
|---|
| 4265 |
|
|---|
| 4266 | if( !glob->params.cleanApertureWidthD ) glob->params.cleanApertureWidthD = 1; // 1
|
|---|
| 4267 | if( !glob->params.cleanApertureHeightD ) glob->params.cleanApertureHeightD = 1; // 1
|
|---|
| 4268 | if( !glob->params.horizOffD ) glob->params.horizOffD = 1; // 1
|
|---|
| 4269 | if( !glob->params.vertOffD ) glob->params.vertOffD = 1; // 1
|
|---|
| 4270 |
|
|---|
| 4271 | // glob->params.OVERRIDECRFQSCALE
|
|---|
| 4272 | if( !glob->params.USERCRFQSCALE ) glob->params.USERCRFQSCALE = 2; // 2
|
|---|
| 4273 | // glob->params.OVERRIDEQMIN
|
|---|
| 4274 | if( !glob->params.USERQMIN ) glob->params.USERQMIN = 2; // 2
|
|---|
| 4275 | #endif
|
|---|
| 4276 | #if XVID
|
|---|
| 4277 | // In case that app passed older struct ; Some params' zero value are not allowed;
|
|---|
| 4278 | // glob->params.CQM_PRESET
|
|---|
| 4279 | // glob->params.NO_DCT_DECIMATE
|
|---|
| 4280 |
|
|---|
| 4281 | if( !glob->params.MB_DECISION ) glob->params.MB_DECISION=2; // BITS
|
|---|
| 4282 | if( !glob->params.ME_METHOD ) glob->params.ME_METHOD=4; // FULL
|
|---|
| 4283 | if( !glob->params.CODER_TYPE ) glob->params.CODER_TYPE=1; // CAVLC
|
|---|
| 4284 | if( !glob->params.DIRECTPRED ) glob->params.DIRECTPRED=3; // Temporal
|
|---|
| 4285 | if( !glob->params.TRELLIS ) glob->params.TRELLIS=3; // All
|
|---|
| 4286 | if( !glob->params.THREADS ) glob->params.THREADS=9; // Auto thread
|
|---|
| 4287 | if( !glob->params.TURBO ) glob->params.TURBO=1; // Disabled
|
|---|
| 4288 | if( !glob->params.LEVEL ) glob->params.LEVEL=9; // Level auto
|
|---|
| 4289 | if( !glob->params.AQ_MODE ) glob->params.AQ_MODE=2; // VARIANCE
|
|---|
| 4290 | // glob->params.ADAPTIVE_BFRAME
|
|---|
| 4291 | if( !glob->params.X264PROFILE ) glob->params.X264PROFILE=3; // 3:High Profile
|
|---|
| 4292 | if( !glob->params.WEIGHTP ) glob->params.WEIGHTP = 1; // Disabled
|
|---|
| 4293 |
|
|---|
| 4294 | if( !glob->params.REFS ) glob->params.REFS = 1; // 1
|
|---|
| 4295 | // if( !glob->params.ME_SUBQ ) glob->params.ME_SUBQ = 8; // 8
|
|---|
| 4296 | if( !glob->params.ME_RANGE ) glob->params.ME_RANGE = 16; // 16
|
|---|
| 4297 | // if( !glob->params.MAX_BFRAMES ) glob->params.MAX_BFRAMES = 1; // 1
|
|---|
| 4298 | // glob->params.SC_THRESHOLD
|
|---|
| 4299 | if( !glob->params.QCOMPRESS ) glob->params.QCOMPRESS = 60; // 0.60
|
|---|
| 4300 | // glob->params.NOISE_REDUCTION
|
|---|
| 4301 | // glob->params.RC_BUFSIZE
|
|---|
| 4302 | // glob->params.RC_MAXRATE
|
|---|
| 4303 | // glob->params.DEBLOCK_ALPHA
|
|---|
| 4304 | // glob->params.DEBLOCK_BETA
|
|---|
| 4305 | if( !glob->params.AQ_STRENGTH ) glob->params.AQ_STRENGTH = 100; // 1.0
|
|---|
| 4306 | if( !glob->params.KEYINT_MIN ) glob->params.KEYINT_MIN = 25; // 25
|
|---|
| 4307 | // glob->params.PSYRD_RDO
|
|---|
| 4308 | // glob->params.PSYRD_TRELLIS
|
|---|
| 4309 | if( !glob->params.MAX_QDIFF ) glob->params.MAX_QDIFF = 3; // 3
|
|---|
| 4310 | // glob->params.CHROMAOFFSET
|
|---|
| 4311 |
|
|---|
| 4312 | if( !glob->params.NCLC ) glob->params.NCLC = 1; // no nclc
|
|---|
| 4313 | if( !glob->params.NATIVE_FPS ) glob->params.NATIVE_FPS=1; // NTSC
|
|---|
| 4314 | // glob->params.USE3RDPASS
|
|---|
| 4315 | // glob->params.EMBEDUUID
|
|---|
| 4316 | // glob->params.FILTERPRESET
|
|---|
| 4317 | // glob->params.SUBSAMPLING
|
|---|
| 4318 |
|
|---|
| 4319 | // // glob->params.MBTREE
|
|---|
| 4320 | // // glob->params.PSY
|
|---|
| 4321 | // glob->params.RC_LOOKAHEAD
|
|---|
| 4322 | if( !glob->params.IP_FACTOR ) glob->params.IP_FACTOR = 125; // 1.25
|
|---|
| 4323 | if( !glob->params.PB_FACTOR ) glob->params.PB_FACTOR = 150; // 1.50
|
|---|
| 4324 |
|
|---|
| 4325 | if( !glob->params.hSpacing ) glob->params.hSpacing = 1; // 1
|
|---|
| 4326 | if( !glob->params.vSpacing ) glob->params.vSpacing = 1; // 1
|
|---|
| 4327 |
|
|---|
| 4328 | if( !glob->params.cleanApertureWidthD ) glob->params.cleanApertureWidthD = 1; // 1
|
|---|
| 4329 | if( !glob->params.cleanApertureHeightD ) glob->params.cleanApertureHeightD = 1; // 1
|
|---|
| 4330 | if( !glob->params.horizOffD ) glob->params.horizOffD = 1; // 1
|
|---|
| 4331 | if( !glob->params.vertOffD ) glob->params.vertOffD = 1; // 1
|
|---|
| 4332 |
|
|---|
| 4333 | // glob->params.OVERRIDECRFQSCALE
|
|---|
| 4334 | if( !glob->params.USERCRFQSCALE ) glob->params.USERCRFQSCALE = 2; // 2
|
|---|
| 4335 | // glob->params.OVERRIDEQMIN
|
|---|
| 4336 | if( !glob->params.USERQMIN ) glob->params.USERQMIN = 2; // 2
|
|---|
| 4337 | #endif
|
|---|
| 4338 | } // checkValues()
|
|---|
| 4339 |
|
|---|
| 4340 |
|
|---|
| 4341 | // Initialize params
|
|---|
| 4342 | static void initValues( lavcEncoderGlobals glob )
|
|---|
| 4343 | {
|
|---|
| 4344 | // logDebug(NULL, "lavcEncoder: [%08x %s]\n", glob, __FUNCTION__);
|
|---|
| 4345 |
|
|---|
| 4346 | glob->params.REV_STRUCT = REV_X264OPENGOP;
|
|---|
| 4347 | #if X264
|
|---|
| 4348 | // Initial values for CODE_ID_H264 (=x264)
|
|---|
| 4349 | glob->params.FLAG_QSCALE = FALSE;
|
|---|
| 4350 | glob->params.FLAG_4MV = FALSE;
|
|---|
| 4351 | glob->params.FLAG_QPEL = FALSE;
|
|---|
| 4352 | glob->params.FLAG_GMC = FALSE;
|
|---|
| 4353 | glob->params.FLAG_MV0 = FALSE;
|
|---|
| 4354 | glob->params.FLAG_PART = FALSE;
|
|---|
| 4355 | glob->params.FLAG_LOOP_FILTER = TRUE;
|
|---|
| 4356 | glob->params.FLAG_PSNR = FALSE;
|
|---|
| 4357 | glob->params.FLAG_NORMALIZE_AQP = FALSE;
|
|---|
| 4358 | glob->params.FLAG_INTERLACED_DCT = FALSE;
|
|---|
| 4359 | glob->params.FLAG_AC_PRED = FALSE;
|
|---|
| 4360 | glob->params.FLAG_CBP_RD = FALSE;
|
|---|
| 4361 | glob->params.FLAG_QP_RD = FALSE;
|
|---|
| 4362 | glob->params.FLAG_CLOSED_GOP = TRUE;
|
|---|
| 4363 |
|
|---|
| 4364 | glob->params.NATIVE_FPS = 1; // NTSC
|
|---|
| 4365 | glob->params.MB_DECISION = 1; // SIMPLE
|
|---|
| 4366 | glob->params.RC_QSQUISH = 0; // clip
|
|---|
| 4367 | glob->params.MPEG_QUANT = 0; // h263
|
|---|
| 4368 | glob->params.THREADS = 9; // Auto thread
|
|---|
| 4369 | glob->params.GAMMA = 0; // no gamma
|
|---|
| 4370 | glob->params.NCLC = 1; // no nclc
|
|---|
| 4371 | glob->params.ME_METHOD = 2; // HEX
|
|---|
| 4372 |
|
|---|
| 4373 | glob->params.SC_THRESHOLD = 40; //
|
|---|
| 4374 | glob->params.QCOMPRESS = 60; // 0.60
|
|---|
| 4375 | glob->params.NOISE_REDUCTION = 0; //
|
|---|
| 4376 | glob->params.RC_MAXRATE = 0; //
|
|---|
| 4377 |
|
|---|
| 4378 | glob->params.REFS = 3; //
|
|---|
| 4379 | glob->params.ME_RANGE = 16; //
|
|---|
| 4380 | glob->params.MAX_BFRAMES = 3; //
|
|---|
| 4381 | glob->params.CODER_TYPE = 2; // CABAC
|
|---|
| 4382 | glob->params.DIRECTPRED = 2; // Spatial
|
|---|
| 4383 | glob->params.CRF = 0; // no crf
|
|---|
| 4384 | glob->params.ADAPTIVE_BFRAME = 1; // use adaptive b frame - fast
|
|---|
| 4385 | glob->params.ME_SUBQ = 7; //
|
|---|
| 4386 |
|
|---|
| 4387 | glob->params.TRELLIS = 2; // FinalOnly
|
|---|
| 4388 | glob->params.TURBO = 3; // Turbo 2
|
|---|
| 4389 | glob->params.CHROMA_ME = 1; // ON
|
|---|
| 4390 | glob->params.PART_4X4 = 0; // OFF
|
|---|
| 4391 | glob->params.BIDIR_ME = 0; // OFF
|
|---|
| 4392 | glob->params.USE3RDPASS = 0; // OFF
|
|---|
| 4393 | glob->params.LEVEL = 9; // Level auto
|
|---|
| 4394 | glob->params.EMBEDUUID = 0; // OFF
|
|---|
| 4395 |
|
|---|
| 4396 | glob->params.FLAG2_BPYRAMID = TRUE;
|
|---|
| 4397 | glob->params.FLAG2_WPRED = TRUE;
|
|---|
| 4398 | glob->params.FLAG2_MIXED_REFS = TRUE;
|
|---|
| 4399 | glob->params.FLAG2_8X8DCT = TRUE;
|
|---|
| 4400 | glob->params.FLAG2_FASTPSKIP = TRUE;
|
|---|
| 4401 | glob->params.FLAG2_AUD = FALSE;
|
|---|
| 4402 | glob->params.FLAG2_BRDO = FALSE;
|
|---|
| 4403 | glob->params.FLAG2_MBTREE = TRUE;
|
|---|
| 4404 | glob->params.FLAG2_PSY = TRUE;
|
|---|
| 4405 | glob->params.FLAG2_SSIM = FALSE;
|
|---|
| 4406 |
|
|---|
| 4407 | glob->params.RC_BUFSIZE = 0; // treated as 0 bit
|
|---|
| 4408 | glob->params.AQ_STRENGTH = 100; // 1.0
|
|---|
| 4409 | glob->params.PSYRD_RDO = 10; // 1.0
|
|---|
| 4410 | glob->params.PSYRD_TRELLIS = 0; // 0.0
|
|---|
| 4411 |
|
|---|
| 4412 | glob->params.DEBLOCK_ALPHA = 0; // 0
|
|---|
| 4413 | glob->params.DEBLOCK_BETA = 0; // 0
|
|---|
| 4414 | glob->params.AQ_MODE = 2; // VARIANCE
|
|---|
| 4415 | glob->params.LUMI_MASKING = 0; // 0:OFF
|
|---|
| 4416 |
|
|---|
| 4417 | glob->params.KEYINT_MIN = 0; // 0:auto
|
|---|
| 4418 | glob->params.CQM_PRESET = 0; // 0:flat16
|
|---|
| 4419 | glob->params.NO_DCT_DECIMATE = 0; // 0:On
|
|---|
| 4420 | glob->params.MAX_QDIFF = 4; // 4
|
|---|
| 4421 |
|
|---|
| 4422 | glob->params.CHROMAOFFSET = 0; // 0
|
|---|
| 4423 | glob->params.FILTERPRESET = 0; // 0
|
|---|
| 4424 | glob->params.SUBSAMPLING = 0; // 0
|
|---|
| 4425 | glob->params.X264PROFILE = 3; // 3
|
|---|
| 4426 |
|
|---|
| 4427 | glob->params.X264PRESET = 0; // 0
|
|---|
| 4428 | glob->params.X264TUNE = 0; // 0
|
|---|
| 4429 | // glob->params.MBTREE = 1; // 1:ON
|
|---|
| 4430 | // glob->params.PSY = 1; // 1:ON
|
|---|
| 4431 |
|
|---|
| 4432 | glob->params.RC_LOOKAHEAD = 40; // 40
|
|---|
| 4433 | glob->params.IP_FACTOR = 140; // 1.4
|
|---|
| 4434 | glob->params.PB_FACTOR = 130; // 1.3
|
|---|
| 4435 |
|
|---|
| 4436 | glob->params.WEIGHTP = 3; // Smart analysis
|
|---|
| 4437 | glob->params.TOPFIELDFIRST = 0; // Progressive or Bottom field first
|
|---|
| 4438 | glob->params.LOSSLESS = 0; // No lossless
|
|---|
| 4439 | glob->params.BD_TUNE = 0; // OFF
|
|---|
| 4440 |
|
|---|
| 4441 | glob->params.USEASPECTRATIO = 0; // Square pixel
|
|---|
| 4442 | glob->params.USECLEANAPERTURE = 0; // Fully Clean Aperture
|
|---|
| 4443 | glob->params.TAGASPECTRATIO = 0; // Custom
|
|---|
| 4444 | glob->params.TAGCLEANAPERTURE = 0; // Custom
|
|---|
| 4445 |
|
|---|
| 4446 | glob->params.hSpacing = 1; // Square pixel
|
|---|
| 4447 | glob->params.vSpacing = 1; // Square pixel
|
|---|
| 4448 | glob->params.cleanApertureWidthN = 0; // undefined
|
|---|
| 4449 | glob->params.cleanApertureWidthD = 1; // equal denomiter
|
|---|
| 4450 | glob->params.cleanApertureHeightN = 0; // undefined
|
|---|
| 4451 | glob->params.cleanApertureHeightD = 1; // equal denomiter
|
|---|
| 4452 | glob->params.horizOffN = 0; // no offset
|
|---|
| 4453 | glob->params.horizOffD = 1; // equal denomiter
|
|---|
| 4454 | glob->params.vertOffN = 0; // no offset
|
|---|
| 4455 | glob->params.vertOffD = 1; // equal denomiter
|
|---|
| 4456 |
|
|---|
| 4457 | glob->params.OVERRIDECRFQSCALE = 0; // OFF
|
|---|
| 4458 | glob->params.USERCRFQSCALE = 23; // 23
|
|---|
| 4459 | glob->params.OVERRIDEQMIN = 1; // ON
|
|---|
| 4460 | glob->params.USERQMIN = 4; // 4
|
|---|
| 4461 | #endif
|
|---|
| 4462 | #if MPEG4
|
|---|
| 4463 | // Initial values for CODE_ID_MPEG4
|
|---|
| 4464 | glob->params.FLAG_QSCALE = FALSE;
|
|---|
| 4465 | glob->params.FLAG_4MV = TRUE;
|
|---|
| 4466 | glob->params.FLAG_QPEL = FALSE;
|
|---|
| 4467 | glob->params.FLAG_GMC = FALSE;
|
|---|
| 4468 | glob->params.FLAG_MV0 = TRUE;
|
|---|
| 4469 | glob->params.FLAG_PART = FALSE;
|
|---|
| 4470 | glob->params.FLAG_LOOP_FILTER = FALSE;
|
|---|
| 4471 | glob->params.FLAG_PSNR = FALSE;
|
|---|
| 4472 | glob->params.FLAG_NORMALIZE_AQP = FALSE;
|
|---|
| 4473 | glob->params.FLAG_INTERLACED_DCT = FALSE;
|
|---|
| 4474 | glob->params.FLAG_AC_PRED = FALSE;
|
|---|
| 4475 | glob->params.FLAG_CBP_RD = FALSE;
|
|---|
| 4476 | glob->params.FLAG_QP_RD = FALSE;
|
|---|
| 4477 | glob->params.FLAG_CLOSED_GOP = TRUE;
|
|---|
| 4478 |
|
|---|
| 4479 | glob->params.NATIVE_FPS = 1; // NTSC
|
|---|
| 4480 | glob->params.MB_DECISION = 2; // BITS
|
|---|
| 4481 | glob->params.RC_QSQUISH = 1; // no clip
|
|---|
| 4482 | glob->params.MPEG_QUANT = 0; // h263
|
|---|
| 4483 | glob->params.THREADS = 9; // Auto thread
|
|---|
| 4484 | glob->params.GAMMA = 0; // no gamma
|
|---|
| 4485 | glob->params.NCLC = 1; // no nclc
|
|---|
| 4486 | glob->params.ME_METHOD = 1; // DIA(EPZS)
|
|---|
| 4487 |
|
|---|
| 4488 | glob->params.SC_THRESHOLD = 0; //
|
|---|
| 4489 | glob->params.QCOMPRESS = 60; // 0.60
|
|---|
| 4490 | glob->params.NOISE_REDUCTION = 0; //
|
|---|
| 4491 | glob->params.RC_MAXRATE = 0; //
|
|---|
| 4492 |
|
|---|
| 4493 | glob->params.REFS = 1; //
|
|---|
| 4494 | glob->params.ME_RANGE = 16; //
|
|---|
| 4495 | glob->params.MAX_BFRAMES = 1; //
|
|---|
| 4496 | glob->params.CODER_TYPE = 1; // CAVLC
|
|---|
| 4497 | glob->params.DIRECTPRED = 3; // Temporal
|
|---|
| 4498 | glob->params.CRF = 0; // No crf
|
|---|
| 4499 | glob->params.ADAPTIVE_BFRAME = 0; // No adaptive b frame
|
|---|
| 4500 | glob->params.ME_SUBQ = 8; //
|
|---|
| 4501 |
|
|---|
| 4502 | glob->params.TRELLIS = 1; // Disabled
|
|---|
| 4503 | glob->params.TURBO = 2; // Turbo 1
|
|---|
| 4504 | glob->params.CHROMA_ME = 0; // OFF
|
|---|
| 4505 | glob->params.PART_4X4 = 0; // OFF
|
|---|
| 4506 | glob->params.BIDIR_ME = 0; // OFF
|
|---|
| 4507 | glob->params.USE3RDPASS = 0; // OFF
|
|---|
| 4508 | glob->params.LEVEL = 9; // Level auto
|
|---|
| 4509 | glob->params.EMBEDUUID = 0; // OFF
|
|---|
| 4510 |
|
|---|
| 4511 | glob->params.FLAG2_BPYRAMID = FALSE;
|
|---|
| 4512 | glob->params.FLAG2_WPRED = FALSE;
|
|---|
| 4513 | glob->params.FLAG2_MIXED_REFS = FALSE;
|
|---|
| 4514 | glob->params.FLAG2_8X8DCT = FALSE;
|
|---|
| 4515 | glob->params.FLAG2_FASTPSKIP = FALSE;
|
|---|
| 4516 | glob->params.FLAG2_AUD = FALSE;
|
|---|
| 4517 | glob->params.FLAG2_BRDO = FALSE;
|
|---|
| 4518 | glob->params.FLAG2_MBTREE = FALSE;
|
|---|
| 4519 | glob->params.FLAG2_PSY = FALSE;
|
|---|
| 4520 | glob->params.FLAG2_SSIM = FALSE;
|
|---|
| 4521 |
|
|---|
| 4522 | glob->params.RC_BUFSIZE = 0; // treated as 0 bit
|
|---|
| 4523 | glob->params.AQ_STRENGTH = 100; // 1.0
|
|---|
| 4524 | glob->params.PSYRD_RDO = 10; // 1.0
|
|---|
| 4525 | glob->params.PSYRD_TRELLIS = 0; // 0.0
|
|---|
| 4526 |
|
|---|
| 4527 | glob->params.DEBLOCK_ALPHA = 0; // 0
|
|---|
| 4528 | glob->params.DEBLOCK_BETA = 0; // 0
|
|---|
| 4529 | glob->params.AQ_MODE = 2; // VARIANCE
|
|---|
| 4530 | glob->params.LUMI_MASKING = 0; // 0:OFF
|
|---|
| 4531 |
|
|---|
| 4532 | glob->params.KEYINT_MIN = 25; // 25
|
|---|
| 4533 | glob->params.CQM_PRESET = 0; // 0:flat16
|
|---|
| 4534 | glob->params.NO_DCT_DECIMATE = 1; // 1:Off
|
|---|
| 4535 | glob->params.MAX_QDIFF = 3; // 3
|
|---|
| 4536 |
|
|---|
| 4537 | glob->params.CHROMAOFFSET = 0; // 0
|
|---|
| 4538 | glob->params.FILTERPRESET = 0; // 0
|
|---|
| 4539 | glob->params.SUBSAMPLING = 0; // 0
|
|---|
| 4540 | glob->params.X264PROFILE = 3; // 3
|
|---|
| 4541 |
|
|---|
| 4542 | glob->params.X264PRESET = 0; // 0
|
|---|
| 4543 | glob->params.X264TUNE = 0; // 0
|
|---|
| 4544 | // glob->params.MBTREE = 0; // 0:OFF
|
|---|
| 4545 | // glob->params.PSY = 0; // 0:OFF
|
|---|
| 4546 |
|
|---|
| 4547 | glob->params.RC_LOOKAHEAD = 0; // 0
|
|---|
| 4548 | glob->params.IP_FACTOR = 125; // 1.25
|
|---|
| 4549 | glob->params.PB_FACTOR = 125; // 1.25
|
|---|
| 4550 |
|
|---|
| 4551 | glob->params.WEIGHTP = 1; // Disabled
|
|---|
| 4552 | glob->params.TOPFIELDFIRST = 0; // Progressive or Bottom field first
|
|---|
| 4553 | glob->params.LOSSLESS = 0; // No lossless
|
|---|
| 4554 | glob->params.BD_TUNE = 0; // OFF
|
|---|
| 4555 |
|
|---|
| 4556 | glob->params.USEASPECTRATIO = 0; // Square pixel
|
|---|
| 4557 | glob->params.USECLEANAPERTURE = 0; // Fully Clean Aperture
|
|---|
| 4558 | glob->params.TAGASPECTRATIO = 0; // Custom
|
|---|
| 4559 | glob->params.TAGCLEANAPERTURE = 0; // Custom
|
|---|
| 4560 |
|
|---|
| 4561 | glob->params.hSpacing = 1; // Square pixel
|
|---|
| 4562 | glob->params.vSpacing = 1; // Square pixel
|
|---|
| 4563 | glob->params.cleanApertureWidthN = 0; // undefined
|
|---|
| 4564 | glob->params.cleanApertureWidthD = 1; // equal denomiter
|
|---|
| 4565 | glob->params.cleanApertureHeightN = 0; // undefined
|
|---|
| 4566 | glob->params.cleanApertureHeightD = 1; // equal denomiter
|
|---|
| 4567 | glob->params.horizOffN = 0; // no offset
|
|---|
| 4568 | glob->params.horizOffD = 1; // equal denomiter
|
|---|
| 4569 | glob->params.vertOffN = 0; // no offset
|
|---|
| 4570 | glob->params.vertOffD = 1; // equal denomiter
|
|---|
| 4571 |
|
|---|
| 4572 | glob->params.OVERRIDECRFQSCALE = 0; // OFF
|
|---|
| 4573 | glob->params.USERCRFQSCALE = 2; // 2
|
|---|
| 4574 | glob->params.OVERRIDEQMIN = 0; // OFF
|
|---|
| 4575 | glob->params.USERQMIN = 2; // 2
|
|---|
| 4576 | #endif
|
|---|
| 4577 | #if XVID
|
|---|
| 4578 | // Initial values for CODE_ID_MPEG4
|
|---|
| 4579 | glob->params.FLAG_QSCALE = FALSE;
|
|---|
| 4580 | glob->params.FLAG_4MV = TRUE;
|
|---|
| 4581 | glob->params.FLAG_QPEL = FALSE;
|
|---|
| 4582 | glob->params.FLAG_GMC = FALSE;
|
|---|
| 4583 | glob->params.FLAG_MV0 = FALSE;
|
|---|
| 4584 | glob->params.FLAG_PART = FALSE;
|
|---|
| 4585 | glob->params.FLAG_LOOP_FILTER = FALSE;
|
|---|
| 4586 | glob->params.FLAG_PSNR = FALSE;
|
|---|
| 4587 | glob->params.FLAG_NORMALIZE_AQP = FALSE;
|
|---|
| 4588 | glob->params.FLAG_INTERLACED_DCT = FALSE;
|
|---|
| 4589 | glob->params.FLAG_AC_PRED = TRUE;
|
|---|
| 4590 | glob->params.FLAG_CBP_RD = FALSE;
|
|---|
| 4591 | glob->params.FLAG_QP_RD = FALSE;
|
|---|
| 4592 | glob->params.FLAG_CLOSED_GOP = TRUE;
|
|---|
| 4593 |
|
|---|
| 4594 | glob->params.NATIVE_FPS = 1; // NTSC
|
|---|
| 4595 | glob->params.MB_DECISION = 1; // SIMPLE
|
|---|
| 4596 | glob->params.RC_QSQUISH = 0; // no clip
|
|---|
| 4597 | glob->params.MPEG_QUANT = 0; // h263
|
|---|
| 4598 | glob->params.THREADS = 9; // Auto thread
|
|---|
| 4599 | glob->params.GAMMA = 0; // no gamma
|
|---|
| 4600 | glob->params.NCLC = 1; // no nclc
|
|---|
| 4601 | glob->params.ME_METHOD = 4; // FULL
|
|---|
| 4602 |
|
|---|
| 4603 | glob->params.SC_THRESHOLD = 0; //
|
|---|
| 4604 | glob->params.QCOMPRESS = 60; // 0.60
|
|---|
| 4605 | glob->params.NOISE_REDUCTION = 0; //
|
|---|
| 4606 | glob->params.RC_MAXRATE = 0; //
|
|---|
| 4607 |
|
|---|
| 4608 | glob->params.REFS = 1; //
|
|---|
| 4609 | glob->params.ME_RANGE = 16; //
|
|---|
| 4610 | glob->params.MAX_BFRAMES = 1; //
|
|---|
| 4611 | glob->params.CODER_TYPE = 1; // CAVLC
|
|---|
| 4612 | glob->params.DIRECTPRED = 3; // Temporal
|
|---|
| 4613 | glob->params.CRF = 0; // No crf
|
|---|
| 4614 | glob->params.ADAPTIVE_BFRAME = 0; // No adaptive b frame
|
|---|
| 4615 | glob->params.ME_SUBQ = 8; //
|
|---|
| 4616 |
|
|---|
| 4617 | glob->params.TRELLIS = 3; // All
|
|---|
| 4618 | glob->params.TURBO = 1; // Disabled
|
|---|
| 4619 | glob->params.CHROMA_ME = 1; // ON
|
|---|
| 4620 | glob->params.PART_4X4 = 0; // OFF
|
|---|
| 4621 | glob->params.BIDIR_ME = 0; // OFF
|
|---|
| 4622 | glob->params.USE3RDPASS = 0; // OFF
|
|---|
| 4623 | glob->params.LEVEL = 9; // Level auto
|
|---|
| 4624 | glob->params.EMBEDUUID = 0; // OFF
|
|---|
| 4625 |
|
|---|
| 4626 | glob->params.FLAG2_BPYRAMID = FALSE;
|
|---|
| 4627 | glob->params.FLAG2_WPRED = FALSE;
|
|---|
| 4628 | glob->params.FLAG2_MIXED_REFS = FALSE;
|
|---|
| 4629 | glob->params.FLAG2_8X8DCT = FALSE;
|
|---|
| 4630 | glob->params.FLAG2_FASTPSKIP = FALSE;
|
|---|
| 4631 | glob->params.FLAG2_AUD = FALSE;
|
|---|
| 4632 | glob->params.FLAG2_BRDO = FALSE;
|
|---|
| 4633 | glob->params.FLAG2_MBTREE = FALSE;
|
|---|
| 4634 | glob->params.FLAG2_PSY = FALSE;
|
|---|
| 4635 | glob->params.FLAG2_SSIM = FALSE;
|
|---|
| 4636 |
|
|---|
| 4637 | glob->params.RC_BUFSIZE = 0; // treated as 0 bit
|
|---|
| 4638 | glob->params.AQ_STRENGTH = 100; // 1.0
|
|---|
| 4639 | glob->params.PSYRD_RDO = 10; // 1.0
|
|---|
| 4640 | glob->params.PSYRD_TRELLIS = 0; // 0.0
|
|---|
| 4641 |
|
|---|
| 4642 | glob->params.DEBLOCK_ALPHA = 0; // 0
|
|---|
| 4643 | glob->params.DEBLOCK_BETA = 0; // 0
|
|---|
| 4644 | glob->params.AQ_MODE = 2; // VARIANCE
|
|---|
| 4645 | glob->params.LUMI_MASKING = 0; // 0:OFF
|
|---|
| 4646 |
|
|---|
| 4647 | glob->params.KEYINT_MIN = 25; // 25
|
|---|
| 4648 | glob->params.CQM_PRESET = 0; // 0:flat16
|
|---|
| 4649 | glob->params.NO_DCT_DECIMATE = 1; // 1:Off
|
|---|
| 4650 | glob->params.MAX_QDIFF = 3; // 3
|
|---|
| 4651 |
|
|---|
| 4652 | glob->params.CHROMAOFFSET = 0; // 0
|
|---|
| 4653 | glob->params.FILTERPRESET = 0; // 0
|
|---|
| 4654 | glob->params.SUBSAMPLING = 0; // 0
|
|---|
| 4655 | glob->params.X264PROFILE = 3; // 3
|
|---|
| 4656 |
|
|---|
| 4657 | glob->params.X264PRESET = 0; // 0
|
|---|
| 4658 | glob->params.X264TUNE = 0; // 0
|
|---|
| 4659 | // glob->params.MBTREE = 0; // 0:OFF
|
|---|
| 4660 | // glob->params.PSY = 0; // 0:OFF
|
|---|
| 4661 |
|
|---|
| 4662 | glob->params.RC_LOOKAHEAD = 0; // 0
|
|---|
| 4663 | glob->params.IP_FACTOR = 125; // 1.25
|
|---|
| 4664 | glob->params.PB_FACTOR = 150; // 1.5
|
|---|
| 4665 |
|
|---|
| 4666 | glob->params.WEIGHTP = 1; // Disabled
|
|---|
| 4667 | glob->params.TOPFIELDFIRST = 0; // Progressive or Bottom field first
|
|---|
| 4668 | glob->params.LOSSLESS = 0; // No lossless
|
|---|
| 4669 | glob->params.BD_TUNE = 0; // OFF
|
|---|
| 4670 |
|
|---|
| 4671 | glob->params.USEASPECTRATIO = 0; // Square pixel
|
|---|
| 4672 | glob->params.USECLEANAPERTURE = 0; // Fully Clean Aperture
|
|---|
| 4673 | glob->params.TAGASPECTRATIO = 0; // Custom
|
|---|
| 4674 | glob->params.TAGCLEANAPERTURE = 0; // Custom
|
|---|
| 4675 |
|
|---|
| 4676 | glob->params.hSpacing = 1; // Square pixel
|
|---|
| 4677 | glob->params.vSpacing = 1; // Square pixel
|
|---|
| 4678 | glob->params.cleanApertureWidthN = 0; // undefined
|
|---|
| 4679 | glob->params.cleanApertureWidthD = 1; // equal denomiter
|
|---|
| 4680 | glob->params.cleanApertureHeightN = 0; // undefined
|
|---|
| 4681 | glob->params.cleanApertureHeightD = 1; // equal denomiter
|
|---|
| 4682 | glob->params.horizOffN = 0; // no offset
|
|---|
| 4683 | glob->params.horizOffD = 1; // equal denomiter
|
|---|
| 4684 | glob->params.vertOffN = 0; // no offset
|
|---|
| 4685 | glob->params.vertOffD = 1; // equal denomiter
|
|---|
| 4686 |
|
|---|
| 4687 | glob->params.OVERRIDECRFQSCALE = 0; // OFF
|
|---|
| 4688 | glob->params.USERCRFQSCALE = 2; // 2
|
|---|
| 4689 | glob->params.OVERRIDEQMIN = 0; // OFF
|
|---|
| 4690 | glob->params.USERQMIN = 2; // 2
|
|---|
| 4691 | #endif
|
|---|
| 4692 | } // initValues()
|
|---|