blob: ecfcbef31cb401e84fbea27df944620a9e5b7fda [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
Johny Lin48690172017-08-04 11:11:50 +080016#include <utils/Log.h>
17
18namespace android {
19
Johny Linac6e2702018-01-17 12:11:52 +080020constexpr SupportedPixelFormat kSupportedPixelFormats[] = {
21 // {mCrcb, mSemiplanar, mPixelFormat}
22 {false, true, HalPixelFormat::NV12},
23 {true, false, HalPixelFormat::YV12},
24 // Add more buffer formats when needed
25};
26
Johny Lina891f0e2017-12-19 10:25:27 +080027C2VDAAdaptor::C2VDAAdaptor() : mNumOutputBuffers(0u) {}
Johny Lin48690172017-08-04 11:11:50 +080028
29C2VDAAdaptor::~C2VDAAdaptor() {
30 if (mVDA) {
31 destroy();
32 }
33}
34
35VideoDecodeAcceleratorAdaptor::Result C2VDAAdaptor::initialize(
Johny Lina891f0e2017-12-19 10:25:27 +080036 media::VideoCodecProfile profile, bool secureMode,
37 VideoDecodeAcceleratorAdaptor::Client* client) {
Hirokazu Hondace275062017-10-30 11:34:57 +090038 // TODO: use secureMode here, or ignore?
Johny Lin48690172017-08-04 11:11:50 +080039 if (mVDA) {
40 ALOGE("Re-initialize() is not allowed");
41 return ILLEGAL_STATE;
42 }
43
44 media::VideoDecodeAccelerator::Config config;
45 config.profile = profile;
46 config.output_mode = media::VideoDecodeAccelerator::Config::OutputMode::IMPORT;
47
48 // TODO(johnylin): may need to implement factory to create VDA if there are multiple VDA
49 // implementations in the future.
50 scoped_refptr<media::V4L2Device> device = new media::V4L2Device();
51 std::unique_ptr<media::VideoDecodeAccelerator> vda(
52 new media::V4L2SliceVideoDecodeAccelerator(device));
53 if (!vda->Initialize(config, this)) {
54 ALOGE("Failed to initialize VDA");
55 return PLATFORM_FAILURE;
56 }
57
58 mVDA = std::move(vda);
59 mClient = client;
60
61 return SUCCESS;
62}
63
64void C2VDAAdaptor::decode(int32_t bitstreamId, int ashmemFd, off_t offset, uint32_t bytesUsed) {
65 CHECK(mVDA);
Johny Lina891f0e2017-12-19 10:25:27 +080066 mVDA->Decode(media::BitstreamBuffer(bitstreamId, base::SharedMemoryHandle(ashmemFd, true),
67 bytesUsed, offset));
Johny Lin48690172017-08-04 11:11:50 +080068}
69
70void C2VDAAdaptor::assignPictureBuffers(uint32_t numOutputBuffers) {
71 CHECK(mVDA);
72 std::vector<media::PictureBuffer> buffers;
73 for (uint32_t id = 0; id < numOutputBuffers; ++id) {
Johny Lina891f0e2017-12-19 10:25:27 +080074 buffers.push_back(media::PictureBuffer(static_cast<int32_t>(id), mPictureSize));
Johny Lin48690172017-08-04 11:11:50 +080075 }
76 mVDA->AssignPictureBuffers(buffers);
77 mNumOutputBuffers = numOutputBuffers;
78}
79
Johny Linac6e2702018-01-17 12:11:52 +080080void C2VDAAdaptor::importBufferForPicture(int32_t pictureBufferId, HalPixelFormat format,
81 int dmabufFd,
Johny Lin48690172017-08-04 11:11:50 +080082 const std::vector<VideoFramePlane>& planes) {
Johny Linac6e2702018-01-17 12:11:52 +080083 // per change ag/3262504, format should be passed to VDA, however it also matters to VDA API
84 // change.
85 // TODO(johnylin): pass format to VDA after updating VDA codes to latest.
86 (void)format;
87
Johny Lin48690172017-08-04 11:11:50 +080088 CHECK(mVDA);
89 CHECK_LT(pictureBufferId, static_cast<int32_t>(mNumOutputBuffers));
90
91 media::NativePixmapHandle handle;
92 handle.fds.emplace_back(base::FileDescriptor(dmabufFd, true));
93 for (const auto& plane : planes) {
Johny Linac6e2702018-01-17 12:11:52 +080094 handle.planes.emplace_back(plane.mStride, plane.mOffset, 0, 0);
Johny Lin48690172017-08-04 11:11:50 +080095 }
96 mVDA->ImportBufferForPicture(pictureBufferId, handle);
97}
98
99void C2VDAAdaptor::reusePictureBuffer(int32_t pictureBufferId) {
100 CHECK(mVDA);
101 CHECK_LT(pictureBufferId, static_cast<int32_t>(mNumOutputBuffers));
102
103 mVDA->ReusePictureBuffer(pictureBufferId);
104}
105
106void C2VDAAdaptor::flush() {
107 CHECK(mVDA);
108 mVDA->Flush();
109}
110
111void C2VDAAdaptor::reset() {
112 CHECK(mVDA);
113 mVDA->Reset();
114}
115
116void C2VDAAdaptor::destroy() {
117 mVDA.reset(nullptr);
118 mNumOutputBuffers = 0u;
119 mPictureSize = media::Size();
120}
121
Johny Lin7c4cb522017-06-26 16:10:24 +0800122//static
123media::VideoDecodeAccelerator::SupportedProfiles C2VDAAdaptor::GetSupportedProfiles(
124 uint32_t inputFormatFourcc) {
125 media::VideoDecodeAccelerator::SupportedProfiles supportedProfiles;
126 auto allProfiles = media::V4L2SliceVideoDecodeAccelerator::GetSupportedProfiles();
127 bool isSliceBased = (inputFormatFourcc == V4L2_PIX_FMT_H264_SLICE) ||
128 (inputFormatFourcc == V4L2_PIX_FMT_VP8_FRAME) ||
129 (inputFormatFourcc == V4L2_PIX_FMT_VP9_FRAME);
130 for (const auto& profile : allProfiles) {
Johny Lina891f0e2017-12-19 10:25:27 +0800131 if (inputFormatFourcc ==
132 media::V4L2Device::VideoCodecProfileToV4L2PixFmt(profile.profile, isSliceBased)) {
Johny Lin7c4cb522017-06-26 16:10:24 +0800133 supportedProfiles.push_back(profile);
134 }
135 }
136 return supportedProfiles;
137}
Johny Lin48690172017-08-04 11:11:50 +0800138
Johny Linac6e2702018-01-17 12:11:52 +0800139//static
140HalPixelFormat C2VDAAdaptor::ResolveBufferFormat(bool crcb, bool semiplanar) {
141 auto value = std::find_if(std::begin(kSupportedPixelFormats), std::end(kSupportedPixelFormats),
142 [crcb, semiplanar](const struct SupportedPixelFormat& f) {
143 return f.mCrcb == crcb && f.mSemiplanar == semiplanar;
144 });
145 LOG_ALWAYS_FATAL_IF(value == std::end(kSupportedPixelFormats),
146 "Unsupported pixel format: (crcb=%d, semiplanar=%d)", crcb, semiplanar);
147 return value->mPixelFormat;
148}
149
Johny Lin48690172017-08-04 11:11:50 +0800150void C2VDAAdaptor::ProvidePictureBuffers(uint32_t requested_num_of_buffers,
151 media::VideoPixelFormat output_format,
152 const media::Size& dimensions) {
Johny Linac6e2702018-01-17 12:11:52 +0800153 // per change ag/3262504, output_format from VDA is no longer used, component side always
154 // allocate graphic buffers for flexible YUV format.
155 (void)output_format;
Johny Lin48690172017-08-04 11:11:50 +0800156
Johny Linac6e2702018-01-17 12:11:52 +0800157 mClient->providePictureBuffers(requested_num_of_buffers, dimensions);
Johny Lin48690172017-08-04 11:11:50 +0800158 mPictureSize = dimensions;
159}
160
161void C2VDAAdaptor::DismissPictureBuffer(int32_t picture_buffer_id) {
162 mClient->dismissPictureBuffer(picture_buffer_id);
163}
164
165void C2VDAAdaptor::PictureReady(const media::Picture& picture) {
Johny Lina891f0e2017-12-19 10:25:27 +0800166 mClient->pictureReady(picture.picture_buffer_id(), picture.bitstream_buffer_id(),
Johny Lin48690172017-08-04 11:11:50 +0800167 picture.visible_rect());
168}
169
170void C2VDAAdaptor::NotifyEndOfBitstreamBuffer(int32_t bitstream_buffer_id) {
171 mClient->notifyEndOfBitstreamBuffer(bitstream_buffer_id);
172}
173
174void C2VDAAdaptor::NotifyFlushDone() {
175 mClient->notifyFlushDone();
176}
177
178void C2VDAAdaptor::NotifyResetDone() {
179 mClient->notifyResetDone();
180}
181
182static VideoDecodeAcceleratorAdaptor::Result convertErrorCode(
183 media::VideoDecodeAccelerator::Error error) {
184 switch (error) {
Johny Lina891f0e2017-12-19 10:25:27 +0800185 case media::VideoDecodeAccelerator::ILLEGAL_STATE:
186 return VideoDecodeAcceleratorAdaptor::ILLEGAL_STATE;
187 case media::VideoDecodeAccelerator::INVALID_ARGUMENT:
188 return VideoDecodeAcceleratorAdaptor::INVALID_ARGUMENT;
189 case media::VideoDecodeAccelerator::UNREADABLE_INPUT:
190 return VideoDecodeAcceleratorAdaptor::UNREADABLE_INPUT;
191 case media::VideoDecodeAccelerator::PLATFORM_FAILURE:
192 return VideoDecodeAcceleratorAdaptor::PLATFORM_FAILURE;
193 default:
194 ALOGE("Unknown error code: %d", static_cast<int>(error));
195 return VideoDecodeAcceleratorAdaptor::PLATFORM_FAILURE;
Johny Lin48690172017-08-04 11:11:50 +0800196 }
197}
198
199void C2VDAAdaptor::NotifyError(media::VideoDecodeAccelerator::Error error) {
200 mClient->notifyError(convertErrorCode(error));
201}
202
203} // namespace android