1 // 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
8 #include <C2VDAAdaptor.h>
9
10 #include <bitstream_buffer.h>
11 #include <native_pixmap_handle.h>
12 #include <v4l2_device.h>
13 #include <v4l2_video_decode_accelerator.h>
14 #include <video_pixel_format.h>
15
16 #include <utils/Log.h>
17
18 namespace android {
19
C2VDAAdaptor()20 C2VDAAdaptor::C2VDAAdaptor() : mNumOutputBuffers(0u) {}
21
~C2VDAAdaptor()22 C2VDAAdaptor::~C2VDAAdaptor() {
23 if (mVDA) {
24 destroy();
25 }
26 }
27
initialize(media::VideoCodecProfile profile,bool secureMode,VideoDecodeAcceleratorAdaptor::Client * client)28 VideoDecodeAcceleratorAdaptor::Result C2VDAAdaptor::initialize(
29 media::VideoCodecProfile profile, bool secureMode,
30 VideoDecodeAcceleratorAdaptor::Client* client) {
31 // TODO: use secureMode here, or ignore?
32 if (mVDA) {
33 ALOGE("Re-initialize() is not allowed");
34 return ILLEGAL_STATE;
35 }
36
37 media::VideoDecodeAccelerator::Config config;
38 config.profile = profile;
39 config.output_mode = media::VideoDecodeAccelerator::Config::OutputMode::IMPORT;
40
41 // TODO(johnylin): may need to implement factory to create VDA if there are multiple VDA
42 // implementations in the future.
43 scoped_refptr<media::V4L2Device> device = new media::V4L2Device();
44 std::unique_ptr<media::VideoDecodeAccelerator> vda(
45 new media::V4L2VideoDecodeAccelerator(device));
46 if (!vda->Initialize(config, this)) {
47 ALOGE("Failed to initialize VDA");
48 return PLATFORM_FAILURE;
49 }
50
51 mVDA = std::move(vda);
52 mClient = client;
53
54 return SUCCESS;
55 }
56
decode(int32_t bitstreamId,int ashmemFd,off_t offset,uint32_t bytesUsed)57 void C2VDAAdaptor::decode(int32_t bitstreamId, int ashmemFd, off_t offset, uint32_t bytesUsed) {
58 CHECK(mVDA);
59 mVDA->Decode(media::BitstreamBuffer(bitstreamId, base::SharedMemoryHandle(ashmemFd, true),
60 bytesUsed, offset));
61 }
62
assignPictureBuffers(uint32_t numOutputBuffers)63 void C2VDAAdaptor::assignPictureBuffers(uint32_t numOutputBuffers) {
64 CHECK(mVDA);
65 std::vector<media::PictureBuffer> buffers;
66 for (uint32_t id = 0; id < numOutputBuffers; ++id) {
67 buffers.push_back(media::PictureBuffer(static_cast<int32_t>(id), mPictureSize));
68 }
69 mVDA->AssignPictureBuffers(buffers);
70 mNumOutputBuffers = numOutputBuffers;
71 }
72
importBufferForPicture(int32_t pictureBufferId,HalPixelFormat format,int dmabufFd,const std::vector<VideoFramePlane> & planes)73 void C2VDAAdaptor::importBufferForPicture(int32_t pictureBufferId, HalPixelFormat format,
74 int dmabufFd,
75 const std::vector<VideoFramePlane>& planes) {
76 CHECK(mVDA);
77 CHECK_LT(pictureBufferId, static_cast<int32_t>(mNumOutputBuffers));
78
79 media::VideoPixelFormat pixelFormat;
80 switch (format) {
81 case HalPixelFormat::YV12:
82 pixelFormat = media::PIXEL_FORMAT_YV12;
83 break;
84 case HalPixelFormat::NV12:
85 pixelFormat = media::PIXEL_FORMAT_NV12;
86 break;
87 default:
88 LOG_ALWAYS_FATAL("Unsupported format: 0x%x", format);
89 return;
90 }
91
92 media::NativePixmapHandle handle;
93 handle.fds.emplace_back(base::FileDescriptor(dmabufFd, true));
94 for (const auto& plane : planes) {
95 handle.planes.emplace_back(plane.mStride, plane.mOffset, 0, 0);
96 }
97 mVDA->ImportBufferForPicture(pictureBufferId, pixelFormat, handle);
98 }
99
reusePictureBuffer(int32_t pictureBufferId)100 void C2VDAAdaptor::reusePictureBuffer(int32_t pictureBufferId) {
101 CHECK(mVDA);
102 CHECK_LT(pictureBufferId, static_cast<int32_t>(mNumOutputBuffers));
103
104 mVDA->ReusePictureBuffer(pictureBufferId);
105 }
106
flush()107 void C2VDAAdaptor::flush() {
108 CHECK(mVDA);
109 mVDA->Flush();
110 }
111
reset()112 void C2VDAAdaptor::reset() {
113 CHECK(mVDA);
114 mVDA->Reset();
115 }
116
destroy()117 void C2VDAAdaptor::destroy() {
118 mVDA.reset(nullptr);
119 mNumOutputBuffers = 0u;
120 mPictureSize = media::Size();
121 }
122
123 //static
GetSupportedProfiles(InputCodec inputCodec)124 media::VideoDecodeAccelerator::SupportedProfiles C2VDAAdaptor::GetSupportedProfiles(
125 InputCodec inputCodec) {
126 // TODO(johnylin): use factory function to determine whether V4L2 stream or slice API is.
127 uint32_t inputFormatFourcc;
128 if (inputCodec == InputCodec::H264) {
129 inputFormatFourcc = V4L2_PIX_FMT_H264;
130 } else if (inputCodec == InputCodec::VP8) {
131 inputFormatFourcc = V4L2_PIX_FMT_VP8;
132 } else { // InputCodec::VP9
133 inputFormatFourcc = V4L2_PIX_FMT_VP9;
134 }
135
136 media::VideoDecodeAccelerator::SupportedProfiles supportedProfiles;
137 auto allProfiles = media::V4L2VideoDecodeAccelerator::GetSupportedProfiles();
138 for (const auto& profile : allProfiles) {
139 if (inputFormatFourcc ==
140 media::V4L2Device::VideoCodecProfileToV4L2PixFmt(profile.profile)) {
141 supportedProfiles.push_back(profile);
142 }
143 }
144 return supportedProfiles;
145 }
146
ProvidePictureBuffers(uint32_t requested_num_of_buffers,media::VideoPixelFormat output_format,const media::Size & dimensions)147 void C2VDAAdaptor::ProvidePictureBuffers(uint32_t requested_num_of_buffers,
148 media::VideoPixelFormat output_format,
149 const media::Size& dimensions) {
150 // per change ag/3262504, output_format from VDA is no longer used, component side always
151 // allocate graphic buffers for flexible YUV format.
152 (void)output_format;
153
154 mClient->providePictureBuffers(requested_num_of_buffers, dimensions);
155 mPictureSize = dimensions;
156 }
157
DismissPictureBuffer(int32_t picture_buffer_id)158 void C2VDAAdaptor::DismissPictureBuffer(int32_t picture_buffer_id) {
159 mClient->dismissPictureBuffer(picture_buffer_id);
160 }
161
PictureReady(const media::Picture & picture)162 void C2VDAAdaptor::PictureReady(const media::Picture& picture) {
163 mClient->pictureReady(picture.picture_buffer_id(), picture.bitstream_buffer_id(),
164 picture.visible_rect());
165 }
166
NotifyEndOfBitstreamBuffer(int32_t bitstream_buffer_id)167 void C2VDAAdaptor::NotifyEndOfBitstreamBuffer(int32_t bitstream_buffer_id) {
168 mClient->notifyEndOfBitstreamBuffer(bitstream_buffer_id);
169 }
170
NotifyFlushDone()171 void C2VDAAdaptor::NotifyFlushDone() {
172 mClient->notifyFlushDone();
173 }
174
NotifyResetDone()175 void C2VDAAdaptor::NotifyResetDone() {
176 mClient->notifyResetDone();
177 }
178
convertErrorCode(media::VideoDecodeAccelerator::Error error)179 static VideoDecodeAcceleratorAdaptor::Result convertErrorCode(
180 media::VideoDecodeAccelerator::Error error) {
181 switch (error) {
182 case media::VideoDecodeAccelerator::ILLEGAL_STATE:
183 return VideoDecodeAcceleratorAdaptor::ILLEGAL_STATE;
184 case media::VideoDecodeAccelerator::INVALID_ARGUMENT:
185 return VideoDecodeAcceleratorAdaptor::INVALID_ARGUMENT;
186 case media::VideoDecodeAccelerator::UNREADABLE_INPUT:
187 return VideoDecodeAcceleratorAdaptor::UNREADABLE_INPUT;
188 case media::VideoDecodeAccelerator::PLATFORM_FAILURE:
189 return VideoDecodeAcceleratorAdaptor::PLATFORM_FAILURE;
190 default:
191 ALOGE("Unknown error code: %d", static_cast<int>(error));
192 return VideoDecodeAcceleratorAdaptor::PLATFORM_FAILURE;
193 }
194 }
195
NotifyError(media::VideoDecodeAccelerator::Error error)196 void C2VDAAdaptor::NotifyError(media::VideoDecodeAccelerator::Error error) {
197 mClient->notifyError(convertErrorCode(error));
198 }
199
200 } // namespace android
201