Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(314)

Side by Side Diff: content/common/gpu/media/vaapi_jpeg_decode_accelerator.cc

Issue 1124423008: MJPEG acceleration for video capture using VAAPI, the GPU and IPC part (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@mjpeg-1-media
Patch Set: gpu_jpeg_decode_accelerator.cc filter to dispatch decode task Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 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 #include "content/common/gpu/media/vaapi_jpeg_decode_accelerator.h"
6
7 #include "base/bind.h"
8 #include "base/logging.h"
9 #include "base/thread_task_runner_handle.h"
10 #include "base/trace_event/trace_event.h"
11 #include "content/common/gpu/gpu_channel.h"
12 #include "content/common/gpu/media/vaapi_picture.h"
13 #include "media/base/video_frame.h"
14 #include "media/filters/jpeg_parser.h"
15
16 static void ReportVaapiError() {
17 // TODO(kcwu) report error to UMA
18 }
19
20 namespace content {
21
22 VaapiJpegDecodeAccelerator::DecodeRequest::DecodeRequest(
23 const media::BitstreamBuffer& bitstream_buffer,
24 scoped_refptr<media::VideoFrame> video_frame)
25 : bitstream_buffer(bitstream_buffer), video_frame(video_frame) {
26 }
27
28 VaapiJpegDecodeAccelerator::DecodeRequest::~DecodeRequest() {
29 }
30
31 void VaapiJpegDecodeAccelerator::NotifyError(int32_t bitstream_buffer_id,
32 Error error) {
33 DCHECK_EQ(task_runner_, base::ThreadTaskRunnerHandle::Get());
34 DLOG(ERROR) << "Notifying of error " << error;
35 DCHECK(client_);
36 client_->NotifyError(bitstream_buffer_id, error);
37 }
38
39 void VaapiJpegDecodeAccelerator::NotifyErrorFromDecoderThread(
40 int32_t bitstream_buffer_id,
41 Error error) {
42 DCHECK(decoder_task_runner_->BelongsToCurrentThread());
43 task_runner_->PostTask(FROM_HERE,
44 base::Bind(&VaapiJpegDecodeAccelerator::NotifyError,
45 weak_this_, bitstream_buffer_id, error));
46 }
47
48 VaapiJpegDecodeAccelerator::VaapiJpegDecodeAccelerator(
49 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner)
50 : initialized_(false),
51 task_runner_(base::ThreadTaskRunnerHandle::Get()),
52 io_task_runner_(io_task_runner),
53 decoder_thread_("VaapiJpegDecoderThread"),
54 va_surface_(VA_INVALID_SURFACE),
55 weak_this_factory_(this) {
56 weak_this_ = weak_this_factory_.GetWeakPtr();
57 }
58
59 VaapiJpegDecodeAccelerator::~VaapiJpegDecodeAccelerator() {
60 DCHECK_EQ(task_runner_, base::ThreadTaskRunnerHandle::Get());
61 Cleanup();
62 }
63
64 bool VaapiJpegDecodeAccelerator::Initialize(Client* client) {
65 DCHECK_EQ(task_runner_, base::ThreadTaskRunnerHandle::Get());
66
67 client_ = client;
68
69 base::AutoLock auto_lock(lock_);
70 DCHECK(!initialized_);
71
72 vaapi_wrapper_ =
73 VaapiWrapper::Create(VaapiWrapper::kDecode, VAProfileJPEGBaseline,
74 base::Bind(&ReportVaapiError));
75
76 if (!vaapi_wrapper_.get()) {
77 DLOG(ERROR) << "Failed initializing VAAPI";
78 return false;
79 }
80
81 if (!decoder_thread_.Start()) {
82 DLOG(ERROR) << "Failed to start decoding thread.";
83 return false;
84 }
85 decoder_task_runner_ = decoder_thread_.task_runner();
86
87 initialized_ = true;
88 return true;
89 }
90
91 bool VaapiJpegDecodeAccelerator::OutputPicture(
92 VASurfaceID va_surface_id,
93 int32_t input_buffer_id,
94 const scoped_refptr<media::VideoFrame>& video_frame) {
95 DCHECK(decoder_task_runner_->BelongsToCurrentThread());
96
97 TRACE_EVENT1("jpeg", "VaapiJpegDecodeAccelerator::OutputPicture",
98 "input_buffer_id", input_buffer_id);
99
100 DVLOG(3) << "Outputting VASurface " << va_surface_id
101 << " into video_frame associated with input buffer id "
102 << input_buffer_id;
103
104 VAImage image;
105 VAImageFormat format;
106 const uint32_t kI420Fourcc = VA_FOURCC('I', '4', '2', '0');
107 memset(&image, 0, sizeof(image));
108 memset(&format, 0, sizeof(format));
109 format.fourcc = kI420Fourcc;
110 format.byte_order = VA_LSB_FIRST;
111 format.bits_per_pixel = 12; // 12 for I420
112
113 void* mem = nullptr;
114 gfx::Size coded_size = video_frame->coded_size();
115 if (!vaapi_wrapper_->GetVaImage(va_surface_id, &format, coded_size, &image,
116 &mem)) {
117 DLOG(ERROR) << "Cannot get VAImage";
118 return false;
119 }
120
121 uint8* frame_mem = video_frame->data(media::VideoFrame::kYPlane);
122 size_t frame_buffer_size =
123 media::VideoFrame::AllocationSize(media::VideoFrame::I420, coded_size);
124 memcpy(frame_mem, mem, frame_buffer_size);
125
126 vaapi_wrapper_->ReturnVaImage(&image);
127
128 task_runner_->PostTask(
129 FROM_HERE,
130 base::Bind(&media::JpegDecodeAccelerator::Client::VideoFrameReady,
131 base::Unretained(client_), input_buffer_id));
132
133 return true;
134 }
135
136 void VaapiJpegDecodeAccelerator::DecodeTask() {
137 DVLOG(3) << __func__;
138 DCHECK(decoder_task_runner_->BelongsToCurrentThread());
139 TRACE_EVENT0("jpeg", "DecodeTask");
140 linked_ptr<DecodeRequest> request;
141 {
142 base::AutoLock auto_lock(lock_);
143 if (!initialized_)
144 return;
145
146 DCHECK(!decode_requests_.empty());
147 request = decode_requests_.front();
148 decode_requests_.pop();
149 }
150
151 DVLOG(4) << "Mapping new input buffer id: " << request->bitstream_buffer.id()
152 << " size: " << (int)request->bitstream_buffer.size();
153
154 scoped_ptr<base::SharedMemory> shm(
155 new base::SharedMemory(request->bitstream_buffer.handle(), true));
156 if (!shm->Map(request->bitstream_buffer.size())) {
157 LOG(ERROR) << "Failed to map input buffer";
158 NotifyErrorFromDecoderThread(request->bitstream_buffer.id(),
159 UNREADABLE_INPUT);
160 return;
161 }
162
163 media::JpegParseResult parse_result;
164
165 if (!media::ParseJpegPicture(reinterpret_cast<const uint8_t*>(shm->memory()),
166 request->bitstream_buffer.size(),
167 &parse_result)) {
168 DLOG(ERROR) << "ParseJpegPicture failed";
169 NotifyErrorFromDecoderThread(
170 request->bitstream_buffer.id(),
171 media::JpegDecodeAccelerator::PARSE_JPEG_FAILED);
172 return;
173 }
174
175 // Reuse VASurface if size doesn't change.
176 gfx::Size coded_size(parse_result.frame_header.coded_width,
177 parse_result.frame_header.coded_height);
178 if (coded_size != coded_size_ || va_surface_ == VA_INVALID_SURFACE) {
179 vaapi_wrapper_->DestroySurfaces();
180 std::vector<VASurfaceID> va_surfaces;
181 if (!vaapi_wrapper_->CreateSurfaces(coded_size, 1, &va_surfaces)) {
182 LOG(ERROR) << "Create VA surface failed";
183 NotifyErrorFromDecoderThread(
184 request->bitstream_buffer.id(),
185 media::JpegDecodeAccelerator::PLATFORM_FAILURE);
186 return;
187 }
188 va_surface_ = va_surfaces[0];
189 coded_size_ = coded_size;
190 }
191
192 if (!VaapiJpegDecoder::Decode(vaapi_wrapper_.get(), parse_result,
193 va_surface_)) {
194 LOG(ERROR) << "Decode JPEG failed";
195 NotifyErrorFromDecoderThread(
196 request->bitstream_buffer.id(),
197 media::JpegDecodeAccelerator::PLATFORM_FAILURE);
198 return;
199 }
200
201 if (!OutputPicture(va_surface_, request->bitstream_buffer.id(),
202 request->video_frame)) {
203 LOG(ERROR) << "Output picture failed";
204 NotifyErrorFromDecoderThread(
205 request->bitstream_buffer.id(),
206 media::JpegDecodeAccelerator::PLATFORM_FAILURE);
207 return;
208 }
209 }
210
211 void VaapiJpegDecodeAccelerator::Decode(
212 const media::BitstreamBuffer& bitstream_buffer,
213 const scoped_refptr<media::VideoFrame>& video_frame) {
214 DVLOG(3) << __func__;
215 DCHECK(io_task_runner_->BelongsToCurrentThread());
216 TRACE_EVENT1("jpeg", "Decode", "input_id", bitstream_buffer.id());
217
218 base::AutoLock auto_lock(lock_);
219 if (!initialized_)
220 return;
221
222 // Set up a new decode request and queue it for later.
223 linked_ptr<DecodeRequest> input_buffer(
224 new DecodeRequest(bitstream_buffer, video_frame));
225 decode_requests_.push(input_buffer);
226
227 decoder_task_runner_->PostTask(
228 FROM_HERE, base::Bind(&VaapiJpegDecodeAccelerator::DecodeTask,
229 base::Unretained(this)));
230 }
231
232 void VaapiJpegDecodeAccelerator::Cleanup() {
233 DCHECK_EQ(task_runner_, base::ThreadTaskRunnerHandle::Get());
234
235 base::AutoLock auto_lock(lock_);
236 if (!initialized_)
237 return;
238
239 DVLOG(1) << "Destroying VaapiJpegDecodeAccelerator";
240
241 weak_this_factory_.InvalidateWeakPtrs();
242
243 {
244 base::AutoUnlock auto_unlock(lock_);
245 decoder_thread_.Stop();
246 }
247
248 initialized_ = false;
249 }
250
251 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698