2 * This file is part of Libav.
4 * Libav is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * Libav is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with Libav; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 #include "libavcodec/avcodec.h"
20 #include "libavcodec/vda.h"
21 #include "libavutil/imgutils.h"
25 typedef struct VDAContext
{
29 static int vda_retrieve_data(AVCodecContext
*s
, AVFrame
*frame
)
31 InputStream
*ist
= s
->opaque
;
32 VDAContext
*vda
= ist
->hwaccel_ctx
;
33 CVPixelBufferRef pixbuf
= (CVPixelBufferRef
)frame
->data
[3];
34 OSType pixel_format
= CVPixelBufferGetPixelFormatType(pixbuf
);
36 uint8_t *data
[4] = { 0 };
37 int linesize
[4] = { 0 };
40 av_frame_unref(vda
->tmp_frame
);
42 switch (pixel_format
) {
43 case kCVPixelFormatType_420YpCbCr8Planar
: vda
->tmp_frame
->format
= AV_PIX_FMT_YUV420P
; break;
44 case kCVPixelFormatType_422YpCbCr8
: vda
->tmp_frame
->format
= AV_PIX_FMT_UYVY422
; break;
46 av_log(NULL
, AV_LOG_ERROR
,
47 "Unsupported pixel format: %u\n", pixel_format
);
48 return AVERROR(ENOSYS
);
51 vda
->tmp_frame
->width
= frame
->width
;
52 vda
->tmp_frame
->height
= frame
->height
;
53 ret
= av_frame_get_buffer(vda
->tmp_frame
, 32);
57 err
= CVPixelBufferLockBaseAddress(pixbuf
, kCVPixelBufferLock_ReadOnly
);
58 if (err
!= kCVReturnSuccess
) {
59 av_log(NULL
, AV_LOG_ERROR
, "Error locking the pixel buffer.\n");
60 return AVERROR_UNKNOWN
;
63 if (CVPixelBufferIsPlanar(pixbuf
)) {
65 planes
= CVPixelBufferGetPlaneCount(pixbuf
);
66 for (i
= 0; i
< planes
; i
++) {
67 data
[i
] = CVPixelBufferGetBaseAddressOfPlane(pixbuf
, i
);
68 linesize
[i
] = CVPixelBufferGetBytesPerRowOfPlane(pixbuf
, i
);
71 data
[0] = CVPixelBufferGetBaseAddress(pixbuf
);
72 linesize
[0] = CVPixelBufferGetBytesPerRow(pixbuf
);
75 av_image_copy(vda
->tmp_frame
->data
, vda
->tmp_frame
->linesize
,
76 data
, linesize
, vda
->tmp_frame
->format
,
77 frame
->width
, frame
->height
);
79 CVPixelBufferUnlockBaseAddress(pixbuf
, kCVPixelBufferLock_ReadOnly
);
81 ret
= av_frame_copy_props(vda
->tmp_frame
, frame
);
85 av_frame_unref(frame
);
86 av_frame_move_ref(frame
, vda
->tmp_frame
);
91 static void vda_uninit(AVCodecContext
*s
)
93 InputStream
*ist
= s
->opaque
;
94 VDAContext
*vda
= ist
->hwaccel_ctx
;
96 ist
->hwaccel_uninit
= NULL
;
97 ist
->hwaccel_retrieve_data
= NULL
;
99 av_frame_free(&vda
->tmp_frame
);
101 av_vda_default_free(s
);
102 av_freep(&ist
->hwaccel_ctx
);
105 int vda_init(AVCodecContext
*s
)
107 InputStream
*ist
= s
->opaque
;
108 int loglevel
= (ist
->hwaccel_id
== HWACCEL_AUTO
) ? AV_LOG_VERBOSE
: AV_LOG_ERROR
;
112 vda
= av_mallocz(sizeof(*vda
));
114 return AVERROR(ENOMEM
);
116 ist
->hwaccel_ctx
= vda
;
117 ist
->hwaccel_uninit
= vda_uninit
;
118 ist
->hwaccel_retrieve_data
= vda_retrieve_data
;
120 vda
->tmp_frame
= av_frame_alloc();
121 if (!vda
->tmp_frame
) {
122 ret
= AVERROR(ENOMEM
);
126 ret
= av_vda_default_init(s
);
128 av_log(NULL
, loglevel
, "Error creating VDA decoder.\n");