26 #import <QuartzCore/CoreImage.h>
27 #import <AppKit/AppKit.h>
97 NSArray *filter_categories = nil;
100 filter_categories = [NSArray arrayWithObjects:kCICategoryGenerator, nil];
103 NSArray *filter_names = [CIFilter filterNamesInCategories:filter_categories];
104 NSEnumerator *
filters = [filter_names objectEnumerator];
106 NSString *filter_name;
107 while (filter_name = [filters nextObject]) {
111 CIFilter *
filter = [CIFilter filterWithName:filter_name];
112 NSDictionary *filter_attribs = [filter attributes];
113 NSArray *filter_inputs = [filter inputKeys];
115 for (input
in filter_inputs) {
116 NSDictionary *input_attribs = [filter_attribs valueForKey:input];
117 NSString *input_class = [input_attribs valueForKey:kCIAttributeClass];
118 if ([input_class isEqualToString:
@"NSNumber"]) {
119 NSNumber *value_default = [input_attribs valueForKey:kCIAttributeDefault];
120 NSNumber *value_min = [input_attribs valueForKey:kCIAttributeSliderMin];
121 NSNumber *value_max = [input_attribs valueForKey:kCIAttributeSliderMax];
125 [input_class UTF8String],
126 [[value_min stringValue] UTF8String],
127 [[value_max stringValue] UTF8String],
128 [[value_default stringValue] UTF8String]);
132 [input_class UTF8String]);
191 NSData *
data = [NSData dataWithBytesNoCopy:frame->data[0]
192 length:frame->height*frame->linesize[0]
195 CIImage *ret = [(__bridge CIImage*)ctx->input_image initWithBitmapData:data
196 bytesPerRow:frame->linesize[0]
198 format:kCIFormatARGB8
199 colorSpace:ctx->color_space];
206 CIImage *filter_input = (__bridge CIImage*)ctx->
input_image;
207 CIImage *filter_output =
NULL;
213 filter_input = [(__bridge CIImage*)ctx->filters[i-1] valueForKey:kCIOutputImageKey];
214 CGRect out_rect = [filter_input extent];
215 if (out_rect.size.width > frame->
width || out_rect.size.height > frame->
height) {
217 out_rect.origin.x = 0.0f;
218 out_rect.origin.y = 0.0f;
219 out_rect.size.width = frame->
width;
220 out_rect.size.height = frame->
height;
222 filter_input = [filter_input imageByCroppingToRect:out_rect];
225 filter = (__bridge CIFilter*)ctx->
filters[i];
230 [filter setValue:filter_input forKey:kCIInputImageKey];
231 }
@catch (NSException *exception) {
232 if (![[exception
name] isEqualToString:NSUndefinedKeyException]) {
243 filter_output = [filter valueForKey:kCIOutputImageKey];
245 if (!filter_output) {
251 CGRect out_rect = [filter_output extent];
252 if (out_rect.size.width > frame->
width || out_rect.size.height > frame->
height) {
254 out_rect.origin.x = 0.0f;
255 out_rect.origin.y = 0.0f;
256 out_rect.size.width = frame->
width;
257 out_rect.size.height = frame->
height;
260 CGImageRef
out = [(__bridge CIContext*)ctx->glctx createCGImage:filter_output
269 CGContextRelease(ctx->
cgctx);
272 size_t out_width = CGImageGetWidth(out);
273 size_t out_height = CGImageGetHeight(out);
275 if (out_width > frame->
width || out_height > frame->
height) {
276 av_log(ctx,
AV_LOG_WARNING,
"Output image has unexpected size: %lux%lu (expected: %ix%i). This may crash...\n",
277 out_width, out_height, frame->
width, frame->
height);
279 ctx->
cgctx = CGBitmapContextCreate(frame->
data[0],
285 (uint32_t)kCGImageAlphaPremultipliedFirst);
295 NSString *tmp_string = [NSString stringWithUTF8String:ctx->output_rect];
296 NSRect
tmp = NSRectFromString(tmp_string);
297 rect = NSRectToCGRect(tmp);
298 }
@catch (NSException *exception) {
302 if (rect.size.width == 0.0f) {
305 if (rect.size.height == 0.0f) {
310 CGContextDrawImage(ctx->
cgctx, rect, out);
360 NSString *input_key = [NSString stringWithUTF8String:key];
361 NSString *input_val = [NSString stringWithUTF8String:value];
363 NSDictionary *filter_attribs = [filter attributes];
364 NSDictionary *input_attribs = [filter_attribs valueForKey:input_key];
366 NSString *input_class = [input_attribs valueForKey:kCIAttributeClass];
367 NSString *input_type = [input_attribs valueForKey:kCIAttributeType];
369 if (!input_attribs) {
371 [input_key UTF8String]);
376 [input_key UTF8String],
377 [input_val UTF8String],
378 input_attribs ? (
unsigned long)[input_attribs
count] : -1,
379 [input_class UTF8String],
380 [input_type UTF8String]);
382 if ([input_class isEqualToString:
@"NSNumber"]) {
383 float input = input_val.floatValue;
384 NSNumber *max_value = [input_attribs valueForKey:kCIAttributeSliderMax];
385 NSNumber *min_value = [input_attribs valueForKey:kCIAttributeSliderMin];
386 NSNumber *used_value = nil;
388 #define CLAMP_WARNING do { \
389 av_log(ctx, AV_LOG_WARNING, "Value of \"%f\" for option \"%s\" is out of range [%f %f], clamping to \"%f\".\n", \
391 [input_key UTF8String], \
392 min_value.floatValue, \
393 max_value.floatValue, \
394 used_value.floatValue); \
396 if (input > max_value.floatValue) {
397 used_value = max_value;
399 }
else if (input < min_value.floatValue) {
400 used_value = min_value;
403 used_value = [NSNumber numberWithFloat:input];
406 [filter setValue:used_value forKey:input_key];
407 }
else if ([input_class isEqualToString:
@"CIVector"]) {
408 CIVector *input = [CIVector vectorWithString:input_val];
412 [input_val UTF8String]);
416 [filter setValue:input forKey:input_key];
417 }
else if ([input_class isEqualToString:
@"CIColor"]) {
418 CIColor *input = [CIColor colorWithString:input_val];
422 [input_val UTF8String]);
426 [filter setValue:input forKey:input_key];
427 }
else if ([input_class isEqualToString:
@"NSString"]) {
428 [filter setValue:input_val forKey:input_key];
429 }
else if ([input_class isEqualToString:
@"NSData"]) {
430 NSData *input = [NSData dataWithBytes:(const void*)[input_val cStringUsingEncoding:NSISOLatin1StringEncoding]
431 length:[input_val lengthOfBytesUsingEncoding:NSISOLatin1StringEncoding]];
435 [input_val UTF8String]);
439 [filter setValue:input forKey:input_key];
442 [input_class UTF8String]);
454 CIFilter *
filter = [CIFilter filterWithName:[NSString stringWithUTF8String:filter_name]];
457 [filter setDefaults];
460 if (filter_options) {
507 if (strncmp(f->
value,
"default", 7)) {
517 if (!filter_options) {
540 const NSOpenGLPixelFormatAttribute attr[] = {
541 NSOpenGLPFAAccelerated,
542 NSOpenGLPFANoRecovery,
543 NSOpenGLPFAColorSize, 32,
547 NSOpenGLPixelFormat *pixel_format = [[NSOpenGLPixelFormat alloc] initWithAttributes:(void *)&attr];
548 ctx->
color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
549 ctx->
glctx = CFBridgingRetain([CIContext contextWithCGLContext:CGLGetCurrentContext()
550 pixelFormat:[pixel_format CGLPixelFormatObj]
560 ctx->
input_image = CFBridgingRetain([CIImage emptyImage]);
578 #define SafeCFRelease(ptr) do { \
630 #define OFFSET(x) offsetof(CoreImageContext, x)
631 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
633 #define GENERATOR_OPTIONS \
634 {"size", "set video size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str = "320x240"}, 0, 0, FLAGS}, \
635 {"s", "set video size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str = "320x240"}, 0, 0, FLAGS}, \
636 {"rate", "set video rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, FLAGS}, \
637 {"r", "set video rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, FLAGS}, \
638 {"duration", "set video duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64 = -1}, -1, INT64_MAX, FLAGS}, \
639 {"d", "set video duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64 = -1}, -1, INT64_MAX, FLAGS}, \
640 {"sar", "set video sample aspect ratio", OFFSET(sar), AV_OPT_TYPE_RATIONAL, {.dbl = 1}, 0, INT_MAX, FLAGS},
642 #define FILTER_OPTIONS \
643 {"list_filters", "list available filters", OFFSET(list_filters), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, .flags = FLAGS}, \
644 {"list_generators", "list available generators", OFFSET(list_generators), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, .flags = FLAGS}, \
645 {"filter", "names and options of filters to apply", OFFSET(filter_string), AV_OPT_TYPE_STRING, {.str = NULL}, .flags = FLAGS}, \
646 {"output_rect", "output rectangle within output image", OFFSET(output_rect), AV_OPT_TYPE_STRING, {.str = NULL}, .flags = FLAGS},
663 .priv_class = &coreimage_class,
664 .
inputs = vf_coreimage_inputs,
665 .
outputs = vf_coreimage_outputs,
679 .
name =
"coreimagesrc",
684 .priv_class = &coreimagesrc_class,
686 .
outputs = vsrc_coreimagesrc_outputs,
CGColorSpaceRef color_space
Common color space for input image and cgcontext.
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
This structure describes decoded (raw) audio or video data.
ptrdiff_t const GLvoid * data
#define AV_LOG_WARNING
Something somehow does not look correct.
Main libavfilter public API header.
int av_get_bits_per_pixel(const AVPixFmtDescriptor *pixdesc)
Return the number of bits per pixel used by the pixel format described by pixdesc.
int h
agreed upon image height
static int config_output(AVFilterLink *link)
int av_dict_count(const AVDictionary *m)
Get number of entries in dictionary.
static av_cold void uninit(AVFilterContext *fctx)
static int config_input(AVFilterLink *link)
Determine image properties from input link of filter chain.
CFTypeRef glctx
OpenGL context.
int list_filters
Option used to list all available filters including generators.
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
#define SafeCFRelease(ptr)
#define GENERATOR_OPTIONS
int64_t duration
duration expressed in microseconds
static int query_formats_src(AVFilterContext *fctx)
static int query_formats(AVFilterContext *fctx)
const char * name
Pad name.
AVFilterLink ** inputs
array of pointers to input links
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
#define AV_DICT_MULTIKEY
Allow to store several equal keys in the dictionary.
static const AVFilterPad vf_coreimage_inputs[]
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
static void filter(int16_t *output, ptrdiff_t out_stride, int16_t *low, ptrdiff_t low_stride, int16_t *high, ptrdiff_t high_stride, int len, uint8_t clip)
static const AVOption coreimage_options[]
AVDictionaryEntry * av_dict_get(const AVDictionary *m, const char *key, const AVDictionaryEntry *prev, int flags)
Get a dictionary entry with matching key.
#define AVERROR_EOF
End of file.
static void list_filters(CoreImageContext *ctx)
Print a list of all available filters including options and respective value ranges and defaults...
int interlaced_frame
The content of the picture is interlaced.
const OptionDef options[]
A filter pad used for either input or output.
AVRational time_base
stream time base
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
A link between two filters.
int width
width and height of the video frame
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
AVFrame * picref
cached reference containing the painted picture
AVRational frame_rate
Frame rate of the stream on the link, or 1/0 if unknown or variable; if left to 0/0, will be automatically copied from the first input of the source filter if it exists.
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
void * priv
private data for use by the filter
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
CFTypeRef input_image
Input image container for passing into Core Image API.
AVRational time_base
Define the time base used by the PTS of the frames/samples which will pass through this link...
int av_log_get_level(void)
Get the current log level.
AVFilterFormats * in_formats
Lists of formats and channel layouts supported by the input and output filters respectively.
AVRational sar
sample aspect ratio
static void * av_mallocz_array(size_t nmemb, size_t size)
packed ARGB 8:8:8:8, 32bpp, ARGBARGB...
static CIFilter * create_filter(CoreImageContext *ctx, const char *filter_name, AVDictionary *filter_options)
Create a filter object by a given name and set all options to defaults.
int w
agreed upon image width
common internal API header
uint8_t nb_components
The number of components each pixel has, (1-4)
CFTypeRef * filters
CIFilter object for all requested filters.
enum AVPictureType pict_type
Picture type of the frame.
GLsizei GLboolean const GLfloat * value
static int request_frame(AVFilterLink *link)
static av_cold int init_src(AVFilterContext *fctx)
AVFilterContext * src
source filter
static const AVFilterPad outputs[]
#define AVERROR_EXIT
Immediate exit was requested; the called function should not be restarted.
AVFrame * av_frame_clone(const AVFrame *src)
Create a new frame that references the same data as src.
int format
agreed upon media format
int64_t pts
increasing presentation time stamp
int av_dict_parse_string(AVDictionary **pm, const char *str, const char *key_val_sep, const char *pairs_sep, int flags)
Parse the key/value pairs list and add the parsed entries to a dictionary.
char * output_rect
Rectangle to be filled with filter intput.
static int filter_frame(AVFilterLink *link, AVFrame *frame)
Apply all valid filters successively to the input image.
#define AV_LOG_INFO
Standard information.
static const AVFilterPad inputs[]
static int apply_filter(CoreImageContext *ctx, AVFilterLink *link, AVFrame *frame)
int bits_per_component
Shared bpc for input-output operation.
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
static av_cold int init(AVFilterContext *fctx)
AVRational sample_aspect_ratio
Sample aspect ratio for the video frame, 0/1 if unknown/unspecified.
uint8_t pi<< 24) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8, uint8_t,(*(constuint8_t *) pi-0x80)*(1.0f/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8, uint8_t,(*(constuint8_t *) pi-0x80)*(1.0/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16, int16_t,(*(constint16_t *) pi >>8)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16, int16_t,*(constint16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16, int16_t,*(constint16_t *) pi *(1.0/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32, int32_t,(*(constint32_t *) pi >>24)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32, int32_t,*(constint32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32, int32_t,*(constint32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, float, av_clip_uint8(lrintf(*(constfloat *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, float, av_clip_int16(lrintf(*(constfloat *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, float, av_clipl_int32(llrintf(*(constfloat *) pi *(1U<< 31)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, double, av_clip_uint8(lrint(*(constdouble *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, double, av_clip_int16(lrint(*(constdouble *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, double, av_clipl_int32(llrint(*(constdouble *) pi *(1U<< 31))))#defineSET_CONV_FUNC_GROUP(ofmt, ifmt) staticvoidset_generic_function(AudioConvert *ac){}voidff_audio_convert_free(AudioConvert **ac){if(!*ac) return;ff_dither_free(&(*ac) ->dc);av_freep(ac);}AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr, enumAVSampleFormatout_fmt, enumAVSampleFormatin_fmt, intchannels, intsample_rate, intapply_map){AudioConvert *ac;intin_planar, out_planar;ac=av_mallocz(sizeof(*ac));if(!ac) returnNULL;ac->avr=avr;ac->out_fmt=out_fmt;ac->in_fmt=in_fmt;ac->channels=channels;ac->apply_map=apply_map;if(avr->dither_method!=AV_RESAMPLE_DITHER_NONE &&av_get_packed_sample_fmt(out_fmt)==AV_SAMPLE_FMT_S16 &&av_get_bytes_per_sample(in_fmt)>2){ac->dc=ff_dither_alloc(avr, out_fmt, in_fmt, channels, sample_rate, apply_map);if(!ac->dc){av_free(ac);returnNULL;}returnac;}in_planar=ff_sample_fmt_is_planar(in_fmt, channels);out_planar=ff_sample_fmt_is_planar(out_fmt, channels);if(in_planar==out_planar){ac->func_type=CONV_FUNC_TYPE_FLAT;ac->planes=in_planar?ac->channels:1;}elseif(in_planar) ac->func_type=CONV_FUNC_TYPE_INTERLEAVE;elseac->func_type=CONV_FUNC_TYPE_DEINTERLEAVE;set_generic_function(ac);if(ARCH_AARCH64) ff_audio_convert_init_aarch64(ac);if(ARCH_ARM) ff_audio_convert_init_arm(ac);if(ARCH_X86) ff_audio_convert_init_x86(ac);returnac;}intff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in){intuse_generic=1;intlen=in->nb_samples;intp;if(ac->dc){av_log(ac->avr, AV_LOG_TRACE,"%dsamples-audio_convert:%sto%s(dithered)\n", len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt));returnff_convert_dither(ac-> in
int num_filters
Amount of filters in *filters.
Describe the class of an AVClass context structure.
Rational number (pair of numerator and denominator).
const char * name
Filter name.
AVRational sample_aspect_ratio
agreed upon sample aspect ratio
AVFilterLink ** outputs
array of pointers to output links
static void set_option(CoreImageContext *ctx, CIFilter *filter, const char *key, const char *value)
Set an option of the given filter to the provided key-value pair.
void avpriv_report_missing_feature(void *avc, const char *msg,...) av_printf_format(2
Log a generic warning message about a missing feature.
int is_video_source
filter is used as video source
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
int list_generators
Option used to list all available generators.
static const AVOption coreimagesrc_options[]
static av_always_inline AVRational av_inv_q(AVRational q)
Invert a rational.
AVRational frame_rate
video frame rate
char * filter_string
The complete user provided filter definition.
AVFILTER_DEFINE_CLASS(coreimage)
AVFilterContext * dst
dest filter
static const struct PPFilter filters[]
int key_frame
1 -> keyframe, 0-> not
CGContextRef cgctx
Bitmap context for image copy.
static const AVFilterPad vf_coreimage_outputs[]
#define AV_DICT_IGNORE_SUFFIX
Return first entry in a dictionary whose first part corresponds to the search key, ignoring the suffix of the found key string.
#define AVERROR_EXTERNAL
Generic error in an external library.
AVPixelFormat
Pixel format.
AVFilter ff_vsrc_coreimagesrc
AVFilterFormats * out_formats
static const AVFilterPad vsrc_coreimagesrc_outputs[]