| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. Use of this | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. Use of this |
| 2 // source code is governed by a BSD-style license that can be found in the | 2 // source code is governed by a BSD-style license that can be found in the |
| 3 // LICENSE file. | 3 // LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/renderer/media/ipc_video_decoder.h" | 5 #include "chrome/renderer/media/ipc_video_decoder.h" |
| 6 | 6 |
| 7 #include <GLES2/gl2.h> |
| 8 |
| 7 #include "base/task.h" | 9 #include "base/task.h" |
| 8 #include "chrome/renderer/ggl/ggl.h" | 10 #include "chrome/renderer/ggl/ggl.h" |
| 9 #include "media/base/callback.h" | 11 #include "media/base/callback.h" |
| 10 #include "media/base/filters.h" | 12 #include "media/base/filters.h" |
| 11 #include "media/base/filter_host.h" | 13 #include "media/base/filter_host.h" |
| 12 #include "media/base/limits.h" | 14 #include "media/base/limits.h" |
| 13 #include "media/base/media_format.h" | 15 #include "media/base/media_format.h" |
| 14 #include "media/base/video_frame.h" | 16 #include "media/base/video_frame.h" |
| 15 #include "media/ffmpeg/ffmpeg_common.h" | 17 #include "media/ffmpeg/ffmpeg_common.h" |
| 16 #include "media/ffmpeg/ffmpeg_util.h" | 18 #include "media/ffmpeg/ffmpeg_util.h" |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 56 if (!demuxer_stream->QueryInterface(&av_stream_provider)) { | 58 if (!demuxer_stream->QueryInterface(&av_stream_provider)) { |
| 57 GpuVideoDecoderInitDoneParam param; | 59 GpuVideoDecoderInitDoneParam param; |
| 58 OnInitializeDone(false, param); | 60 OnInitializeDone(false, param); |
| 59 return; | 61 return; |
| 60 } | 62 } |
| 61 | 63 |
| 62 AVStream* av_stream = av_stream_provider->GetAVStream(); | 64 AVStream* av_stream = av_stream_provider->GetAVStream(); |
| 63 width_ = av_stream->codec->width; | 65 width_ = av_stream->codec->width; |
| 64 height_ = av_stream->codec->height; | 66 height_ = av_stream->codec->height; |
| 65 | 67 |
| 66 // TODO(hclam): Pass an actual context instead of NULL. | 68 // Switch GL context. |
| 67 gpu_video_decoder_host_ = ggl::CreateVideoDecoder(NULL); | 69 bool ret = ggl::MakeCurrent(ggl_context_); |
| 70 DCHECK(ret) << "Failed to switch GL context"; |
| 71 |
| 72 // Generate textures to be used by the hardware video decoder in the GPU |
| 73 // process. |
| 74 // TODO(hclam): Allocation of textures should be done based on the request |
| 75 // of the GPU process. |
| 76 GLuint texture; |
| 77 glGenTextures(1, &texture); |
| 78 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width_, height_, 0, GL_RGBA, |
| 79 GL_UNSIGNED_BYTE, NULL); |
| 80 texture_ = texture; |
| 81 |
| 82 // Create a hardware video decoder handle for IPC communication. |
| 83 gpu_video_decoder_host_ = ggl::CreateVideoDecoder(ggl_context_); |
| 68 | 84 |
| 69 // Initialize hardware decoder. | 85 // Initialize hardware decoder. |
| 70 GpuVideoDecoderInitParam param = {0}; | 86 GpuVideoDecoderInitParam param = {0}; |
| 71 param.width_ = width_; | 87 param.width = width_; |
| 72 param.height_ = height_; | 88 param.height = height_; |
| 73 if (!gpu_video_decoder_host_->Initialize(this, param)) { | 89 if (!gpu_video_decoder_host_->Initialize(this, param)) { |
| 74 GpuVideoDecoderInitDoneParam param; | 90 GpuVideoDecoderInitDoneParam param; |
| 75 OnInitializeDone(false, param); | 91 OnInitializeDone(false, param); |
| 76 } | 92 } |
| 77 } | 93 } |
| 78 | 94 |
| 79 void IpcVideoDecoder::OnInitializeDone( | 95 void IpcVideoDecoder::OnInitializeDone( |
| 80 bool success, const GpuVideoDecoderInitDoneParam& param) { | 96 bool success, const GpuVideoDecoderInitDoneParam& param) { |
| 81 if (MessageLoop::current() != renderer_thread_message_loop_) { | 97 if (MessageLoop::current() != renderer_thread_message_loop_) { |
| 82 renderer_thread_message_loop_->PostTask( | 98 renderer_thread_message_loop_->PostTask( |
| 83 FROM_HERE, | 99 FROM_HERE, |
| 84 NewRunnableMethod(this, | 100 NewRunnableMethod(this, |
| 85 &IpcVideoDecoder::OnInitializeDone, | 101 &IpcVideoDecoder::OnInitializeDone, |
| 86 success, | 102 success, |
| 87 param)); | 103 param)); |
| 88 return; | 104 return; |
| 89 } | 105 } |
| 90 | 106 |
| 91 media::AutoCallbackRunner done_runner(initialize_callback_.release()); | 107 media::AutoCallbackRunner done_runner(initialize_callback_.release()); |
| 92 | 108 |
| 93 if (success) { | 109 if (success) { |
| 94 media_format_.SetAsString(media::MediaFormat::kMimeType, | 110 media_format_.SetAsString(media::MediaFormat::kMimeType, |
| 95 media::mime_type::kUncompressedVideo); | 111 media::mime_type::kUncompressedVideo); |
| 96 media_format_.SetAsInteger(media::MediaFormat::kWidth, width_); | 112 media_format_.SetAsInteger(media::MediaFormat::kWidth, width_); |
| 97 media_format_.SetAsInteger(media::MediaFormat::kHeight, height_); | 113 media_format_.SetAsInteger(media::MediaFormat::kHeight, height_); |
| 98 media_format_.SetAsInteger(media::MediaFormat::kSurfaceType, | 114 media_format_.SetAsInteger(media::MediaFormat::kSurfaceType, |
| 99 static_cast<int>(param.surface_type_)); | 115 static_cast<int>(param.surface_type)); |
| 100 media_format_.SetAsInteger(media::MediaFormat::kSurfaceFormat, | 116 media_format_.SetAsInteger(media::MediaFormat::kSurfaceFormat, |
| 101 static_cast<int>(param.format_)); | 117 static_cast<int>(param.format)); |
| 102 state_ = kPlaying; | 118 state_ = kPlaying; |
| 103 } else { | 119 } else { |
| 104 LOG(ERROR) << "IpcVideoDecoder initialization failed!"; | 120 LOG(ERROR) << "IpcVideoDecoder initialization failed!"; |
| 105 host()->SetError(media::PIPELINE_ERROR_DECODE); | 121 host()->SetError(media::PIPELINE_ERROR_DECODE); |
| 106 } | 122 } |
| 107 } | 123 } |
| 108 | 124 |
| 109 void IpcVideoDecoder::Stop(media::FilterCallback* callback) { | 125 void IpcVideoDecoder::Stop(media::FilterCallback* callback) { |
| 110 if (MessageLoop::current() != renderer_thread_message_loop_) { | 126 if (MessageLoop::current() != renderer_thread_message_loop_) { |
| 111 renderer_thread_message_loop_->PostTask( | 127 renderer_thread_message_loop_->PostTask( |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 261 &IpcVideoDecoder::ProduceVideoFrame, | 277 &IpcVideoDecoder::ProduceVideoFrame, |
| 262 video_frame)); | 278 video_frame)); |
| 263 return; | 279 return; |
| 264 } | 280 } |
| 265 | 281 |
| 266 // Synchronized flushing before stop should prevent this. | 282 // Synchronized flushing before stop should prevent this. |
| 267 DCHECK_NE(state_, kStopped); | 283 DCHECK_NE(state_, kStopped); |
| 268 | 284 |
| 269 // Notify decode engine the available of new frame. | 285 // Notify decode engine the available of new frame. |
| 270 ++pending_requests_; | 286 ++pending_requests_; |
| 271 gpu_video_decoder_host_->FillThisBuffer(video_frame); | 287 |
| 288 VideoFrame::GlTexture textures[3] = { texture_, 0, 0 }; |
| 289 scoped_refptr<VideoFrame> frame; |
| 290 media::VideoFrame::CreateFrameGlTexture( |
| 291 media::VideoFrame::RGBA, width_, height_, textures, |
| 292 base::TimeDelta(), base::TimeDelta(), &frame); |
| 293 gpu_video_decoder_host_->FillThisBuffer(frame); |
| 272 } | 294 } |
| 273 | 295 |
| 274 void IpcVideoDecoder::OnFillBufferDone( | 296 void IpcVideoDecoder::OnFillBufferDone( |
| 275 scoped_refptr<media::VideoFrame> video_frame) { | 297 scoped_refptr<media::VideoFrame> video_frame) { |
| 276 if (MessageLoop::current() != renderer_thread_message_loop_) { | 298 if (MessageLoop::current() != renderer_thread_message_loop_) { |
| 277 renderer_thread_message_loop_->PostTask( | 299 renderer_thread_message_loop_->PostTask( |
| 278 FROM_HERE, | 300 FROM_HERE, |
| 279 NewRunnableMethod(this, | 301 NewRunnableMethod(this, |
| 280 &IpcVideoDecoder::OnFillBufferDone, | 302 &IpcVideoDecoder::OnFillBufferDone, |
| 281 video_frame)); | 303 video_frame)); |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 342 if (!format.GetAsString(media::MediaFormat::kMimeType, &mime_type) && | 364 if (!format.GetAsString(media::MediaFormat::kMimeType, &mime_type) && |
| 343 media::mime_type::kFFmpegVideo != mime_type) | 365 media::mime_type::kFFmpegVideo != mime_type) |
| 344 return false; | 366 return false; |
| 345 | 367 |
| 346 // TODO(jiesun): Although we current only support H264 hardware decoding, | 368 // TODO(jiesun): Although we current only support H264 hardware decoding, |
| 347 // in the future, we should query GpuVideoService for capabilities. | 369 // in the future, we should query GpuVideoService for capabilities. |
| 348 int codec_id; | 370 int codec_id; |
| 349 return format.GetAsInteger(media::MediaFormat::kFFmpegCodecID, &codec_id) && | 371 return format.GetAsInteger(media::MediaFormat::kFFmpegCodecID, &codec_id) && |
| 350 codec_id == CODEC_ID_H264; | 372 codec_id == CODEC_ID_H264; |
| 351 } | 373 } |
| OLD | NEW |