List pixel formats available on device and select the first one.
Based on Apple documentation, first one is most effective.
---
libavdevice/avfoundation_dec.m | 80 +++++++++++++++++++++++++++++++++++++++---
1 file changed, 76 insertions(+), 4 deletions(-)
diff --git a/libavdevice/avfoundation_dec.m b/libavdevice/avfoundation_dec.m
index b9ed6c1..7bac610 100644
--- a/libavdevice/avfoundation_dec.m
+++ b/libavdevice/avfoundation_dec.m
@@ -33,10 +33,46 @@
#include "avdevice.h"
+struct AVFPixelFormatSpec {
+ enum AVPixelFormat ff_id;
+ OSType avf_id;
+};
+
+static const struct AVFPixelFormatSpec avf_pixel_formats[] = {
+ { AV_PIX_FMT_MONOBLACK, kCVPixelFormatType_1Monochrome },
+ { AV_PIX_FMT_RGB555BE, kCVPixelFormatType_16BE555 },
+ { AV_PIX_FMT_RGB555LE, kCVPixelFormatType_16LE555 },
+ { AV_PIX_FMT_RGB565BE, kCVPixelFormatType_16BE565 },
+ { AV_PIX_FMT_RGB565LE, kCVPixelFormatType_16LE565 },
+ { AV_PIX_FMT_RGB24, kCVPixelFormatType_24RGB },
+ { AV_PIX_FMT_BGR24, kCVPixelFormatType_24BGR },
+ { AV_PIX_FMT_ARGB, kCVPixelFormatType_32ARGB },
+ { AV_PIX_FMT_BGRA, kCVPixelFormatType_32BGRA },
+ { AV_PIX_FMT_ABGR, kCVPixelFormatType_32ABGR },
+ { AV_PIX_FMT_RGBA, kCVPixelFormatType_32RGBA },
+ { AV_PIX_FMT_BGR48BE, kCVPixelFormatType_48RGB },
+ { AV_PIX_FMT_UYVY422, kCVPixelFormatType_422YpCbCr8 },
+ { AV_PIX_FMT_YUVA444P, kCVPixelFormatType_4444YpCbCrA8R },
+ { AV_PIX_FMT_YUVA444P16LE, kCVPixelFormatType_4444AYpCbCr16 },
+ { AV_PIX_FMT_YUV444P, kCVPixelFormatType_444YpCbCr8 },
+ { AV_PIX_FMT_YUV422P16, kCVPixelFormatType_422YpCbCr16 },
+ { AV_PIX_FMT_YUV422P10, kCVPixelFormatType_422YpCbCr10 },
+ { AV_PIX_FMT_YUV444P10, kCVPixelFormatType_444YpCbCr10 },
+ { AV_PIX_FMT_YUV420P, kCVPixelFormatType_420YpCbCr8Planar },
+ { AV_PIX_FMT_NV12, kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange
},
+ { AV_PIX_FMT_YUYV422, kCVPixelFormatType_422YpCbCr8_yuvs },
+#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1080
+ { AV_PIX_FMT_GRAY8, kCVPixelFormatType_OneComponent8 },
+#endif
+ { AV_PIX_FMT_NONE, 0 }
+};
+
typedef struct AVFoundationCaptureContext {
AVClass *class;
int list_devices;
+ enum AVPixelFormat pixel_format;
+
int video_stream_index;
int64_t first_pts;
@@ -189,9 +225,46 @@ static int setup_stream(AVFormatContext *s,
AVCaptureDevice *device)
}
[out setAlwaysDiscardsLateVideoFrames:YES];
- out.videoSettings = @{(id)kCVPixelBufferPixelFormatTypeKey:
@(kCVPixelFormatType_32BGRA)};
- //[out setVideoSettings:nil];
+
+ // select pixel format
+ struct AVFPixelFormatSpec pxl_fmt_spec;
+ pxl_fmt_spec.ff_id = AV_PIX_FMT_NONE;
+
+ av_log(s, AV_LOG_ERROR, "Supported pixel formats:\n");
+ for (NSNumber *pxl_fmt in [out availableVideoCVPixelFormatTypes]) {
+ struct AVFPixelFormatSpec pxl_fmt_dummy;
+ pxl_fmt_dummy.ff_id = AV_PIX_FMT_NONE;
+ for (int i = 0; avf_pixel_formats[i].ff_id != AV_PIX_FMT_NONE;
i++) {
+ if ([pxl_fmt intValue] == avf_pixel_formats[i].avf_id) {
+ pxl_fmt_dummy = avf_pixel_formats[i];
+ break;
+ }
+ }
+
+ if (pxl_fmt_dummy.ff_id != AV_PIX_FMT_NONE) {
+ av_log(s, AV_LOG_ERROR, " %s: %d \n",
av_get_pix_fmt_name(pxl_fmt_dummy.ff_id),
+ pxl_fmt_dummy.avf_id);
+
+ // select first supported pixel format instead of user
selected (or default) pixel format
+ if (pxl_fmt_spec.ff_id == AV_PIX_FMT_NONE) {
+ pxl_fmt_spec = pxl_fmt_dummy;
+ }
+ }
+ }
+
+ // fail if there is no appropriate pixel format or print a warning
about overriding the pixel format
+ if (pxl_fmt_spec.ff_id == AV_PIX_FMT_NONE) {
+ return 1;
+ } else {
+ av_log(s, AV_LOG_WARNING, "Overriding selected pixel format to use
%s instead.\n",
+ av_get_pix_fmt_name(pxl_fmt_spec.ff_id));
+ }
+ ctx->pixel_format = pxl_fmt_spec.ff_id;
+ NSNumber *pixel_format = [NSNumber
numberWithUnsignedInt:pxl_fmt_spec.avf_id];
+ NSDictionary *capture_dict = [NSDictionary
dictionaryWithObject:pixel_format
+
forKey:(id)kCVPixelBufferPixelFormatTypeKey];
+ [out setVideoSettings:capture_dict];
AVFFrameReceiver* delegate = [[AVFFrameReceiver alloc]
initWithContext:ctx];
@@ -244,8 +317,7 @@ static int get_video_config(AVFormatContext *s)
stream->codec->codec_type = AVMEDIA_TYPE_VIDEO;
stream->codec->width = (int)image_buffer_size.width;
stream->codec->height = (int)image_buffer_size.height;
- // No support for pixel formats for now using default one
- stream->codec->pix_fmt = AV_PIX_FMT_BGR32;
+ stream->codec->pix_fmt = ctx->pixel_format;
CFRelease(ctx->current_frame);
ctx->current_frame = nil;
--
2.6.2
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel