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

Side by Side Diff: content/browser/renderer_host/gpu_jpeg_decoder.cc

Issue 1132683004: MJPEG acceleration for video capture, browser part (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@mjpeg-2-gpu
Patch Set: add flag --enable-accelerated-mjpeg-decode 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/browser/renderer_host/gpu_jpeg_decoder.h"
6
7 #include "base/bind.h"
8 #include "base/command_line.h"
9 #include "base/logging.h"
10 #include "base/strings/stringprintf.h"
11 #include "base/trace_event/trace_event.h"
12 #include "content/browser/gpu/browser_gpu_channel_host_factory.h"
13 #include "content/common/gpu/client/gpu_jpeg_decode_accelerator_host.h"
14 #include "content/public/browser/browser_thread.h"
15 #include "content/public/common/content_switches.h"
16 #include "media/base/video_frame.h"
17
18 namespace content {
19
20 // static
21 bool GpuJpegDecoder::Supported() {
22 // A lightweight check for caller to avoid IPC latency for known unsupported
23 // platform. Initialize() can do the real platform supporting check but it
24 // requires an IPC even for platforms that do not support HW decoder.
25 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
26 switches::kEnableAcceleratedMjpegDecode)) {
27 // TODO(kcwu): move this information to GpuInfo.
28 #if defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY)
29 return true;
30 #endif
31 }
32 return false;
33 }
34
35 GpuJpegDecoder::GpuJpegDecoder(const DecodeDoneCB& decode_done_cb,
36 const ErrorCB& error_cb)
37 : gpu_channel_event_(false /* manual reset */,
38 false /* initially_signaled */),
39 decode_done_cb_(decode_done_cb),
40 error_cb_(error_cb),
41 next_bitstream_buffer_id_(0),
42 in_buffer_(media::JpegDecodeAccelerator::kInvalidBitstreamBufferId,
43 base::SharedMemory::NULLHandle(),
44 0) {
45 }
46
47 GpuJpegDecoder::~GpuJpegDecoder() {
48 DCHECK(CalledOnValidThread());
49
50 // |decoder_| guarantees no more JpegDecodeAccelerator::Client callbacks
51 // on IO thread after deletion.
52 decoder_.reset();
53
54 // |gpu_channel_host_| should outlive |decoder_|, so |gpu_channel_host_|
55 // must be released after |decoder_| is been destroyed.
56 gpu_channel_host_ = nullptr;
57 }
58
59 bool GpuJpegDecoder::IsDecoding_Locked() {
60 lock_.AssertAcquired();
61 return !decode_done_closure_.is_null();
62 }
63
64 bool GpuJpegDecoder::Initialize() {
65 DVLOG(3) << __func__;
66 DCHECK(CalledOnValidThread());
67 // Not on IO thread. Otherwise deadlock.
68 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
69
70 DCHECK(BrowserGpuChannelHostFactory::instance());
71 BrowserThread::PostTask(
72 BrowserThread::UI, FROM_HERE,
73 base::Bind(&BrowserGpuChannelHostFactory::EstablishGpuChannel,
74 base::Unretained(BrowserGpuChannelHostFactory::instance()),
piman 2015/06/05 23:07:51 BrowserGpuChannelHostFactory is a UI thread class.
kcwu 2015/06/17 14:35:37 Done.
75 CAUSE_FOR_GPU_LAUNCH_JPEGDECODEACCELERATOR_INITIALIZE,
76 base::Bind(&GpuJpegDecoder::GpuChannelEstablished,
77 base::Unretained(this))));
78 gpu_channel_event_.Wait();
piman 2015/06/05 23:07:51 Which thread is this called on? It seems like this
kcwu 2015/06/17 14:35:37 Done. I added a function ReadyToDecode, which indi
79 if (!gpu_channel_host_) {
80 LOG(ERROR) << "Failed to establish GPU channel for JPEG decoder";
81 return false;
82 }
83
84 decoder_ = gpu_channel_host_->CreateJpegDecoder(this);
85 if (!decoder_) {
86 return false;
87 }
88
89 return true;
90 }
91
92 void GpuJpegDecoder::GpuChannelEstablished() {
93 DCHECK(BrowserGpuChannelHostFactory::instance()->IsMainThread());
94
95 gpu_channel_host_ = BrowserGpuChannelHostFactory::instance()->GetGpuChannel();
96 gpu_channel_event_.Signal();
97 }
98
99 void GpuJpegDecoder::VideoFrameReady(int32_t bitstream_buffer_id) {
100 DVLOG(3) << __func__;
101 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
102 TRACE_EVENT0("jpeg", "GpuJpegDecoder::VideoFrameReady");
103 base::AutoLock lock(lock_);
104
105 if (!IsDecoding_Locked()) {
106 LOG(ERROR) << "Got decode response while not decoding";
107 return;
108 }
109
110 if (bitstream_buffer_id != in_buffer_.id()) {
111 LOG(ERROR) << "Unexpected bitstream_buffer_id " << bitstream_buffer_id
112 << ", expected " << in_buffer_.id();
113 return;
114 }
115
116 decode_done_closure_.Run();
117 decode_done_closure_.Reset();
118
119 TRACE_EVENT_ASYNC_END0("jpeg", "GpuJpegDecoder decoding",
120 bitstream_buffer_id);
121 }
122
123 void GpuJpegDecoder::NotifyError(int32_t bitstream_buffer_id,
124 media::JpegDecodeAccelerator::Error error) {
125 DVLOG(3) << __func__;
126 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
127 LOG(ERROR) << "Decode error, bitstream_buffer_id=" << bitstream_buffer_id;
128
129 base::AutoLock lock(lock_);
130 decode_done_closure_.Reset();
131
132 error_cb_.Run(
133 base::StringPrintf("Decode error, bitstream_buffer_id=%d, error=%d",
134 bitstream_buffer_id, error));
135 }
136
137 void GpuJpegDecoder::DecodeCapturedData(
138 const uint8* data,
139 size_t in_buffer_size,
140 const media::VideoCaptureFormat& frame_format,
141 const base::TimeTicks& timestamp,
142 scoped_ptr<media::VideoCaptureDevice::Client::Buffer> out_buffer) {
143 DCHECK(CalledOnValidThread());
144
145 TRACE_EVENT_ASYNC_BEGIN0("jpeg", "GpuJpegDecoder decoding",
146 next_bitstream_buffer_id_);
147 TRACE_EVENT0("jpeg", "GpuJpegDecoder::DecodeCapturedData");
148
149 // TODO(kcwu): enqueue decode requests in case decoding is not fast enough
150 // (say, if decoding time is longer than 16ms for 60fps 4k image)
151 {
152 base::AutoLock lock(lock_);
153 if (IsDecoding_Locked()) {
154 DVLOG(1) << "Drop captured frame. Previous jpeg frame is still decoding";
155 return;
156 }
157 }
158
159 // Enlarge input buffer if necessary.
160 if (!in_shared_memory_.get() ||
161 in_buffer_size > in_shared_memory_->mapped_size()) {
162 // Reserve 2x space to avoid frequent reallocations for initial frames.
163 const size_t reserved_size = 2 * in_buffer_size;
164 in_shared_memory_.reset(new base::SharedMemory);
165 if (!in_shared_memory_->CreateAndMapAnonymous(reserved_size)) {
166 base::AutoLock lock(lock_);
167 error_cb_.Run(base::StringPrintf("CreateAndMapAnonymous failed, size=%zd",
168 reserved_size));
169 return;
170 }
171 }
172 memcpy(in_shared_memory_->memory(), data, in_buffer_size);
173
174 // No need to lock for |in_buffer_| since IsDecoding_Locked() is false.
175 in_buffer_ = media::BitstreamBuffer(
176 next_bitstream_buffer_id_, in_shared_memory_->handle(), in_buffer_size);
177 // Mask against 30 bits, to avoid (undefined) wraparound on signed integer.
178 next_bitstream_buffer_id_ = (next_bitstream_buffer_id_ + 1) & 0x3FFFFFFF;
179
180 const gfx::Size dimensions = frame_format.frame_size;
181 base::SharedMemoryHandle out_handle(out_buffer->AsPlatformHandle(), true);
182 scoped_refptr<media::VideoFrame> out_frame =
183 media::VideoFrame::WrapExternalSharedMemory(
184 media::VideoFrame::I420, // format
185 dimensions, // coded_size
186 gfx::Rect(dimensions), // visible_rect
187 dimensions, // natural_size
188 static_cast<uint8*>(out_buffer->data()), // data
189 out_buffer->size(), // data_size
190 out_handle, // handle
191 0, // shared_memory_offset
192 base::TimeDelta()); // timestamp
193 DCHECK(out_frame.get());
194 out_frame->metadata()->SetDouble(media::VideoFrameMetadata::FRAME_RATE,
195 frame_format.frame_rate);
196
197 {
198 base::AutoLock lock(lock_);
199 decode_done_closure_ = base::Bind(
200 decode_done_cb_, base::Passed(&out_buffer), out_frame, timestamp);
201 }
202 decoder_->Decode(in_buffer_, out_frame);
203 }
204
205 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698