CorsixTH engine (the C++ part)
Open source implementation of Theme Hospital
Loading...
Searching...
No Matches
th_movie.h
Go to the documentation of this file.
1/*
2Copyright (c) 2012 Stephen Baker
3
4Permission is hereby granted, free of charge, to any person obtaining a copy of
5this software and associated documentation files (the "Software"), to deal in
6the Software without restriction, including without limitation the rights to
7use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
8of the Software, and to permit persons to whom the Software is furnished to do
9so, subject to the following conditions:
10
11The above copyright notice and this permission notice shall be included in all
12copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20SOFTWARE.
21*/
22
23#ifndef TH_VIDEO_H
24#define TH_VIDEO_H
25
26#include "config.h"
27
28#include <SDL_rect.h>
29#include <SDL_render.h>
30
31#include <array>
32#include <atomic>
33#include <condition_variable>
34#include <memory>
35#include <mutex>
36#include <queue>
37#include <string>
38#include <thread>
39
40#ifdef CORSIX_TH_USE_FFMPEG
41#include <SDL_mixer.h>
42
43extern "C" {
44#ifndef INT64_C
45#define INT64_C(c) (c##LL)
46#define UINT64_C(c) (c##ULL)
47#endif
48#include <libavcodec/avcodec.h>
49// IWYU pragma: no_include <libavcodec/codec.h>
50// IWYU pragma: no_include <libavcodec/packet.h>
51// IWYU pragma: no_include <libavcodec/version.h>
52#include <libavformat/avformat.h>
53#include <libavutil/avutil.h> // IWYU pragma: keep
54// IWYU pragma: no_include <libavutil/channel_layout.h>
55// IWYU pragma: no_include <libavutil/frame.h>
56// IWYU pragma: no_include <libavutil/mem.h>
57// IWYU pragma: no_include <libavutil/pixfmt.h>
58// IWYU pragma: no_include <libavutil/version.h>
59#include <libswresample/swresample.h>
60}
61
62struct SwsContext;
63
64#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(59, 0, 100)
65using av_codec_ptr = AVCodec*;
66#else
67using av_codec_ptr = const AVCodec*;
68#endif
69
74 public:
75 void operator()(AVPacket* p) {
77 av_free(p);
78 }
79};
80
82using av_packet_unique_ptr = std::unique_ptr<AVPacket, av_packet_deleter>;
83
84class av_frame_deleter {
85 public:
86 void operator()(AVFrame* f) { av_frame_free(&f); }
87};
88
89using av_frame_unique_ptr = std::unique_ptr<AVFrame, av_frame_deleter>;
90
92 public:
93 void operator()(AVCodecContext* c) { avcodec_free_context(&c); }
94};
95
97 std::unique_ptr<AVCodecContext, av_codec_context_deleter>;
98
103class mix_chunk_deleter {
104 public:
105 void operator()(Mix_Chunk* c) { Mix_FreeChunk(c); }
106};
107
108using mix_chunk_unique_ptr = std::unique_ptr<Mix_Chunk, mix_chunk_deleter>;
109
110#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 24, 100)
113 public:
114 void operator()(AVChannelLayout* c) {
116 delete c;
117 }
118};
119
122 std::unique_ptr<AVChannelLayout, av_channel_layout_deleter>;
123#endif
124
129class movie_picture {
130 public:
133
135 void allocate(int iWidth, int iHeight);
136
138 void deallocate();
139
140 uint8_t* buffer;
141 const AVPixelFormat pixel_format;
142 int width;
143 int height;
144 double pts;
145 std::mutex mutex;
146};
147
150 public:
153
154 // NB: The following functions are called by the main program thread
155
157 void abort();
158
160 void reset();
161
168
174 void deallocate();
175
177 bool advance();
178
185 void draw(SDL_Renderer* pRenderer, const SDL_Rect& dstrect);
186
188 double get_next_pts();
189
194 bool empty();
195
196 // NB: These functions are called by a second thread
197
202 bool full();
203
210 int write(AVFrame* pFrame, double dPts);
211
212 private:
216 bool unsafe_full() const;
217
219 static constexpr std::size_t picture_buffer_size = 4;
220
222 std::atomic<bool> aborting;
223
225 bool allocated;
226
228 int picture_count;
229
231 std::size_t read_index;
232
234 std::size_t write_index;
235
239
242 SDL_Texture* texture;
243
245 std::mutex mutex;
246
248 std::condition_variable cond;
249
251 std::array<movie_picture, picture_buffer_size> picture_queue;
252};
253
255class av_packet_queue {
256 public:
259
264 ~av_packet_queue() = default;
265
268
274
276 std::size_t get_count() const;
277
279 void release();
280
282 void clear();
283
284 private:
285 std::queue<av_packet_unique_ptr> data;
286 std::mutex mutex;
288 std::condition_variable
289 cond;
290};
291#endif // CORSIX_TH_USE_FFMPEG
292
300 public:
302 movie_player();
303
306
313
315 bool movies_enabled() const;
316
318 bool load(const char* szFilepath);
319
324 void unload();
325
330
332 void stop();
333
338 void togglePause();
339
341 int get_native_height() const;
342
344 int get_native_width() const;
345
347 bool has_audio_track() const;
348
350 double get_movie_length() const;
351
353 const char* get_last_error() const;
354
357 void clear_last_error();
358
364 double refresh(const SDL_Rect& destination_rect);
365
375
378
384 void read_streams();
385
391 void run_video();
392
395 void copy_audio_to_stream(uint8_t* pbStream, int iStreamSize);
396
397 private:
398#ifdef CORSIX_TH_USE_FFMPEG
399 static constexpr size_t movie_error_buffer_capacity =
400 128;
401
405
407
414 double get_presentation_time_for_frame(const AVFrame& frame,
415 int streamIndex) const;
416
418 int decode_audio_frame(uint8_t* stream, int stream_size);
419
426 int populate_frame(int stream, AVFrame& frame);
427
436
437 SDL_Renderer* renderer;
438
440 std::string last_error;
441
444
446 std::atomic<bool> aborting;
447
449 std::atomic<bool> paused{};
450 uint32_t pause_start_time{};
451
452 std::mutex decoding_audio_mutex;
453
464
465 // queues for transferring data between threads
469
470 // clock sync parameters
471 std::uint32_t current_sync_pts_system_time;
473 double current_sync_pts;
475
478
480 std::array<std::uint8_t, 1024>
482
483 int audio_channel;
484 int mixer_channels;
486 int mixer_frequency;
487
488 std::thread stream_thread;
490 std::thread video_thread;
492#endif // CORSIX_TH_USE_FFMPEG
493};
494
495#endif // TH_VIDEO_H
Definition th_movie.h:299
int get_native_width() const
Return the original width of the movie.
Definition th_movie.cpp:797
double refresh(const SDL_Rect &destination_rect)
Definition th_movie.cpp:802
void deallocate_picture_buffer()
Definition th_movie.cpp:804
void play(int requested_audio_channel)
Definition th_movie.cpp:789
void run_video()
Definition th_movie.cpp:806
void unload()
Definition th_movie.cpp:788
bool movies_enabled() const
Return whether movies were compiled into CorsixTH.
Definition th_movie.cpp:786
void read_streams()
Definition th_movie.cpp:805
void stop()
Stop the currently playing movie.
Definition th_movie.cpp:794
int get_native_height() const
Return the original height of the movie.
Definition th_movie.cpp:796
bool load(const char *szFilepath)
Load the movie with the given file name.
Definition th_movie.cpp:787
~movie_player()
Destroy the movie_player.
Definition th_movie.cpp:784
void clear_last_error()
Definition th_movie.cpp:801
const char * get_last_error() const
Return a text description of the last error encountered.
Definition th_movie.cpp:800
void set_renderer(SDL_Renderer *pRenderer)
Definition th_movie.cpp:785
double get_movie_length() const
Return the length of the movie in milliseconds.
Definition th_movie.cpp:799
void allocate_picture_buffer()
Allocate the picture buffer for the current renderer.
Definition th_movie.cpp:803
bool has_audio_track() const
Return whether the movie has an audio stream.
Definition th_movie.cpp:798
void copy_audio_to_stream(uint8_t *pbStream, int iStreamSize)
Definition th_movie.cpp:807
movie_player()
Construct a new movie_player.
Definition th_movie.cpp:783
void togglePause()
Definition th_movie.cpp:795