TDME2  1.9.200
MPEG1Decoder.cpp
Go to the documentation of this file.
1 // This source code is based on
2 /*
3 PL_MPEG Example - Video player using SDL2/OpenGL for rendering
4 
5 Dominic Szablewski - https://phoboslab.org
6 
7 
8 -- LICENSE: The MIT License(MIT)
9 
10 Copyright(c) 2019 Dominic Szablewski
11 
12 Permission is hereby granted, free of charge, to any person obtaining a copy of
13 this software and associated documentation files(the "Software"), to deal in
14 the Software without restriction, including without limitation the rights to
15 use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies
16 of the Software, and to permit persons to whom the Software is furnished to do
17 so, subject to the following conditions :
18 The above copyright notice and this permission notice shall be included in all
19 copies or substantial portions of the Software.
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
23 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 SOFTWARE.
27 */
28 
29 #define PL_MPEG_IMPLEMENTATION
30 #include <ext/pl_mpeg/pl_mpeg.h>
31 
34 
35 #include <memory>
36 #include <string>
37 
38 #include <tdme/tdme.h>
39 #include <tdme/math/Math.h>
41 #include <tdme/utilities/Console.h>
42 
44 
45 using std::make_unique;
46 using std::string;
47 using std::to_string;
48 using std::unique_ptr;
49 
50 using tdme::math::Math;
54 
55 void MPEG1Decoder::openFile(const string& pathName, const string& fileName) {
56  // close old stream
57  close();
58 
59  // open new stream
60  plm = plm_create_with_filename((pathName + "/" + fileName).c_str());
61  if (plm == nullptr) {
62  Console::println("MPEG1Decoder::openFile(): Failed to open: " + pathName + "/" + fileName);
63  throw VideoDecoderException("Failed to open file");
64  }
65 
66  plm_set_video_decode_callback(plm, plmOnVideo, this);
67  plm_set_audio_decode_callback(plm, plmOnAudio, this);
68 
69  //
70  audioSampleRate = plm_get_samplerate(plm);
71  audioChannels = 2;
72  videoFrameRate = plm_get_framerate(plm);
73  videoDuration = plm_get_duration(plm);
74  videoWidth = plm_get_width(plm);
75  videoHeight = plm_get_height(plm);
76  videoBuffer = unique_ptr<ByteBuffer>(ByteBuffer::allocate(static_cast<int>(videoWidth) * static_cast<int>(videoHeight) * 4));
77  audioBuffer = unique_ptr<ByteBuffer>(ByteBuffer::allocate(32768));
78 
79  // request looping, enable audio, use stream 0
80  plm_set_loop(plm, TRUE);
81  plm_set_audio_enabled(plm, TRUE);
82  plm_set_audio_stream(plm, 0);
83 
84  // audio lead time
85  if (plm_get_num_audio_streams(plm) > 0) {
86  auto samplesPerBuffer = 4096;
87  plm_set_audio_lead_time(plm, (float)samplesPerBuffer / (float)audioSampleRate);
88  }
89 }
90 
92  if (plm == nullptr) return;
93  plm_seek(plm, 0.0f, FALSE);
94 }
95 
96 void MPEG1Decoder::update(float deltaTime) {
97  if (plm == nullptr) return;
98  plm_decode(plm, deltaTime);
99 }
100 
101 void MPEG1Decoder::seek(float time) {
102  if (plm == nullptr) return;
103  plm_seek(plm, time, FALSE);
104 }
105 
107  if (plm == nullptr) return 0LL;
108  auto read = Math::min(audioBuffer->getPosition(), data->getCapacity() - data->getPosition());
109  data->put(audioBuffer->getBuffer(), read);
110  audioBuffer->clear();
111  return read;
112 }
113 
115  if (plm == nullptr) return 0LL;
116  auto read = Math::min(videoBuffer->getCapacity(), data->getCapacity() - data->getPosition());
117  data->put(videoBuffer->getBuffer(), read);
118  return read;
119 }
120 
122  if (plm == nullptr) return;
123  plm_destroy(plm);
124  plm = nullptr;
125  videoBuffer = nullptr;
126  audioBuffer = nullptr;
127 }
128 
129 void MPEG1Decoder::plmOnVideo(plm_t* plm, plm_frame_t *frame, void *user) {
130  auto mpeg1Decoder = static_cast<MPEG1Decoder*>(user);
131  auto frameBuffer = mpeg1Decoder->videoBuffer->getBuffer();
132  plm_frame_to_rgba(frame, frameBuffer, frame->width * 4);
133  for (auto y = 0; y < mpeg1Decoder->videoHeight; y++) {
134  for (auto x = 0; x < mpeg1Decoder->videoWidth; x++) {
135  frameBuffer[y * mpeg1Decoder->videoWidth * 4 + x * 4 + 3] = 0xff;
136  }
137  }
138 }
139 
140 void MPEG1Decoder::plmOnAudio(plm_t* plm, plm_samples_t *samples, void *user) {
141  auto mpeg1Decoder = static_cast<MPEG1Decoder*>(user);
142  int samplesToProcess = samples->count * 2;
143  for (auto i = 0LL; i < samplesToProcess; i++) {
144  auto sample = static_cast<int16_t>(samples->interleaved[i] * 32767);
145  mpeg1Decoder->audioBuffer->put((uint8_t*)&sample, sizeof(int16_t));
146  }
147 }
Standard math functions.
Definition: Math.h:19
Buffer * put(uint8_t value)
Put value into buffer.
Definition: Buffer.h:115
virtual int64_t getCapacity() const
Definition: Buffer.h:82
virtual int64_t getPosition() const
Definition: Buffer.h:89
Byte buffer class.
Definition: ByteBuffer.h:27
Console class.
Definition: Console.h:29
PL_MPEG/MPEG1 video decoder.
Definition: MPEG1Decoder.h:28
int64_t readVideoFromStream(ByteBuffer *data) override
Read raw RGB video data from stream.
void close() override
Closes the audio file.
int64_t readAudioFromStream(ByteBuffer *data) override
Read raw PCM data from stream.
unique_ptr< ByteBuffer > audioBuffer
Definition: MPEG1Decoder.h:57
void update(float deltaTime) override
Update.
unique_ptr< ByteBuffer > videoBuffer
Definition: MPEG1Decoder.h:56
void seek(float time) override
Update.
static void plmOnVideo(plm_t *plm, plm_frame_t *frame, void *user)
PLM on video.
void reset() override
Resets this video decoder, if a stream was open it will be rewinded.
static void plmOnAudio(plm_t *plm, plm_samples_t *samples, void *user)
PLM on audio.