• 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_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