Ticket #4143: x264Encoder.c

File x264Encoder.c, 154.2 KB (added by Carl Eugen Hoyos, 11 years ago)
Line 
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
9This 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
95typedef 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
265typedef 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
277typedef 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
385typedef void (*InitializeNibProc)();
386typedef void (*SetFourCCProc)(CFStringRef fourCC);
387typedef void (*SetBundleIDProc)(CFStringRef newBundleID);
388typedef params* (*ShowDialogProc)(params* inParams);
389typedef void (*ReleaseNibProc)();
390typedef void (*InitializeCocoaProc)();
391InitializeNibProc uiInitializeNib;
392SetFourCCProc uiSetFourCC;
393SetBundleIDProc uiSetBundleID;
394ShowDialogProc uiShowDialog;
395ReleaseNibProc uiReleaseNib;
396InitializeCocoaProc uiInitializeCocoa;
397
398
399#pragma mark -
400#pragma mark Prototypes
401
402
403static OSStatus setup_codecCont(lavcEncoderGlobalRecord *glob);
404static OSStatus open_libAV(lavcEncoderGlobalRecord *glob);
405static OSStatus process_libAV(lavcEncoderGlobalRecord *glob, ICMCompressorSourceFrameRef source_frame);
406static OSStatus emitFrameData(lavcEncoderGlobalRecord *glob);
407
408static OSStatus createPixelBufferAttributesDictionary( lavcEncoderGlobalRecord *glob,
409 const OSType *pixelFormatList, int pixelFormatCount, CFMutableDictionaryRef *pixelBufferAttributesOut );
410
411static ICMCompressorSourceFrameRef getSourceFrameForEncodedFrame(lavcEncoderGlobalRecord *glob);
412static Boolean removeSourceFrame(lavcEncoderGlobalRecord *glob, ICMCompressorSourceFrameRef source_frame);
413static Boolean doesQueueContainEarlierDisplayNumbers( lavcEncoderGlobalRecord *glob, long display_number );
414static Boolean removeSourceFrameForEncodedFrame( lavcEncoderGlobalRecord *glob );
415
416static Handle avcCExtension( lavcEncoderGlobalRecord *glob );
417static Handle esdsExtension( lavcEncoderGlobalRecord *glob );
418static OSStatus prepareImageDescriptionExtensions(lavcEncoderGlobalRecord *glob);
419
420static void logInfo(lavcEncoderGlobalRecord *glob, char* fmt, ...);
421static void logDebug(lavcEncoderGlobalRecord *glob, char* fmt, ...);
422
423static OSStatus openCoreVF( lavcEncoderGlobals glob );
424static OSStatus closeCoreVF( lavcEncoderGlobals glob );
425
426static void checkValues( lavcEncoderGlobals glob );
427static void initValues( lavcEncoderGlobals glob );
428
429
430#pragma mark -
431#pragma mark Standard Component Call handler
432
433
434// StdComponentCall (Target) // 2
435ComponentResult 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
445ComponentResult 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
458ComponentResult 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
574ComponentResult 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
606ComponentResult 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
628ComponentResult 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
648ComponentResult 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
729ComponentResult 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
771ComponentResult 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
956ComponentResult 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
1270bail:
1271 if(err && !glob->meetsErr) {
1272 AudioServicesPlayAlertSound(kUserPreferredAlert); glob->meetsErr = TRUE;
1273 }
1274 return err;
1275} // ComponentCall (PrepareToCompressFrames)
1276
1277
1278// ComponentCall (EncodeFrame) // 56
1279ComponentResult 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
1524bail:
1525 if(err && !glob->meetsErr) {
1526 AudioServicesPlayAlertSound(kUserPreferredAlert); glob->meetsErr = TRUE;
1527 }
1528 return err;
1529} // ComponentCall (EncodeFrame)
1530
1531
1532// ComponentCall (CompleteFrame) // 57
1533ComponentResult 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
1635bail:
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
1647ComponentResult 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
1851bail:
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
1864ComponentResult 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
1998bail:
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...
2062ComponentResult 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
2131static 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;
2743bail:
2744 return err;
2745}
2746
2747static 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;
2902bail:
2903 return err;
2904}
2905
2906static 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
2980bail:
2981 return err;
2982}
2983
2984
2985// Write out encoded AVFrame into storage
2986static 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
3328bail:
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.
3335static 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
3443bail:
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
3455static 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
3494static 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
3515static 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
3535static 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
3556bail:
3557 return ret;
3558}
3559
3560
3561#pragma mark -
3562
3563
3564// Prepare avcC atom for ImageDescription Extension.
3565static 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
3654bail:
3655 return avcCHdl;
3656} // avcCExtension()
3657
3658
3659// Prepare elementary stream description atom for ImageDescription Extension.
3660static 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//
3735static 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
3986bail:
3987 return err;
3988}
3989
3990
3991#pragma mark -
3992
3993
3994// log Debug support
3995static 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
4010static 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
4029static 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
4110bail:
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
4122static 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
4148static 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
4342static 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()