blob: 446a6b4ec1aa7a3a3de3eb07f68c1d9567a68de5 [file] [log] [blame]
Johny Lin48690172017-08-04 11:11:50 +08001// Copyright 2017 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5//#define LOG_NDEBUG 0
6#define LOG_TAG "C2VDAAdaptor"
7
Johny Linc6d0b6f2017-12-19 15:47:06 +08008#include <C2VDAAdaptor.h>
9
10#include <bitstream_buffer.h>
11#include <native_pixmap_handle.h>
12#include <v4l2_device.h>
13#include <v4l2_slice_video_decode_accelerator.h>
14#include <videodev2.h>
Johny Lin48690172017-08-04 11:11:50 +080015
16#include <system/graphics.h>
17#include <utils/Log.h>
18
19namespace android {
20
Johny Lina891f0e2017-12-19 10:25:27 +080021C2VDAAdaptor::C2VDAAdaptor() : mNumOutputBuffers(0u) {}
Johny Lin48690172017-08-04 11:11:50 +080022
23C2VDAAdaptor::~C2VDAAdaptor() {
24 if (mVDA) {
25 destroy();
26 }
27}
28
29VideoDecodeAcceleratorAdaptor::Result C2VDAAdaptor::initialize(
Johny Lina891f0e2017-12-19 10:25:27 +080030 media::VideoCodecProfile profile, bool secureMode,
31 VideoDecodeAcceleratorAdaptor::Client* client) {
Hirokazu Hondace275062017-10-30 11:34:57 +090032 // TODO: use secureMode here, or ignore?
Johny Lin48690172017-08-04 11:11:50 +080033 if (mVDA) {
34 ALOGE("Re-initialize() is not allowed");
35 return ILLEGAL_STATE;
36 }
37
38 media::VideoDecodeAccelerator::Config config;
39 config.profile = profile;
40 config.output_mode = media::VideoDecodeAccelerator::Config::OutputMode::IMPORT;
41
42 // TODO(johnylin): may need to implement factory to create VDA if there are multiple VDA
43 // implementations in the future.
44 scoped_refptr<media::V4L2Device> device = new media::V4L2Device();
45 std::unique_ptr<media::VideoDecodeAccelerator> vda(
46 new media::V4L2SliceVideoDecodeAccelerator(device));
47 if (!vda->Initialize(config, this)) {
48 ALOGE("Failed to initialize VDA");
49 return PLATFORM_FAILURE;
50 }
51
52 mVDA = std::move(vda);
53 mClient = client;
54
55 return SUCCESS;
56}
57
58void C2VDAAdaptor::decode(int32_t bitstreamId, int ashmemFd, off_t offset, uint32_t bytesUsed) {
59 CHECK(mVDA);
Johny Lina891f0e2017-12-19 10:25:27 +080060 mVDA->Decode(media::BitstreamBuffer(bitstreamId, base::SharedMemoryHandle(ashmemFd, true),
61 bytesUsed, offset));
Johny Lin48690172017-08-04 11:11:50 +080062}
63
64void C2VDAAdaptor::assignPictureBuffers(uint32_t numOutputBuffers) {
65 CHECK(mVDA);
66 std::vector<media::PictureBuffer> buffers;
67 for (uint32_t id = 0; id < numOutputBuffers; ++id) {
Johny Lina891f0e2017-12-19 10:25:27 +080068 buffers.push_back(media::PictureBuffer(static_cast<int32_t>(id), mPictureSize));
Johny Lin48690172017-08-04 11:11:50 +080069 }
70 mVDA->AssignPictureBuffers(buffers);
71 mNumOutputBuffers = numOutputBuffers;
72}
73
74void C2VDAAdaptor::importBufferForPicture(int32_t pictureBufferId, int dmabufFd,
75 const std::vector<VideoFramePlane>& planes) {
76 CHECK(mVDA);
77 CHECK_LT(pictureBufferId, static_cast<int32_t>(mNumOutputBuffers));
78
79 media::NativePixmapHandle handle;
80 handle.fds.emplace_back(base::FileDescriptor(dmabufFd, true));
81 for (const auto& plane : planes) {
82 handle.planes.emplace_back(plane.stride, plane.offset, 0, 0);
83 }
84 mVDA->ImportBufferForPicture(pictureBufferId, handle);
85}
86
87void C2VDAAdaptor::reusePictureBuffer(int32_t pictureBufferId) {
88 CHECK(mVDA);
89 CHECK_LT(pictureBufferId, static_cast<int32_t>(mNumOutputBuffers));
90
91 mVDA->ReusePictureBuffer(pictureBufferId);
92}
93
94void C2VDAAdaptor::flush() {
95 CHECK(mVDA);
96 mVDA->Flush();
97}
98
99void C2VDAAdaptor::reset() {
100 CHECK(mVDA);
101 mVDA->Reset();
102}
103
104void C2VDAAdaptor::destroy() {
105 mVDA.reset(nullptr);
106 mNumOutputBuffers = 0u;
107 mPictureSize = media::Size();
108}
109
Johny Lin7c4cb522017-06-26 16:10:24 +0800110//static
111media::VideoDecodeAccelerator::SupportedProfiles C2VDAAdaptor::GetSupportedProfiles(
112 uint32_t inputFormatFourcc) {
113 media::VideoDecodeAccelerator::SupportedProfiles supportedProfiles;
114 auto allProfiles = media::V4L2SliceVideoDecodeAccelerator::GetSupportedProfiles();
115 bool isSliceBased = (inputFormatFourcc == V4L2_PIX_FMT_H264_SLICE) ||
116 (inputFormatFourcc == V4L2_PIX_FMT_VP8_FRAME) ||
117 (inputFormatFourcc == V4L2_PIX_FMT_VP9_FRAME);
118 for (const auto& profile : allProfiles) {
Johny Lina891f0e2017-12-19 10:25:27 +0800119 if (inputFormatFourcc ==
120 media::V4L2Device::VideoCodecProfileToV4L2PixFmt(profile.profile, isSliceBased)) {
Johny Lin7c4cb522017-06-26 16:10:24 +0800121 supportedProfiles.push_back(profile);
122 }
123 }
124 return supportedProfiles;
125}
Johny Lin48690172017-08-04 11:11:50 +0800126
127void C2VDAAdaptor::ProvidePictureBuffers(uint32_t requested_num_of_buffers,
128 media::VideoPixelFormat output_format,
129 const media::Size& dimensions) {
130 uint32_t pixelFormat;
131 switch (output_format) {
Johny Lina891f0e2017-12-19 10:25:27 +0800132 case media::PIXEL_FORMAT_I420:
133 case media::PIXEL_FORMAT_YV12:
134 case media::PIXEL_FORMAT_NV12:
135 case media::PIXEL_FORMAT_NV21:
136 // HAL_PIXEL_FORMAT_YCbCr_420_888 is the flexible pixel format in Android
137 // which handles all 420 formats, with both orderings of chroma (CbCr and
138 // CrCb) as well as planar and semi-planar layouts.
139 pixelFormat = HAL_PIXEL_FORMAT_YCbCr_420_888;
140 break;
141 case media::PIXEL_FORMAT_ARGB:
142 pixelFormat = HAL_PIXEL_FORMAT_BGRA_8888;
143 break;
144 default:
145 ALOGE("Format not supported: %d", output_format);
146 mClient->notifyError(PLATFORM_FAILURE);
147 return;
Johny Lin48690172017-08-04 11:11:50 +0800148 }
149
150 mClient->providePictureBuffers(pixelFormat, requested_num_of_buffers, dimensions);
151 mPictureSize = dimensions;
152}
153
154void C2VDAAdaptor::DismissPictureBuffer(int32_t picture_buffer_id) {
155 mClient->dismissPictureBuffer(picture_buffer_id);
156}
157
158void C2VDAAdaptor::PictureReady(const media::Picture& picture) {
Johny Lina891f0e2017-12-19 10:25:27 +0800159 mClient->pictureReady(picture.picture_buffer_id(), picture.bitstream_buffer_id(),
Johny Lin48690172017-08-04 11:11:50 +0800160 picture.visible_rect());
161}
162
163void C2VDAAdaptor::NotifyEndOfBitstreamBuffer(int32_t bitstream_buffer_id) {
164 mClient->notifyEndOfBitstreamBuffer(bitstream_buffer_id);
165}
166
167void C2VDAAdaptor::NotifyFlushDone() {
168 mClient->notifyFlushDone();
169}
170
171void C2VDAAdaptor::NotifyResetDone() {
172 mClient->notifyResetDone();
173}
174
175static VideoDecodeAcceleratorAdaptor::Result convertErrorCode(
176 media::VideoDecodeAccelerator::Error error) {
177 switch (error) {
Johny Lina891f0e2017-12-19 10:25:27 +0800178 case media::VideoDecodeAccelerator::ILLEGAL_STATE:
179 return VideoDecodeAcceleratorAdaptor::ILLEGAL_STATE;
180 case media::VideoDecodeAccelerator::INVALID_ARGUMENT:
181 return VideoDecodeAcceleratorAdaptor::INVALID_ARGUMENT;
182 case media::VideoDecodeAccelerator::UNREADABLE_INPUT:
183 return VideoDecodeAcceleratorAdaptor::UNREADABLE_INPUT;
184 case media::VideoDecodeAccelerator::PLATFORM_FAILURE:
185 return VideoDecodeAcceleratorAdaptor::PLATFORM_FAILURE;
186 default:
187 ALOGE("Unknown error code: %d", static_cast<int>(error));
188 return VideoDecodeAcceleratorAdaptor::PLATFORM_FAILURE;
Johny Lin48690172017-08-04 11:11:50 +0800189 }
190}
191
192void C2VDAAdaptor::NotifyError(media::VideoDecodeAccelerator::Error error) {
193 mClient->notifyError(convertErrorCode(error));
194}
195
196} // namespace android