Shaka Player Embedded
sdl_video_renderer.cc
Go to the documentation of this file.
1 // Copyright 2019 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
16 
17 #include <SDL2/SDL.h>
18 
19 #include <atomic>
20 
21 #include "shaka/optional.h"
22 #include "shaka/sdl_frame_drawer.h"
23 #include "shaka/utils.h"
24 #include "src/debug/mutex.h"
25 #include "src/debug/thread.h"
27 #include "src/util/clock.h"
28 #include "src/util/macros.h"
29 #include "src/util/utils.h"
30 
31 namespace shaka {
32 namespace media {
33 
35  public:
36  explicit Impl(SDL_Renderer* renderer)
37  : mutex_("SdlManualVideoRenderer"), renderer_(renderer) {
38  sdl_drawer_.SetRenderer(renderer);
39  }
40 
41  void SetRenderer(SDL_Renderer* renderer) {
42  std::unique_lock<Mutex> lock(mutex_);
43  sdl_drawer_.SetRenderer(renderer);
44  renderer_ = renderer;
45  }
46 
47  SDL_Renderer* GetRenderer() const {
48  std::unique_lock<Mutex> lock(mutex_);
49  return renderer_;
50  }
51 
52  double Render(const SDL_Rect* region) {
53  std::shared_ptr<DecodedFrame> frame;
54  const double delay = GetCurrentFrame(&frame);
55 
56  std::unique_lock<Mutex> lock(mutex_);
57  if (frame && renderer_) {
58  SDL_Texture* texture = sdl_drawer_.Draw(frame);
59  if (texture) {
60  ShakaRect<uint32_t> region_shaka;
61  if (region) {
62  region_shaka = {region->x, region->y, region->w, region->h};
63  } else {
64  int w = frame->stream_info->width;
65  int h = frame->stream_info->height;
66  SDL_GetRendererOutputSize(renderer_, &w, &h);
67  region_shaka.x = region_shaka.y = 0;
68  region_shaka.w = w;
69  region_shaka.h = h;
70  }
71 
73  ShakaRect<uint32_t> frame_region = {0, 0, frame->stream_info->width,
74  frame->stream_info->height};
75  FitVideoToRegion(frame_region, region_shaka,
76  frame->stream_info->sample_aspect_ratio, fill_mode(),
77  &src, &dest);
78  SDL_Rect src_sdl = {src.x, src.y, src.w, src.h};
79  SDL_Rect dest_sdl = {dest.x, dest.y, dest.w, dest.h};
80  SDL_RenderCopy(renderer_, texture, &src_sdl, &dest_sdl);
81  }
82  }
83 
84  return delay;
85  }
86 
87  private:
88  mutable Mutex mutex_;
89  SdlFrameDrawer sdl_drawer_;
90  SDL_Renderer* renderer_;
91 };
92 
94  public:
95  Impl(SdlThreadVideoRenderer* renderer, const SDL_Rect* region)
96  : renderer_(renderer),
97  region_(region ? optional<SDL_Rect>(*region) : nullopt),
98  shutdown_(false),
99  thread_("SdlThreadVideo", std::bind(&Impl::ThreadMain, this)) {}
100  ~Impl() {
101  shutdown_.store(true, std::memory_order_relaxed);
102  thread_.join();
103  }
104 
106 
107  private:
108  void ThreadMain() {
109  while (!shutdown_.load(std::memory_order_relaxed)) {
110  const double delay =
111  renderer_->Render(region_.has_value() ? &region_.value() : nullptr);
112  SDL_RenderPresent(renderer_->GetRenderer());
113 
115  }
116  }
117 
118  SdlThreadVideoRenderer* renderer_;
119  const optional<SDL_Rect> region_;
120  std::atomic<bool> shutdown_;
121  Thread thread_;
122 };
123 
124 
126  : impl_(new Impl(renderer)) {}
128 
129 void SdlManualVideoRenderer::SetRenderer(SDL_Renderer* renderer) {
130  impl_->SetRenderer(renderer);
131 }
132 SDL_Renderer* SdlManualVideoRenderer::GetRenderer() const {
133  return impl_->GetRenderer();
134 }
135 
136 double SdlManualVideoRenderer::Render(const SDL_Rect* region) {
137  return impl_->Render(region);
138 }
139 
141  impl_->SetPlayer(player);
142 }
144  impl_->Attach(stream);
145 }
147  impl_->Detach();
148 }
150  return impl_->VideoPlaybackQuality();
151 }
153  return impl_->SetVideoFillMode(mode);
154 }
155 
156 
158  : SdlManualVideoRenderer(renderer), impl_(new Impl(this, nullptr)) {}
160  const SDL_Rect* region)
161  : SdlManualVideoRenderer(renderer), impl_(new Impl(this, region)) {}
163 
164 } // namespace media
165 } // namespace shaka
SDL_Texture * texture
double Render(const SDL_Rect *region=nullptr)
const char * dest
Definition: media_utils.cc:31
bool SetVideoFillMode(VideoFillMode mode) override
VideoFillMode
Definition: utils.h:41
void Attach(const DecodedStream *stream) override
SDL_Texture * Draw(std::shared_ptr< media::DecodedFrame > frame)
std::shared_ptr< shaka::media::DecodedFrame > frame
void SetPlayer(const MediaPlayer *player) override
double GetCurrentFrame(std::shared_ptr< DecodedFrame > *frame)
struct VideoPlaybackQuality VideoPlaybackQuality() const override
#define SHAKA_NON_COPYABLE_OR_MOVABLE_TYPE(Type)
Definition: macros.h:51
const nullopt_t nullopt
Definition: optional.cc:22
void SetRenderer(SDL_Renderer *renderer)
SdlManualVideoRenderer(SDL_Renderer *renderer=nullptr)
void SetRenderer(SDL_Renderer *renderer)
void FitVideoToRegion(ShakaRect< uint32_t > frame, ShakaRect< uint32_t > bounds, Rational< uint32_t > sample_aspect_ratio, VideoFillMode mode, ShakaRect< uint32_t > *src, ShakaRect< uint32_t > *dest)
Definition: shaka_utils.cc:23
static const Clock Instance
Definition: clock.h:29
virtual void SleepSeconds(double seconds) const
Definition: clock.cc:39
SdlThreadVideoRenderer(SDL_Renderer *renderer)
Impl(SdlThreadVideoRenderer *renderer, const SDL_Rect *region)