| Index: media/mf/basic_renderer.cc
|
| ===================================================================
|
| --- media/mf/basic_renderer.cc (revision 57106)
|
| +++ media/mf/basic_renderer.cc (working copy)
|
| @@ -1,220 +0,0 @@
|
| -// Copyright (c) 2010 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "media/mf/basic_renderer.h"
|
| -
|
| -#include <d3d9.h>
|
| -#include <mfapi.h>
|
| -#include <mfidl.h>
|
| -
|
| -#include "base/message_loop.h"
|
| -#include "base/scoped_comptr_win.h"
|
| -#include "media/base/yuv_convert.h"
|
| -
|
| -// For MFGetService and MF_BUFFER_SERVICE (getting D3D surface from buffer)
|
| -#pragma comment(lib, "mf.lib")
|
| -#pragma comment(lib, "strmiids.lib")
|
| -
|
| -namespace media {
|
| -
|
| -// Converts the given raw data buffer into RGB32 format, and drawing the result
|
| -// into the given window. This is only used when DXVA2 is not enabled.
|
| -// Returns: true on success.
|
| -bool ConvertToRGBAndDrawToWindow(HWND video_window, uint8* data, int width,
|
| - int height, int stride) {
|
| - CHECK(video_window != NULL);
|
| - CHECK(data != NULL);
|
| - CHECK_GT(width, 0);
|
| - CHECK_GT(height, 0);
|
| - CHECK_GE(stride, width);
|
| - height = (height + 15) & ~15;
|
| - bool success = true;
|
| - uint8* y_start = reinterpret_cast<uint8*>(data);
|
| - uint8* u_start = y_start + height * stride * 5 / 4;
|
| - uint8* v_start = y_start + height * stride;
|
| - static uint8* rgb_frame = new uint8[height * stride * 4];
|
| - int y_stride = stride;
|
| - int uv_stride = stride / 2;
|
| - int rgb_stride = stride * 4;
|
| - ConvertYUVToRGB32(y_start, u_start, v_start, rgb_frame,
|
| - width, height, y_stride, uv_stride,
|
| - rgb_stride, YV12);
|
| - PAINTSTRUCT ps;
|
| - InvalidateRect(video_window, NULL, TRUE);
|
| - HDC hdc = BeginPaint(video_window, &ps);
|
| - BITMAPINFOHEADER hdr;
|
| - hdr.biSize = sizeof(BITMAPINFOHEADER);
|
| - hdr.biWidth = width;
|
| - hdr.biHeight = -height; // minus means top-down bitmap
|
| - hdr.biPlanes = 1;
|
| - hdr.biBitCount = 32;
|
| - hdr.biCompression = BI_RGB; // no compression
|
| - hdr.biSizeImage = 0;
|
| - hdr.biXPelsPerMeter = 1;
|
| - hdr.biYPelsPerMeter = 1;
|
| - hdr.biClrUsed = 0;
|
| - hdr.biClrImportant = 0;
|
| - int rv = StretchDIBits(hdc, 0, 0, width, height, 0, 0, width, height,
|
| - rgb_frame, reinterpret_cast<BITMAPINFO*>(&hdr),
|
| - DIB_RGB_COLORS, SRCCOPY);
|
| - if (rv == 0) {
|
| - LOG(ERROR) << "StretchDIBits failed";
|
| - MessageLoopForUI::current()->QuitNow();
|
| - success = false;
|
| - }
|
| - EndPaint(video_window, &ps);
|
| -
|
| - return success;
|
| -}
|
| -
|
| -// Obtains the underlying raw data buffer for the given IMFMediaBuffer, and
|
| -// calls ConvertToRGBAndDrawToWindow() with it.
|
| -// Returns: true on success.
|
| -bool PaintMediaBufferOntoWindow(HWND video_window, IMFMediaBuffer* video_buffer,
|
| - int width, int height, int stride) {
|
| - CHECK(video_buffer != NULL);
|
| - HRESULT hr;
|
| - BYTE* data;
|
| - DWORD buffer_length;
|
| - DWORD data_length;
|
| - hr = video_buffer->Lock(&data, &buffer_length, &data_length);
|
| - if (FAILED(hr)) {
|
| - LOG(ERROR) << "Failed to lock IMFMediaBuffer";
|
| - return false;
|
| - }
|
| - if (!ConvertToRGBAndDrawToWindow(video_window,
|
| - reinterpret_cast<uint8*>(data),
|
| - width,
|
| - height,
|
| - stride)) {
|
| - LOG(ERROR) << "Failed to convert raw buffer to RGB and draw to window";
|
| - video_buffer->Unlock();
|
| - return false;
|
| - }
|
| - video_buffer->Unlock();
|
| - return true;
|
| -}
|
| -
|
| -// Obtains the D3D9 surface from the given IMFMediaBuffer, then calls methods
|
| -// in the D3D device to draw to the window associated with it.
|
| -// Returns: true on success.
|
| -bool PaintD3D9BufferOntoWindow(IDirect3DDevice9* device,
|
| - IMFMediaBuffer* video_buffer) {
|
| - CHECK(device != NULL);
|
| - ScopedComPtr<IDirect3DSurface9> surface;
|
| - HRESULT hr = MFGetService(video_buffer, MR_BUFFER_SERVICE,
|
| - IID_PPV_ARGS(surface.Receive()));
|
| - if (FAILED(hr)) {
|
| - LOG(ERROR) << "Failed to get D3D9 surface from buffer";
|
| - return false;
|
| - }
|
| - hr = device->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0),
|
| - 1.0f, 0);
|
| - if (FAILED(hr)) {
|
| - LOG(ERROR) << "Device->Clear() failed";
|
| - return false;
|
| - }
|
| - ScopedComPtr<IDirect3DSurface9> backbuffer;
|
| - hr = device->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO,
|
| - backbuffer.Receive());
|
| - if (FAILED(hr)) {
|
| - LOG(ERROR) << "Device->GetBackBuffer() failed";
|
| - return false;
|
| - }
|
| - hr = device->StretchRect(surface.get(), NULL, backbuffer.get(), NULL,
|
| - D3DTEXF_NONE);
|
| - if (FAILED(hr)) {
|
| - LOG(ERROR) << "Device->StretchRect() failed";
|
| - return false;
|
| - }
|
| - hr = device->Present(NULL, NULL, NULL, NULL);
|
| - if (FAILED(hr)) {
|
| - if (hr == E_FAIL) {
|
| - LOG(WARNING) << "Present() returned E_FAIL";
|
| - } else {
|
| - static int frames_dropped = 0;
|
| - LOG(ERROR) << "Device->Present() failed "
|
| - << std::hex << std::showbase << hr;
|
| - if (++frames_dropped == 10) {
|
| - LOG(ERROR) << "Dropped too many frames, quitting";
|
| - MessageLoopForUI::current()->QuitNow();
|
| - return false;
|
| - }
|
| - }
|
| - }
|
| - return true;
|
| -}
|
| -
|
| -static void ReleaseOutputBuffer(VideoFrame* frame) {
|
| - if (frame != NULL &&
|
| - frame->type() == VideoFrame::TYPE_MFBUFFER ||
|
| - frame->type() == VideoFrame::TYPE_DIRECT3DSURFACE) {
|
| - static_cast<IMFMediaBuffer*>(frame->private_buffer())->Release();
|
| - }
|
| -}
|
| -
|
| -// NullRenderer
|
| -
|
| -NullRenderer::NullRenderer(MftH264Decoder* decoder) : MftRenderer(decoder) {}
|
| -NullRenderer::~NullRenderer() {}
|
| -
|
| -void NullRenderer::ProcessFrame(scoped_refptr<VideoFrame> frame) {
|
| - ReleaseOutputBuffer(frame);
|
| - MessageLoop::current()->PostTask(
|
| - FROM_HERE, NewRunnableMethod(decoder_.get(),
|
| - &MftH264Decoder::GetOutput));
|
| -}
|
| -
|
| -void NullRenderer::StartPlayback() {
|
| - MessageLoop::current()->PostTask(
|
| - FROM_HERE, NewRunnableMethod(decoder_.get(),
|
| - &MftH264Decoder::GetOutput));
|
| -}
|
| -
|
| -void NullRenderer::OnDecodeError(MftH264Decoder::Error error) {
|
| - MessageLoop::current()->Quit();
|
| -}
|
| -
|
| -// BasicRenderer
|
| -
|
| -BasicRenderer::BasicRenderer(MftH264Decoder* decoder,
|
| - HWND window, IDirect3DDevice9* device)
|
| - : MftRenderer(decoder),
|
| - window_(window),
|
| - device_(device) {
|
| -}
|
| -
|
| -BasicRenderer::~BasicRenderer() {}
|
| -
|
| -void BasicRenderer::ProcessFrame(scoped_refptr<VideoFrame> frame) {
|
| - MessageLoopForUI::current()->PostDelayedTask(
|
| - FROM_HERE, NewRunnableMethod(decoder_.get(),
|
| - &MftH264Decoder::GetOutput),
|
| - frame->GetDuration().InMilliseconds());
|
| - if (device_ != NULL) {
|
| - if (!PaintD3D9BufferOntoWindow(device_,
|
| - static_cast<IMFMediaBuffer*>(frame->private_buffer()))) {
|
| - MessageLoopForUI::current()->QuitNow();
|
| - }
|
| - } else {
|
| - if (!PaintMediaBufferOntoWindow(
|
| - window_, static_cast<IMFMediaBuffer*>(frame->private_buffer()),
|
| - frame->width(), frame->height(), frame->stride(0))) {
|
| - MessageLoopForUI::current()->QuitNow();
|
| - }
|
| - }
|
| - ReleaseOutputBuffer(frame);
|
| -}
|
| -
|
| -void BasicRenderer::StartPlayback() {
|
| - MessageLoopForUI::current()->PostTask(
|
| - FROM_HERE, NewRunnableMethod(decoder_.get(),
|
| - &MftH264Decoder::GetOutput));
|
| -}
|
| -
|
| -void BasicRenderer::OnDecodeError(MftH264Decoder::Error error) {
|
| - MessageLoopForUI::current()->Quit();
|
| -}
|
| -
|
| -} // namespace media
|
|
|