blob: 5646d24bc8fc8017c16b880027f3024e9adf4eae [file] [log] [blame]
// Copyright 2016 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef STARBOARD_RASPI_SHARED_DISPMANX_UTIL_H_
#define STARBOARD_RASPI_SHARED_DISPMANX_UTIL_H_
#include <bcm_host.h>
#include <functional>
#include "starboard/common/log.h"
#include "starboard/common/scoped_ptr.h"
#include "starboard/configuration.h"
#include "starboard/shared/internal_only.h"
#include "starboard/shared/starboard/player/filter/video_frame_internal.h"
#include "starboard/types.h"
namespace starboard {
namespace raspi {
namespace shared {
class DispmanxRect : public VC_RECT_T {
public:
DispmanxRect() { vc_dispmanx_rect_set(this, 0, 0, 0, 0); }
DispmanxRect(uint32_t x, uint32_t y, uint32_t width, uint32_t height) {
vc_dispmanx_rect_set(this, x, y, width, height);
}
};
class DispmanxDisplay {
public:
DispmanxDisplay() {
bcm_host_init();
handle_ = vc_dispmanx_display_open(0);
SB_DCHECK(handle_ != DISPMANX_NO_HANDLE);
}
~DispmanxDisplay() {
int result = vc_dispmanx_display_close(handle_);
SB_DCHECK(result == 0);
bcm_host_deinit();
}
DISPMANX_DISPLAY_HANDLE_T handle() const { return handle_; }
private:
DISPMANX_DISPLAY_HANDLE_T handle_;
DispmanxDisplay(const DispmanxDisplay&) = delete;
void operator=(const DispmanxDisplay&) = delete;
};
class DispmanxResource {
public:
DispmanxResource() : handle_(DISPMANX_NO_HANDLE) {}
virtual ~DispmanxResource() {
if (handle_ != DISPMANX_NO_HANDLE) {
int32_t result = vc_dispmanx_resource_delete(handle_);
SB_DCHECK(result == 0) << " result=" << result;
}
}
DISPMANX_RESOURCE_HANDLE_T handle() const { return handle_; }
uint32_t visible_width() const { return visible_width_; }
uint32_t visible_height() const { return visible_height_; }
uint32_t width() const { return width_; }
uint32_t height() const { return height_; }
protected:
DispmanxResource(VC_IMAGE_TYPE_T image_type,
uint32_t width,
uint32_t height,
uint32_t visible_width,
uint32_t visible_height);
private:
DISPMANX_RESOURCE_HANDLE_T handle_;
uint32_t width_;
uint32_t height_;
uint32_t visible_width_;
uint32_t visible_height_;
DispmanxResource(const DispmanxResource&) = delete;
void operator=(const DispmanxResource&) = delete;
};
class DispmanxYUV420Resource : public DispmanxResource {
public:
DispmanxYUV420Resource(uint32_t width,
uint32_t height,
uint32_t visible_width,
uint32_t visible_height)
: DispmanxResource(VC_IMAGE_YUV420,
width,
height,
visible_width,
visible_height) {}
void WriteData(const void* data);
void ClearWithBlack();
};
class DispmanxRGB565Resource : public DispmanxResource {
public:
DispmanxRGB565Resource(uint32_t width,
uint32_t height,
uint32_t visible_width,
uint32_t visible_height)
: DispmanxResource(VC_IMAGE_RGB565,
width,
height,
visible_width,
visible_height) {}
void WriteData(const void* data);
void ClearWithBlack();
};
class DispmanxElement {
public:
DispmanxElement(const DispmanxDisplay& display,
int32_t layer,
const DispmanxRect& dest_rect,
const DispmanxResource& src,
const DispmanxRect& src_rect);
~DispmanxElement();
DISPMANX_ELEMENT_HANDLE_T handle() const { return handle_; }
void ChangeSource(const DispmanxResource& new_src);
private:
DISPMANX_ELEMENT_HANDLE_T handle_;
DispmanxElement(const DispmanxElement&) = delete;
void operator=(const DispmanxElement&) = delete;
};
class DispmanxVideoFrame
: public starboard::shared::starboard::player::filter::VideoFrame {
public:
DispmanxVideoFrame(SbTime time,
DispmanxYUV420Resource* resource,
std::function<void(DispmanxYUV420Resource*)> release_cb)
: VideoFrame(time), resource_(resource), release_cb_(release_cb) {
SB_DCHECK(resource_);
SB_DCHECK(release_cb_);
}
~DispmanxVideoFrame() { release_cb_(resource_); }
DispmanxYUV420Resource* resource() const { return resource_; }
private:
DispmanxYUV420Resource* resource_;
std::function<void(DispmanxYUV420Resource*)> release_cb_;
};
class DispmanxVideoRenderer {
public:
typedef starboard::shared::starboard::player::filter::VideoFrame VideoFrame;
DispmanxVideoRenderer(const DispmanxDisplay& display, int32_t layer);
void Update(const scoped_refptr<VideoFrame>& video_frame);
void HideElement();
void ShowElement();
private:
scoped_ptr<DispmanxElement> element_;
scoped_refptr<VideoFrame> frame_;
// Value of |frame_| when HideElement() gets called.
scoped_refptr<VideoFrame> hidden_frame_;
// Used to fill the background with black if no video is playing so that the
// console does not show through.
DispmanxRGB565Resource black_frame_;
DispmanxVideoRenderer(const DispmanxVideoRenderer&) = delete;
void operator=(const DispmanxVideoRenderer&) = delete;
};
} // namespace shared
} // namespace raspi
} // namespace starboard
#endif // STARBOARD_RASPI_SHARED_DISPMANX_UTIL_H_