[FFmpeg-devel] [PATCH] vdadec: support more pixfmts

Xidorn Quan quanxunzhen at gmail.com
Wed Aug 22 17:05:35 CEST 2012


---
 configure                 |  2 ++
 libavcodec/vda_h264_dec.c | 76 ++++++++++++++++++++++++++++++++++++-----
 libavutil/Makefile        |  4 +++
 libavutil/osx.c           | 87 +++++++++++++++++++++++++++++++++++++++++++++++
 libavutil/osx.h           | 34 ++++++++++++++++++
 5 files changed, 194 insertions(+), 9 deletions(-)
 create mode 100644 libavutil/osx.c
 create mode 100644 libavutil/osx.h

diff --git a/configure b/configure
index ca2feab..731f30b 100755
--- a/configure
+++ b/configure
@@ -1236,6 +1236,7 @@ HAVE_LIST="
     cmov
     cpuid
     cpunop
+    CoreFoundation_CoreFoundation_h
     dcbzl
     dev_bktr_ioctl_bt848_h
     dev_bktr_ioctl_meteor_h
@@ -3384,6 +3385,7 @@ check_header vdpau/vdpau_x11.h
 check_header windows.h
 check_header X11/extensions/XvMClib.h
 check_header asm/types.h
+check_header CoreFoundation/CoreFoundation.h
 
 disabled  zlib || check_lib   zlib.h      zlibVersion -lz   || disable  zlib
 disabled bzlib || check_lib2 bzlib.h BZ2_bzlibVersion -lbz2 || disable bzlib
diff --git a/libavcodec/vda_h264_dec.c b/libavcodec/vda_h264_dec.c
index 1a097de..dd247e9 100644
--- a/libavcodec/vda_h264_dec.c
+++ b/libavcodec/vda_h264_dec.c
@@ -31,6 +31,22 @@
 #include "h264.h"
 #include "golomb.h"
 #include "avcodec.h"
+#include "libavutil/osx.h"
+#include "libavutil/avassert.h"
+
+static const enum PixelFormat vda_pixfmts_prior_10_7[] = {
+    PIX_FMT_UYVY422,
+    PIX_FMT_YUV420P,
+    PIX_FMT_NONE
+};
+
+static const enum PixelFormat vda_pixfmts[] = {
+    PIX_FMT_UYVY422,
+    PIX_FMT_YUYV422,
+    PIX_FMT_NV12,
+    PIX_FMT_YUV420P,
+    PIX_FMT_NONE
+};
 
 typedef struct display_frame {
     AVFrame f;
@@ -52,14 +68,24 @@ typedef struct {
 static inline DisplayFrame *alloc_frame(CVPixelBufferRef buffer)
 {
     DisplayFrame *new_frame = av_calloc(1, sizeof(DisplayFrame));
+    AVFrame *f = &new_frame->f;
+    size_t i, count;
+
     if (!new_frame)
         return NULL;
 
     new_frame->cv_buffer = buffer;
     CVPixelBufferLockBaseAddress(buffer, 0);
-    new_frame->f.data[0] = CVPixelBufferGetBaseAddress(buffer);
-    new_frame->f.data[3] = (void *)buffer;
-    new_frame->f.linesize[0] = CVPixelBufferGetBytesPerRow(buffer);
+    if (CVPixelBufferIsPlanar(buffer)) {
+        count = CVPixelBufferGetPlaneCount(buffer);
+        for (i = 0; i < count; i++) {
+            f->data[i] = CVPixelBufferGetBaseAddressOfPlane(buffer, i);
+            f->linesize[i] = CVPixelBufferGetBytesPerRowOfPlane(buffer, i);
+        }
+    } else {
+        f->data[0] = CVPixelBufferGetBaseAddress(buffer);
+        f->linesize[0] = CVPixelBufferGetBytesPerRow(buffer);
+    }
 
     return new_frame;
 }
@@ -365,14 +391,32 @@ static av_cold int vdadec_close(AVCodecContext *avctx)
 
 static av_cold int vdadec_init(AVCodecContext *avctx)
 {
-    VDADecoderContext *ctx;
+    VDADecoderContext *ctx = avctx->priv_data;
     struct vda_context *vda_ctx;
     H264Context *h;
     OSStatus status;
 
-    ctx = avctx->priv_data;
+    /* clean up */
     memset(ctx, 0, sizeof(VDADecoderContext));
 
+    /* init pix_fmts of codec */
+    if (!avctx->codec->pix_fmts) {
+        int major, minor, bugfix;
+        if (!av_get_osx_version(&major, &minor, &bugfix)) {
+            av_assert0(major == 10);
+            av_log(avctx, AV_LOG_VERBOSE, "Detected system version: %d.%d.%d\n",
+                    major, minor, bugfix);
+            if (minor < 7)
+                avctx->codec->pix_fmts = vda_pixfmts_prior_10_7;
+            else
+                avctx->codec->pix_fmts = vda_pixfmts;
+        } else {
+            av_log(avctx, AV_LOG_WARNING,
+                    "Failed to determine system version.\n");
+            avctx->codec->pix_fmts = vda_pixfmts;
+        }
+    }
+
     /* init display queue */
     ctx->queue.mmco_reset = 1;
     ctx->queue.f.key_frame = 1;
@@ -402,9 +446,25 @@ static av_cold int vdadec_init(AVCodecContext *avctx)
     vda_ctx->width = avctx->width;
     vda_ctx->height = avctx->height;
     vda_ctx->format = 'avc1';
-    vda_ctx->cv_pix_fmt_type = kCVPixelFormatType_422YpCbCr8_yuvs;
     vda_ctx->use_sync_decoding = 1;
-    avctx->pix_fmt = PIX_FMT_YUYV422;
+    avctx->pix_fmt = avctx->get_format(avctx, avctx->codec->pix_fmts);
+    switch (avctx->pix_fmt) {
+    case PIX_FMT_UYVY422:
+        vda_ctx->cv_pix_fmt_type = '2vuy';
+        break;
+    case PIX_FMT_YUYV422:
+        vda_ctx->cv_pix_fmt_type = 'yuvs';
+        break;
+    case PIX_FMT_NV12:
+        vda_ctx->cv_pix_fmt_type = '420v';
+        break;
+    case PIX_FMT_YUV420P:
+        vda_ctx->cv_pix_fmt_type = 'y420';
+        break;
+    default:
+        av_log(avctx, AV_LOG_ERROR, "Unsupported pixel format: %d\n", avctx->pix_fmt);
+        goto failed;
+    }
     status = ff_vda_create_decoder(vda_ctx,
                                    avctx->extradata, avctx->extradata_size);
     if (status != kVDADecoderNoErr) {
@@ -445,6 +505,4 @@ AVCodec ff_h264_vda_decoder = {
     .capabilities   = CODEC_CAP_DELAY,
     .flush          = vdadec_flush,
     .long_name      = NULL_IF_CONFIG_SMALL("H.264 (VDA acceleration)"),
-    .pix_fmts       = (const enum PixelFormat[]){ PIX_FMT_YUYV422,
-                                                  PIX_FMT_NONE },
 };
diff --git a/libavutil/Makefile b/libavutil/Makefile
index ef1f658..88f1fb1 100644
--- a/libavutil/Makefile
+++ b/libavutil/Makefile
@@ -119,6 +119,10 @@ TESTPROGS = adler32                                                     \
             tree                                                        \
             xtea                                                        \
 
+HEADERS-$(HAVE_COREFOUNDATION_COREFOUNDATION_H) += osx.h
+
+OBJS-$(HAVE_COREFOUNDATION_COREFOUNDATION_H) += osx.o
+
 TESTPROGS-$(HAVE_LZO1X_999_COMPRESS) += lzo
 
 TOOLS = ffeval
diff --git a/libavutil/osx.c b/libavutil/osx.c
new file mode 100644
index 0000000..ea85c3c
--- /dev/null
+++ b/libavutil/osx.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2012, Xidorn Quan
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdio.h>
+#include <CoreFoundation/CoreFoundation.h>
+
+#include "osx.h"
+#include "mem.h"
+
+int av_get_osx_version(int *major, int *minor, int *bugfix)
+{
+    static int s_major = 0, s_minor = 0, s_bugfix = 0;
+    CFURLRef versionPath;
+    CFDataRef data;
+    SInt32 errorCode;
+    CFDictionaryRef dict;
+    CFStringRef versionStr;
+    CFIndex length;
+    char *version;
+
+    if (s_major) {
+        *major = s_major;
+        *minor = s_minor;
+        *bugfix = s_bugfix;
+        return 0;
+    }
+
+    versionPath = CFURLCreateWithFileSystemPath(NULL,
+            CFSTR("/System/Library/CoreServices/SystemVersion.plist"),
+            kCFURLPOSIXPathStyle, false);
+    if (!CFURLCreateDataAndPropertiesFromResource(
+                NULL, versionPath, &data, NULL, NULL, &errorCode))
+        goto release_path;
+
+    dict = CFPropertyListCreateWithData(
+            NULL, data, kCFPropertyListImmutable, NULL, NULL);
+    if (!dict)
+        goto release_data;
+
+    versionStr = CFDictionaryGetValue(dict, CFSTR("ProductVersion"));
+    if (!versionStr)
+        goto release_dict;
+
+    length = CFStringGetLength(versionStr) + 1;
+    version = av_malloc(length);
+    if (!version)
+        goto release_dict;
+
+    if (!CFStringGetCString(versionStr,
+            version, length, kCFStringEncodingUTF8))
+        goto release_version;
+
+    sscanf(version, "%d.%d.%d", &s_major, &s_minor, &s_bugfix);
+    *major = s_major;
+    *minor = s_minor;
+    *bugfix = s_bugfix;
+    
+release_version:
+    av_free(version);
+
+release_dict:
+    CFRelease(dict);
+
+release_data:
+    CFRelease(data);
+
+release_path:
+    CFRelease(versionPath);
+    return s_major ? 0 : -1;
+}
diff --git a/libavutil/osx.h b/libavutil/osx.h
new file mode 100644
index 0000000..afd6c4e
--- /dev/null
+++ b/libavutil/osx.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2012, Xidorn Quan
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVUTIL_OSX_H
+#define AVUTIL_OSX_H
+
+/**
+ * Get version of Mac OS X
+ *
+ * @param major  pointer to store major version
+ * @param minor  pointer to store minor version
+ * @param bugfix pointer to store bugfix version
+ * @return       zero if succeed, -1 otherwise
+ */
+int av_get_osx_version(int *major, int *minor, int *bugfix);
+
+#endif /* AVUTIL_OSX_H */
-- 
1.7.11.4



More information about the ffmpeg-devel mailing list