• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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