Process Alt-Svc headers.
[chromium-blink-merge.git] / content / browser / renderer_host / media / video_capture_gpu_jpeg_decoder.cc
blob8881a6f098f6fe9fd8004c3bf63e1c6a57d87d90
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.
5 #include "content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.h"
7 #include "base/bind.h"
8 #include "base/command_line.h"
9 #include "base/logging.h"
10 #include "base/single_thread_task_runner.h"
11 #include "base/strings/stringprintf.h"
12 #include "base/thread_task_runner_handle.h"
13 #include "base/trace_event/trace_event.h"
14 #include "content/browser/gpu/browser_gpu_channel_host_factory.h"
15 #include "content/common/gpu/client/gpu_jpeg_decode_accelerator_host.h"
16 #include "content/public/browser/browser_thread.h"
17 #include "content/public/common/content_switches.h"
18 #include "media/base/video_frame.h"
20 namespace content {
22 VideoCaptureGpuJpegDecoder::VideoCaptureGpuJpegDecoder(
23 const DecodeDoneCB& decode_done_cb)
24 : decode_done_cb_(decode_done_cb),
25 next_bitstream_buffer_id_(0),
26 in_buffer_id_(media::JpegDecodeAccelerator::kInvalidBitstreamBufferId),
27 decoder_status_(INIT_PENDING) {}
29 VideoCaptureGpuJpegDecoder::~VideoCaptureGpuJpegDecoder() {
30 DCHECK(CalledOnValidThread());
32 // |decoder_| guarantees no more JpegDecodeAccelerator::Client callbacks
33 // on IO thread after deletion.
34 decoder_.reset();
36 // |gpu_channel_host_| should outlive |decoder_|, so |gpu_channel_host_|
37 // must be released after |decoder_| has been destroyed.
38 gpu_channel_host_ = nullptr;
41 bool VideoCaptureGpuJpegDecoder::IsDecoding_Locked() const {
42 lock_.AssertAcquired();
43 return !decode_done_closure_.is_null();
46 void VideoCaptureGpuJpegDecoder::Initialize() {
47 DCHECK(CalledOnValidThread());
49 base::AutoLock lock(lock_);
50 // TODO(henryhsu): enable on ARM platform after V4L2 JDA is ready.
51 #if !defined(OS_CHROMEOS) || !defined(ARCH_CPU_X86_FAMILY)
52 // Non-ChromeOS platforms do not support HW JPEG decode now. Do not establish
53 // gpu channel to avoid introducing overhead.
54 decoder_status_ = FAILED;
55 return;
56 #else
57 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
58 switches::kDisableAcceleratedMjpegDecode)) {
59 decoder_status_ = FAILED;
60 return;
63 const scoped_refptr<base::SingleThreadTaskRunner> current_task_runner(
64 base::ThreadTaskRunnerHandle::Get());
65 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
66 base::Bind(&EstablishGpuChannelOnUIThread,
67 current_task_runner, AsWeakPtr()));
68 #endif
71 VideoCaptureGpuJpegDecoder::STATUS VideoCaptureGpuJpegDecoder::GetStatus()
72 const {
73 DCHECK(CalledOnValidThread());
74 base::AutoLock lock(lock_);
75 return decoder_status_;
78 // static
79 void VideoCaptureGpuJpegDecoder::EstablishGpuChannelOnUIThread(
80 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
81 base::WeakPtr<VideoCaptureGpuJpegDecoder> weak_this) {
82 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
83 DCHECK(BrowserGpuChannelHostFactory::instance());
85 BrowserGpuChannelHostFactory::instance()->EstablishGpuChannel(
86 CAUSE_FOR_GPU_LAUNCH_JPEGDECODEACCELERATOR_INITIALIZE,
87 base::Bind(&VideoCaptureGpuJpegDecoder::GpuChannelEstablishedOnUIThread,
88 task_runner, weak_this));
91 // static
92 void VideoCaptureGpuJpegDecoder::GpuChannelEstablishedOnUIThread(
93 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
94 base::WeakPtr<VideoCaptureGpuJpegDecoder> weak_this) {
95 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
97 scoped_refptr<GpuChannelHost> gpu_channel_host(
98 BrowserGpuChannelHostFactory::instance()->GetGpuChannel());
99 task_runner->PostTask(
100 FROM_HERE, base::Bind(&VideoCaptureGpuJpegDecoder::FinishInitialization,
101 weak_this, base::Passed(&gpu_channel_host)));
104 void VideoCaptureGpuJpegDecoder::FinishInitialization(
105 scoped_refptr<GpuChannelHost> gpu_channel_host) {
106 DCHECK(CalledOnValidThread());
107 base::AutoLock lock(lock_);
108 if (!gpu_channel_host) {
109 LOG(ERROR) << "Failed to establish GPU channel for JPEG decoder";
110 decoder_status_ = FAILED;
111 return;
114 if (gpu_channel_host->gpu_info().jpeg_decode_accelerator_supported) {
115 gpu_channel_host_ = gpu_channel_host.Pass();
116 decoder_ = gpu_channel_host_->CreateJpegDecoder(this);
118 decoder_status_ = decoder_ ? INIT_PASSED : FAILED;
121 void VideoCaptureGpuJpegDecoder::VideoFrameReady(int32_t bitstream_buffer_id) {
122 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
123 TRACE_EVENT0("jpeg", "VideoCaptureGpuJpegDecoder::VideoFrameReady");
124 base::AutoLock lock(lock_);
126 if (!IsDecoding_Locked()) {
127 LOG(ERROR) << "Got decode response while not decoding";
128 return;
131 if (bitstream_buffer_id != in_buffer_id_) {
132 LOG(ERROR) << "Unexpected bitstream_buffer_id " << bitstream_buffer_id
133 << ", expected " << in_buffer_id_;
134 return;
136 in_buffer_id_ = media::JpegDecodeAccelerator::kInvalidBitstreamBufferId;
138 decode_done_closure_.Run();
139 decode_done_closure_.Reset();
141 TRACE_EVENT_ASYNC_END0("jpeg", "VideoCaptureGpuJpegDecoder decoding",
142 bitstream_buffer_id);
145 void VideoCaptureGpuJpegDecoder::NotifyError(
146 int32_t bitstream_buffer_id,
147 media::JpegDecodeAccelerator::Error error) {
148 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
149 LOG(ERROR) << "Decode error, bitstream_buffer_id=" << bitstream_buffer_id
150 << ", error=" << error;
152 base::AutoLock lock(lock_);
153 decode_done_closure_.Reset();
154 decoder_status_ = FAILED;
157 void VideoCaptureGpuJpegDecoder::DecodeCapturedData(
158 const uint8_t* data,
159 size_t in_buffer_size,
160 const media::VideoCaptureFormat& frame_format,
161 const base::TimeTicks& timestamp,
162 scoped_ptr<media::VideoCaptureDevice::Client::Buffer> out_buffer) {
163 DCHECK(CalledOnValidThread());
164 DCHECK(decoder_);
166 TRACE_EVENT_ASYNC_BEGIN0("jpeg", "VideoCaptureGpuJpegDecoder decoding",
167 next_bitstream_buffer_id_);
168 TRACE_EVENT0("jpeg", "VideoCaptureGpuJpegDecoder::DecodeCapturedData");
170 // TODO(kcwu): enqueue decode requests in case decoding is not fast enough
171 // (say, if decoding time is longer than 16ms for 60fps 4k image)
173 base::AutoLock lock(lock_);
174 if (IsDecoding_Locked()) {
175 DVLOG(1) << "Drop captured frame. Previous jpeg frame is still decoding";
176 return;
180 // Enlarge input buffer if necessary.
181 if (!in_shared_memory_.get() ||
182 in_buffer_size > in_shared_memory_->mapped_size()) {
183 // Reserve 2x space to avoid frequent reallocations for initial frames.
184 const size_t reserved_size = 2 * in_buffer_size;
185 in_shared_memory_.reset(new base::SharedMemory);
186 if (!in_shared_memory_->CreateAndMapAnonymous(reserved_size)) {
187 base::AutoLock lock(lock_);
188 decoder_status_ = FAILED;
189 LOG(WARNING) << "CreateAndMapAnonymous failed, size=" << reserved_size;
190 return;
193 memcpy(in_shared_memory_->memory(), data, in_buffer_size);
195 // No need to lock for |in_buffer_id_| since IsDecoding_Locked() is false.
196 in_buffer_id_ = next_bitstream_buffer_id_;
197 media::BitstreamBuffer in_buffer(in_buffer_id_, in_shared_memory_->handle(),
198 in_buffer_size);
199 // Mask against 30 bits, to avoid (undefined) wraparound on signed integer.
200 next_bitstream_buffer_id_ = (next_bitstream_buffer_id_ + 1) & 0x3FFFFFFF;
202 #if defined(OS_POSIX) && !(defined(OS_MACOSX) && !defined(OS_IOS))
203 const gfx::Size dimensions = frame_format.frame_size;
204 base::SharedMemoryHandle out_handle = out_buffer->AsPlatformFile();
205 scoped_refptr<media::VideoFrame> out_frame =
206 media::VideoFrame::WrapExternalSharedMemory(
207 media::PIXEL_FORMAT_I420, // format
208 dimensions, // coded_size
209 gfx::Rect(dimensions), // visible_rect
210 dimensions, // natural_size
211 static_cast<uint8_t*>(out_buffer->data()), // data
212 out_buffer->size(), // data_size
213 out_handle, // handle
214 0, // shared_memory_offset
215 base::TimeDelta()); // timestamp
216 if (!out_frame) {
217 base::AutoLock lock(lock_);
218 decoder_status_ = FAILED;
219 LOG(ERROR) << "DecodeCapturedData: WrapExternalSharedMemory failed";
220 return;
222 out_frame->metadata()->SetDouble(media::VideoFrameMetadata::FRAME_RATE,
223 frame_format.frame_rate);
226 base::AutoLock lock(lock_);
227 decode_done_closure_ = base::Bind(
228 decode_done_cb_, base::Passed(&out_buffer), out_frame, timestamp);
230 decoder_->Decode(in_buffer, out_frame);
231 #else
232 NOTREACHED();
233 #endif
236 } // namespace content