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