vdr-plugin-softhddevice-drm-gles 1.4.0
mediaplayer.cpp
Go to the documentation of this file.
1
25#include <cstdlib>
26#include <sys/stat.h>
27
28#include <string>
29using std::string;
30#include <fstream>
31using std::ifstream;
32#include <sys/stat.h>
33
34#include <vdr/interface.h>
35#include <vdr/player.h>
36#include <vdr/plugin.h>
37#include <vdr/videodir.h>
38
39#include "mediaplayer.h"
40#include "softhdmenu.h"
41#include "softhddevice.h"
42#include "logger.h"
43
44extern "C"
45{
46#include <libavcodec/avcodec.h>
47#include <libavformat/avformat.h>
48}
49
50#include "misc.h"
51
52#include "videostream.h"
53#include "audio.h"
54
55/*****************************************************************************
56 * cSoftHdPlayer (cPlayer mediaplayer)
57 ****************************************************************************/
58
60:cPlayer (pmAudioVideo)
61{
62// m_pPlayer= this;
63 m_pSource = (char *) malloc(1 + strlen(url));
64 strcpy(m_pSource, url);
65 if (strcasestr(m_pSource, ".M3U") && !strcasestr(m_pSource, ".M3U8")) {
68 } else {
69 FirstEntry = CurrentEntry = NULL;
70 }
71 Pause = 0;
72 Random = 0;
73 m_pDevice = device;
75// LOGDEBUG2(L_MEDIA, "mediaplayer: %s: Player gestartet.", __FUNCTION__);
76}
77
79{
80 StopPlay = 1;
81 free(m_pSource);
82 if (FirstEntry) {
83 while(FirstEntry) {
84 PLEntry *entry = FirstEntry;
85 FirstEntry = entry->NextEntry;
86 delete entry;
87 m_Entries--;
88 }
89 }
90
91// LOGDEBUG2(L_MEDIA, "mediaplayer: %s: Player beendet.", __FUNCTION__);
92}
93
95{
96// LOGDEBUG2(L_MEDIA, "mediaplayer: %s: %s", __FUNCTION__, On ? "On" : "Off");
97 if (On)
98 Start();
99}
100
102{
103// LOGDEBUG2(L_MEDIA, "mediaplayer: %s:", __FUNCTION__);
104 NoModify = 0;
105
106 if (strcasestr(m_pSource, ".M3U") && !strcasestr(m_pSource, ".M3U8")) {
107 while(CurrentEntry) {
108 Jump = 0;
109 Player(CurrentEntry->Path.c_str());
110
111 if (!NoModify) {
113
114 if (Random) {
115 srand (time (NULL));
116 SetEntry(std::rand() % (m_Entries));
117 }
118 }
119 NoModify = 0;
120
121 if (cSoftHdMenu::Menu()) {
123 }
124 }
125 } else {
127 }
128
130 usleep(5000);
131
133}
134
135void cSoftHdPlayer::ReadPL(const char *Playlist)
136{
137 ifstream f;
138 PLEntry *last_entry = NULL;
139 m_Entries = 0;
140
141 f.open(Playlist);
142 if (!f.good()) {
143 LOGERROR("mediaplayer: %s: open PL %s failed", __FUNCTION__, Playlist);
144 return;
145 }
146
147 while (!f.eof()) {
148 string s;
149 getline(f, s);
150 if (s.size() && s.compare(0, 1, "#")) {
151 PLEntry *entry = new PLEntry;
152 entry->NextEntry = NULL;
153
154 entry->Path = s;
155 entry->File = entry->Path.substr(entry->Path.find_last_of("/") +1, string::npos);
156
157 string SubString = entry->Path.substr(0, entry->Path.find_last_of("/"));
158 entry->SubFolder = SubString.substr(SubString.find_last_of("/") +1, string::npos);
159
160 string FolderString = entry->Path.substr(0, SubString.find_last_of("/"));
161 entry->Folder = FolderString.substr(FolderString.find_last_of("/") +1, string::npos);
162
163 if (!last_entry) {
164 FirstEntry = entry;
165 } else {
166 last_entry->NextEntry = entry;
167 }
168 last_entry = entry;
169 m_Entries++;
170 }
171 }
172
173 f.close();
174}
175
177{
178 PLEntry *entry;
179 entry = FirstEntry;
180
181 for(int i = 0; i < index ; i++) {
182 entry = entry->NextEntry;
183 }
184 CurrentEntry = entry;
185 NoModify = 1;
186 StopPlay = 1;
187}
188
189void cSoftHdPlayer::Player(const char *url)
190{
191#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(59,0,100)
192 AVCodec *video_codec;
193#else
194 const AVCodec *video_codec;
195#endif
196 int err = 0;
197 int audio_stream_index = 0;
198 int video_stream_index;
199 int jump_stream_index = 0;
200 int start_time;
201
202 StopPlay = 0;
203 Jump = 0;
204
205 AVFormatContext *format = avformat_alloc_context();
206 if (avformat_open_input(&format, url, NULL, NULL) != 0) {
207 LOGERROR("mediaplayer: %s: Could not open file '%s'", __FUNCTION__, url);
208 return;
209 }
210#ifdef MEDIA_DEBUG
211 av_dump_format(format, -1, url, 0);
212#endif
213 if (avformat_find_stream_info(format, NULL) < 0) {
214 LOGERROR("mediaplayer: %s: Could not retrieve stream info from file '%s'", __FUNCTION__, url);
215 return;
216 }
217
218 for (unsigned int i = 0; i < format->nb_streams; i++) {
219 if (format->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
220 m_pDevice->SetAudioCodec(format->streams[i]->codecpar->codec_id,
221 format->streams[i]->codecpar, format->streams[i]->time_base);
222 audio_stream_index = jump_stream_index = i;
223 break;
224 }
225 }
226
227 video_stream_index = av_find_best_stream(format, AVMEDIA_TYPE_VIDEO,
228 -1, -1, &video_codec, 0);
229
230 if (video_stream_index < 0) {
231 LOGDEBUG2(L_MEDIA, "mediaplayer: %s: stream does not seem to contain video", __FUNCTION__);
232 } else {
233 m_pDevice->SetVideoCodec(video_codec->id,
234 format->streams[video_stream_index]->codecpar,
235 format->streams[video_stream_index]->time_base);
236 jump_stream_index = video_stream_index;
237 }
238
239 Duration = format->duration / AV_TIME_BASE;
240 start_time = format->start_time / AV_TIME_BASE;
241
242 AVPacket *packet = nullptr;
243 while (!StopPlay) {
244 if (!packet) {
245 packet = av_packet_alloc();
246 if (!packet) {
247 LOGFATAL("mediaplayer: %s: out of memory", __FUNCTION__);
248 return;
249 }
250
251 err = av_read_frame(format, packet);
252 if (err < 0) {
253 LOGDEBUG2(L_MEDIA, "mediaplayer: %s: av_read_frame error: %s", __FUNCTION__,
254 av_err2str(err));
255 StopPlay = 1;
256 av_packet_free(&packet);
257 break;
258 }
259 }
260
261 if (audio_stream_index == packet->stream_index) {
262 if (!m_pDevice->PlayAudioPkts(packet)) {
263 usleep(packet->duration * AV_TIME_BASE *
264 av_q2d(format->streams[audio_stream_index]->time_base));
265 } else {
266 CurrentTime = m_pAudio->GetHardwareOutputPtsMs() / 1000 - start_time;
267 av_packet_free(&packet);
268 packet = nullptr;
269 }
270 } else if (video_stream_index == packet->stream_index) {
271 if (!m_pDevice->PlayVideoPkts(packet)) {
272 usleep(packet->duration * AV_TIME_BASE *
273 av_q2d(format->streams[video_stream_index]->time_base));
274 } else {
275 packet = nullptr;
276 }
277 } else {
278 av_packet_free(&packet);
279 packet = nullptr;
280 }
281
282 while (Pause && !StopPlay)
283 sleep(1);
284
285 if (Jump && format->pb->seekable) {
286 av_seek_frame(format, format->streams[jump_stream_index]->index,
287 packet->pts + (int64_t)(Jump / // - BufferOffset
288 av_q2d(format->streams[jump_stream_index]->time_base)), 0);
289 m_pDevice->Clear();
290 Jump = 0;
291
292 if (packet) {
293 av_packet_free(&packet);
294 packet = nullptr;
295 }
296 }
297
298 if (StopPlay) {
299 m_pDevice->Clear();
300 break;
301 }
302 }
303
304 if (packet)
305 av_packet_free(&packet);
306
307 Duration = 0;
308 CurrentTime = 0;
309
310 avformat_close_input(&format);
311 avformat_free_context(format);
312}
313
314const char * cSoftHdPlayer::GetTitle(void)
315{
316 if (CurrentEntry)
317 return CurrentEntry->Path.c_str();
318
319 return m_pSource;
320}
321
322/*****************************************************************************
323 * cSoftHdControl (cControl mediaplayer)
324 ****************************************************************************/
325
328
333:cControl(m_pPlayer = new cSoftHdPlayer(url, device))
334{
335// LOGDEBUG2(L_MEDIA, "cSoftHdControl: Player gestartet.");
336 m_pControl = this;
337 Close = false;
338 m_pOsd = NULL;
339 m_pDevice = device;
340}
341
346{
347 delete m_pPlayer;
348 m_pPlayer = NULL;
349 m_pControl = NULL;
350 LOGDEBUG2(L_MEDIA, "mediaplayer: %s: Player beendet.", __FUNCTION__);
351}
352
354{
355 LOGDEBUG2(L_MEDIA, "mediaplayer: %s:", __FUNCTION__);
356 if (m_pOsd) {
357 delete m_pOsd;
358 m_pOsd = NULL;
359 }
360}
361
363{
364 if (!m_pOsd) {
365 LOGDEBUG2(L_MEDIA, "mediaplayer: %s: get OSD", __FUNCTION__);
366 m_pOsd = Skins.Current()->DisplayReplay(false);
367 }
368
369 m_pOsd->SetTitle(m_pPlayer->GetTitle());
371 m_pOsd->SetCurrent(IndexToHMSF(m_pPlayer->CurrentTime, false, 1));
372 m_pOsd->SetTotal(IndexToHMSF(m_pPlayer->Duration, false, 1));
373
374 Skins.Flush();
375}
376
382eOSState cSoftHdControl::ProcessKey(eKeys key)
383{
384 switch (key) {
385 case kNone:
386 if (m_pOsd)
387 ShowProgress();
388 if (Close) {
389 Hide();
390 return osStopReplay;
391 }
392 break;
393
394 case kOk:
395 if (m_pOsd) {
396 Hide();
397 } else {
398 ShowProgress();
399 }
400 break;
401
402 case kPlay:
403 if (m_pPlayer->Pause) {
404 m_pPlayer->Pause = 0;
405 m_pDevice->Play();
406 }
407 break;
408
409 case kGreen:
410 m_pPlayer->Jump = -60;
411 break;
412
413 case kYellow:
414 m_pPlayer->Jump = 60;
415 break;
416
417 case kBlue:
418 Hide();
419 m_pPlayer->StopPlay = 1;
420 return osStopReplay;
421
422 case kPause:
423 if (m_pPlayer->Pause) {
424 m_pPlayer->Pause = 0;
425 m_pDevice->Play();
426 } else {
427 m_pPlayer->Pause = 1;
428 m_pDevice->Freeze();
429 }
430 break;
431
432 case kNext:
433 m_pPlayer->StopPlay = 1;
434 break;
435
436 default:
437 break;
438 }
439
440 return osContinue;
441}
Audio and alsa module header file.
int64_t GetHardwareOutputPtsMs(void)
Get the hardware output PTS in milliseconds.
Definition: audio.cpp:884
virtual eOSState ProcessKey(eKeys)
Handle a key event.
cSoftHdControl(const char *, cSoftHdDevice *)
Player control constructor.
static cSoftHdControl * Control()
Definition: mediaplayer.h:88
cSoftHdDevice * m_pDevice
Definition: mediaplayer.h:81
cSkinDisplayReplay * m_pOsd
Definition: mediaplayer.h:80
static cSoftHdPlayer * m_pPlayer
Definition: mediaplayer.h:79
static cSoftHdControl * m_pControl
Definition: mediaplayer.h:78
virtual void Hide(void)
virtual ~cSoftHdControl()
Player control destructor.
int PlayAudioPkts(AVPacket *)
Play an audio packet.
virtual void Clear(void)
Clears all video and audio data from the device.
void SetAudioCodec(enum AVCodecID, AVCodecParameters *, AVRational)
Open an audio codec.
virtual void Play(void)
Sets the device into play mode (after a previous trick mode, or pause)
int PlayVideoPkts(AVPacket *)
Play a video packet.
virtual void Freeze(void)
Puts the device into "freeze frame" mode.
void SetVideoCodec(enum AVCodecID, AVCodecParameters *, AVRational)
Open a video codec.
cSoftHdAudio * Audio(void)
Definition: softhddevice.h:177
void PlayListMenu(void)
Create playlist menu.
Definition: softhdmenu.cpp:319
static cSoftHdMenu * Menu()
Definition: softhdmenu.h:41
const char * GetTitle(void)
char * m_pSource
Definition: mediaplayer.h:45
virtual void Action(void)
virtual ~cSoftHdPlayer()
Definition: mediaplayer.cpp:78
void Player(const char *)
void ReadPL(const char *)
struct PLEntry * FirstEntry
Definition: mediaplayer.h:55
virtual void Activate(bool On)
Definition: mediaplayer.cpp:94
cSoftHdAudio * m_pAudio
Definition: mediaplayer.h:48
struct PLEntry * CurrentEntry
Definition: mediaplayer.h:56
cSoftHdDevice * m_pDevice
Definition: mediaplayer.h:47
cSoftHdPlayer(const char *, cSoftHdDevice *)
Definition: mediaplayer.cpp:59
void SetEntry(int)
Logger class header file.
#define LOGDEBUG2
Definition: logger.h:50
#define LOGERROR
Definition: logger.h:46
#define LOGFATAL
Logger macros.
Definition: logger.h:45
#define L_MEDIA
Definition: logger.h:66
Mediaplayer class header file.
Misc function header file.
#define AV_NOPTS_VALUE
Definition: misc.h:35
Device class header file.
Softhddevice menu class header file.
string Folder
Definition: mediaplayer.h:29
string Path
Definition: mediaplayer.h:27
string File
Definition: mediaplayer.h:28
string SubFolder
Definition: mediaplayer.h:30
struct PLEntry * NextEntry
Definition: mediaplayer.h:31
Videostream class header file.