From 826a826f823c2d068b7453e54dec25c9c127978a Mon Sep 17 00:00:00 2001 From: martii Date: Sat, 4 Aug 2012 13:31:28 +0200 Subject: [PATCH] libeplayer3: add support for teletext and dvbsubtitle streams Origin commit data ------------------ Branch: master Commit: https://github.com/neutrino-images/ni-libstb-hal/commit/92731e6fe370b37b49e6b566f1db66816b49c81d Author: martii Date: 2012-08-04 (Sat, 04 Aug 2012) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- Makefile.am | 3 + libeplayer3/Makefile.am | 3 +- libeplayer3/container/container_ffmpeg.c | 103 +++++ libeplayer3/include/container.h | 4 + libeplayer3/include/manager.h | 4 + libeplayer3/include/output.h | 10 + libeplayer3/include/playback.h | 6 +- libeplayer3/include/writer.h | 4 + libeplayer3/manager/audio.c | 8 +- libeplayer3/manager/dvbsubtitle.c | 259 +++++++++++++ libeplayer3/manager/manager.c | 8 + libeplayer3/manager/teletext.c | 259 +++++++++++++ libeplayer3/output/output.c | 82 ++++ libeplayer3/output/output_pipe.c | 454 +++++++++++++++++++++++ libeplayer3/playback/playback.c | 73 ++++ libspark/playback_libeplayer3.cpp | 68 ++++ libspark/playback_libeplayer3.h | 14 + 17 files changed, 1356 insertions(+), 6 deletions(-) create mode 100644 libeplayer3/manager/dvbsubtitle.c create mode 100644 libeplayer3/manager/teletext.c create mode 100644 libeplayer3/output/output_pipe.c diff --git a/Makefile.am b/Makefile.am index 0a9c765..b4e802d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -67,6 +67,9 @@ libstb_hal_a_LIBADD += \ libeplayer3/manager.o \ libeplayer3/subtitle.o \ libeplayer3/video.o \ + libeplayer3/output_pipe.o \ + libeplayer3/dvbsubtitle.o \ + libeplayer3/teletext.o \ libeplayer3/output_subtitle.o \ libeplayer3/linuxdvb.o \ libeplayer3/output.o \ diff --git a/libeplayer3/Makefile.am b/libeplayer3/Makefile.am index 3a1f167..72fd1c9 100644 --- a/libeplayer3/Makefile.am +++ b/libeplayer3/Makefile.am @@ -9,7 +9,8 @@ libeplayer3_a_SOURCES = \ container/container.c container/container_ffmpeg.c container/text_srt.c \ container/text_ssa.c container/container_ass.c \ manager/audio.c manager/manager.c manager/subtitle.c manager/video.c \ - output/output_subtitle.c output/linuxdvb.c output/output.c \ + manager/dvbsubtitle.c manager/teletext.c \ + output/output_subtitle.c output/linuxdvb.c output/output.c output/output_pipe.c \ playback/playback.c output/writer/writer.c output/writer/aac.c output/writer/wmv.c \ output/writer/ac3.c output/writer/divx.c output/writer/wma.c output/writer/pes.c \ output/writer/dts.c output/writer/mpeg2.c output/writer/mp3.c output/writer/misc.c \ diff --git a/libeplayer3/container/container_ffmpeg.c b/libeplayer3/container/container_ffmpeg.c index 9466d5b..6038ae3 100644 --- a/libeplayer3/container/container_ffmpeg.c +++ b/libeplayer3/container/container_ffmpeg.c @@ -102,7 +102,11 @@ static AVFormatContext* avContext = NULL; static unsigned char isContainerRunning = 0; +#ifdef MARTII +long long int latestPts = 0; +#else static long long int latestPts = 0; +#endif /* ***************************** */ /* Prototypes */ @@ -324,6 +328,9 @@ static void FFMPEGThread(Context_t *context) { off_t lastReverseSeek = 0; /* max address to read before seek again in reverse play */ off_t lastSeek = -1; long long int lastPts = -1, currentVideoPts = -1, currentAudioPts = -1, showtime = 0, bofcount = 0; +#ifdef MARTII + long long int currentDvbsubtitlePts = -1, currentTeletextPts = -1; +#endif int err = 0, gotlastPts = 0, audioMute = 0; AudioVideoOut_t avOut; @@ -482,6 +489,10 @@ if(!context->playback->BackWard && audioMute) Track_t * videoTrack = NULL; Track_t * audioTrack = NULL; Track_t * subtitleTrack = NULL; +#ifdef MARTII + Track_t * dvbsubtitleTrack = NULL; + Track_t * teletextTrack = NULL; +#endif int index = packet.stream_index; @@ -499,6 +510,13 @@ if(!context->playback->BackWard && audioMute) if (context->manager->subtitle->Command(context, MANAGER_GET_TRACK, &subtitleTrack) < 0) ffmpeg_err("error getting subtitle track\n"); +#ifdef MARTII + if (context->manager->dvbsubtitle->Command(context, MANAGER_GET_TRACK, &dvbsubtitleTrack) < 0) + ffmpeg_err("error getting dvb subtitle track\n"); + + if (context->manager->teletext->Command(context, MANAGER_GET_TRACK, &teletextTrack) < 0) + ffmpeg_err("error getting teletext track\n"); +#endif ffmpeg_printf(200, "packet.size %d - index %d\n", packet.size, index); @@ -762,6 +780,54 @@ if(!context->playback->BackWard && audioMute) } /* duration */ } } +#ifdef MARTII + if (dvbsubtitleTrack != NULL) { + if (dvbsubtitleTrack->Id == index) { + currentDvbsubtitlePts = dvbsubtitleTrack->pts = pts = calcPts(dvbsubtitleTrack->stream, &packet); + + ffmpeg_printf(200, "DvbSubTitle index = %d\n",index); + + avOut.data = packet.data; + avOut.len = packet.size; + avOut.pts = pts; + avOut.extradata = NULL; + avOut.extralen = 0; + avOut.frameRate = 0; + avOut.timeScale = 0; + avOut.width = 0; + avOut.height = 0; + avOut.type = "dvbsubtitle"; + + if (context->output->dvbsubtitle->Write(context, &avOut) < 0) + { + //ffmpeg_err("writing data to dvbsubtitle fifo failed\n"); + } + } + } + if (teletextTrack != NULL) { + if (teletextTrack->Id == index) { + currentTeletextPts = teletextTrack->pts = pts = calcPts(teletextTrack->stream, &packet); + + ffmpeg_printf(200, "TeleText index = %d\n",index); + + avOut.data = packet.data; + avOut.len = packet.size; + avOut.pts = pts; + avOut.extradata = NULL; + avOut.extralen = 0; + avOut.frameRate = 0; + avOut.timeScale = 0; + avOut.width = 0; + avOut.height = 0; + avOut.type = "teletext"; + + if (context->output->teletext->Write(context, &avOut) < 0) + { + //ffmpeg_err("writing data to teletext fifo failed\n"); + } + } + } +#endif if (packet.data) av_free_packet(&packet); @@ -846,8 +912,13 @@ int container_ffmpeg_init(Context_t *context, char * filename) ffmpeg_printf(20, "find_streaminfo\n"); +#if LIBAVCODEC_VERSION_MAJOR < 54 if (av_find_stream_info(avContext) < 0) { + ffmpeg_err("Error avformat_find_stream_info\n"); +#else + if (avformat_find_stream_info(avContext, NULL) < 0) { ffmpeg_err("Error av_find_stream_info\n"); +#endif #ifdef this_is_ok /* crow reports that sometimes this returns an error * but the file is played back well. so remove this @@ -1199,6 +1270,17 @@ int container_ffmpeg_init(Context_t *context, char * filename) if (track.Name) ffmpeg_printf(10, "FOUND SUBTITLE %s\n", track.Name); +#ifdef MARTII + if (stream->codec->codec_id == CODEC_ID_DVB_TELETEXT && context->manager->teletext) { + if (context->manager->teletext->Command(context, MANAGER_ADD, &track) < 0) { + ffmpeg_err("failed to add teletext track %d\n", n); + } + } else if (stream->codec->codec_id == CODEC_ID_DVB_SUBTITLE && context->manager->dvbsubtitle) { + if (context->manager->dvbsubtitle->Command(context, MANAGER_ADD, &track) < 0) { + ffmpeg_err("failed to add dvbsubtitle track %d\n", n); + } + } else +#endif if (context->manager->subtitle) if (context->manager->subtitle->Command(context, MANAGER_ADD, &track) < 0) { @@ -1693,6 +1775,17 @@ static int container_ffmpeg_swich_subtitle(Context_t* context, int* arg) /* Hellmaster1024: nothing to do here!*/ return cERR_CONTAINER_FFMPEG_NO_ERROR; } +#ifdef MARTII +static int container_ffmpeg_switch_dvbsubtitle(Context_t* context, int* arg) +{ + return cERR_CONTAINER_FFMPEG_NO_ERROR; +} + +static int container_ffmpeg_switch_teletext(Context_t* context, int* arg) +{ + return cERR_CONTAINER_FFMPEG_NO_ERROR; +} +#endif /* konfetti comment: I dont like the mechanism of overwriting * the pointer in infostring. This lead in most cases to @@ -1822,6 +1915,16 @@ static int Command(void *_context, ContainerCmd_t command, void * argument) *((long long int*)argument) = latestPts; break; } +#ifdef MARTII + case CONTAINER_SWITCH_DVBSUBTITLE: { + ret = container_ffmpeg_switch_dvbsubtitle(context, (int*) argument); + break; + } + case CONTAINER_SWITCH_TELETEXT: { + ret = container_ffmpeg_switch_teletext(context, (int*) argument); + break; + } +#endif default: ffmpeg_err("ContainerCmd %d not supported!\n", command); ret = cERR_CONTAINER_FFMPEG_ERR; diff --git a/libeplayer3/include/container.h b/libeplayer3/include/container.h index 958440c..4d05508 100644 --- a/libeplayer3/include/container.h +++ b/libeplayer3/include/container.h @@ -17,6 +17,10 @@ CONTAINER_LENGTH, CONTAINER_DEL, CONTAINER_SWITCH_AUDIO, CONTAINER_SWITCH_SUBTITLE, +#ifdef MARTII +CONTAINER_SWITCH_DVBSUBTITLE, +CONTAINER_SWITCH_TELETEXT, +#endif CONTAINER_INFO, CONTAINER_STATUS, CONTAINER_LAST_PTS, diff --git a/libeplayer3/include/manager.h b/libeplayer3/include/manager.h index 79bc684..9f80c73 100644 --- a/libeplayer3/include/manager.h +++ b/libeplayer3/include/manager.h @@ -69,6 +69,10 @@ typedef struct ManagerHandler_s { Manager_t * audio; Manager_t * video; Manager_t * subtitle; +#ifdef MARTII + Manager_t * dvbsubtitle; + Manager_t * teletext; +#endif } ManagerHandler_t; void freeTrack(Track_t* track); diff --git a/libeplayer3/include/output.h b/libeplayer3/include/output.h index a0998bc..25d39dc 100644 --- a/libeplayer3/include/output.h +++ b/libeplayer3/include/output.h @@ -61,10 +61,16 @@ typedef struct Output_s { extern Output_t LinuxDvbOutput; extern Output_t SubtitleOutput; +#ifdef MARTII +extern Output_t PipeOutput; +#endif static Output_t * AvailableOutput[] = { &LinuxDvbOutput, &SubtitleOutput, +#ifdef MARTII + &PipeOutput, +#endif NULL }; @@ -73,6 +79,10 @@ typedef struct OutputHandler_s { Output_t * audio; Output_t * video; Output_t * subtitle; +#ifdef MARTII + Output_t * dvbsubtitle; + Output_t * teletext; +#endif int (* Command) (/*Context_t*/void *, OutputCmd_t, void *); } OutputHandler_t; diff --git a/libeplayer3/include/playback.h b/libeplayer3/include/playback.h index 3c44ccb..3b396af 100644 --- a/libeplayer3/include/playback.h +++ b/libeplayer3/include/playback.h @@ -3,7 +3,7 @@ #include #ifdef MARTII -typedef enum {PLAYBACK_OPEN, PLAYBACK_CLOSE, PLAYBACK_PLAY, PLAYBACK_STOP, PLAYBACK_PAUSE, PLAYBACK_CONTINUE, PLAYBACK_FLUSH, PLAYBACK_TERM, PLAYBACK_FASTFORWARD, PLAYBACK_SEEK, PLAYBACK_SEEK_ABS, PLAYBACK_PTS, PLAYBACK_LENGTH, PLAYBACK_SWITCH_AUDIO, PLAYBACK_SWITCH_SUBTITLE, PLAYBACK_INFO, PLAYBACK_SLOWMOTION, PLAYBACK_FASTBACKWARD, PLAYBACK_GET_FRAME_COUNT} PlaybackCmd_t; +typedef enum {PLAYBACK_OPEN, PLAYBACK_CLOSE, PLAYBACK_PLAY, PLAYBACK_STOP, PLAYBACK_PAUSE, PLAYBACK_CONTINUE, PLAYBACK_FLUSH, PLAYBACK_TERM, PLAYBACK_FASTFORWARD, PLAYBACK_SEEK, PLAYBACK_SEEK_ABS, PLAYBACK_PTS, PLAYBACK_LENGTH, PLAYBACK_SWITCH_AUDIO, PLAYBACK_SWITCH_SUBTITLE, PLAYBACK_INFO, PLAYBACK_SLOWMOTION, PLAYBACK_FASTBACKWARD, PLAYBACK_GET_FRAME_COUNT, PLAYBACK_SWITCH_TELETEXT, PLAYBACK_SWITCH_DVBSUBTITLE} PlaybackCmd_t; #else typedef enum {PLAYBACK_OPEN, PLAYBACK_CLOSE, PLAYBACK_PLAY, PLAYBACK_STOP, PLAYBACK_PAUSE, PLAYBACK_CONTINUE, PLAYBACK_FLUSH, PLAYBACK_TERM, PLAYBACK_FASTFORWARD, PLAYBACK_SEEK, PLAYBACK_PTS, PLAYBACK_LENGTH, PLAYBACK_SWITCH_AUDIO, PLAYBACK_SWITCH_SUBTITLE, PLAYBACK_INFO, PLAYBACK_SLOWMOTION, PLAYBACK_FASTBACKWARD, PLAYBACK_GET_FRAME_COUNT} PlaybackCmd_t; #endif @@ -31,6 +31,10 @@ typedef struct PlaybackHandler_s { unsigned char isVideo; unsigned char isAudio; unsigned char isSubtitle; +#ifdef MARTII + unsigned char isDvbSubtitle; + unsigned char isTeletext; +#endif int (* Command) (/*Context_t*/void *, PlaybackCmd_t, void *); char * uri; diff --git a/libeplayer3/include/writer.h b/libeplayer3/include/writer.h index 47b2c23..6e5eb61 100644 --- a/libeplayer3/include/writer.h +++ b/libeplayer3/include/writer.h @@ -73,6 +73,10 @@ extern Writer_t WriterVideoH263; extern Writer_t WriterVideoFLV; extern Writer_t WriterVideoVC1; extern Writer_t WriterFramebuffer; +#ifdef MARTII +extern Writer_t WriterPipe; +extern Writer_t WriterDVBSubtitle; +#endif static Writer_t * AvailableWriter[] = { &WriterAudioIPCM, diff --git a/libeplayer3/manager/audio.c b/libeplayer3/manager/audio.c index 3305985..8cc5dc2 100644 --- a/libeplayer3/manager/audio.c +++ b/libeplayer3/manager/audio.c @@ -24,9 +24,9 @@ #include #include -// >>> MARTII +#ifdef MARTII #include -// <<< MARTII +#endif #include "manager.h" #include "common.h" @@ -217,7 +217,7 @@ static int Command(void *_context, ManagerCmd_t command, void * argument) { case MANAGER_SET: { int id = *((int*)argument); -// >>> MARTII +#ifdef MARTII // What's the argument supposed to be? apid or local index? --martii if (id >= TrackCount) { @@ -227,7 +227,7 @@ static int Command(void *_context, ManagerCmd_t command, void * argument) { break; } } -// <<< MARTII +#endif audio_mgr_printf(20, "%s::%s MANAGER_SET id=%d\n", FILENAME, __FUNCTION__, id); if (id < TrackCount) diff --git a/libeplayer3/manager/dvbsubtitle.c b/libeplayer3/manager/dvbsubtitle.c new file mode 100644 index 0000000..aa2c453 --- /dev/null +++ b/libeplayer3/manager/dvbsubtitle.c @@ -0,0 +1,259 @@ +#ifdef MARTII +/* + * dvbsubtitle manager handling. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* ***************************** */ +/* Includes */ +/* ***************************** */ + +#include +#include + +#include +#include "manager.h" +#include "common.h" + +/* ***************************** */ +/* Makros/Constants */ +/* ***************************** */ +#define TRACKWRAP 20 + +#define DVBSUBTITLE_MGR_DEBUG + +#ifdef DVBSUBTITLE_MGR_DEBUG + +static short debug_level = 0; + +#define dvbsubtitle_mgr_printf(level, x...) do { \ +if (debug_level >= level) printf(x); } while (0) +#else +#define dvbsubtitle_mgr_printf(level, x...) +#endif + +#ifndef DVBSUBTITLE_MGR_SILENT +#define dvbsubtitle_mgr_err(x...) do { printf(x); } while (0) +#else +#define dvbsubtitle_mgr_err(x...) +#endif + +/* Error Constants */ +#define cERR_DVBSUBTITLE_MGR_NO_ERROR 0 +#define cERR_DVBSUBTITLE_MGR_ERROR -1 + +static const char FILENAME[] = __FILE__; + +/* ***************************** */ +/* Types */ +/* ***************************** */ + +/* ***************************** */ +/* Varaibles */ +/* ***************************** */ + +static Track_t * Tracks; +static int TrackCount = 0; +static int CurrentTrack = -1; + +/* ***************************** */ +/* Prototypes */ +/* ***************************** */ + +/* ***************************** */ +/* Functions */ +/* ***************************** */ + +static int ManagerAdd(Context_t *context, Track_t track) { + + dvbsubtitle_mgr_printf(10, "%s::%s name=\"%s\" encoding=\"%s\" id=%d\n", FILENAME, __FUNCTION__, track.Name, track.Encoding, track.Id); + + if (Tracks == NULL) { + Tracks = malloc(sizeof(Track_t) * TRACKWRAP); + } + + if (Tracks == NULL) + { + dvbsubtitle_mgr_err("%s:%s malloc failed\n", FILENAME, __FUNCTION__); + return cERR_DVBSUBTITLE_MGR_ERROR; + } + + if (TrackCount < TRACKWRAP) { + copyTrack(&Tracks[TrackCount], &track); + TrackCount++; + } else { + dvbsubtitle_mgr_err("%s:%s TrackCount out if range %d - %d\n", FILENAME, __FUNCTION__, TrackCount, TRACKWRAP); + return cERR_DVBSUBTITLE_MGR_ERROR; + } + + if (TrackCount > 0) + context->playback->isDvbSubtitle = 1; + + dvbsubtitle_mgr_printf(10, "%s::%s\n", FILENAME, __FUNCTION__); + + return cERR_DVBSUBTITLE_MGR_NO_ERROR; +} + +static char ** ManagerList(Context_t *context) { + int i = 0, j = 0; + char ** tracklist = NULL; + + dvbsubtitle_mgr_printf(10, "%s::%s\n", FILENAME, __FUNCTION__); + + if (Tracks != NULL) { + + tracklist = malloc(sizeof(char *) * ((TrackCount*2) + 1)); + + if (tracklist == NULL) + { + dvbsubtitle_mgr_err("%s:%s malloc failed\n", FILENAME, __FUNCTION__); + return NULL; + } + + for (i = 0, j = 0; i < TrackCount; i++, j+=2) { + tracklist[j] = strdup(Tracks[i].Name); + tracklist[j+1] = strdup(Tracks[i].Encoding); + } + tracklist[j] = NULL; + } + + dvbsubtitle_mgr_printf(10, "%s::%s return %p (%d - %d)\n", FILENAME, __FUNCTION__, tracklist, j, TrackCount); + + return tracklist; +} + +static int ManagerDel(Context_t * context) { + + int i = 0; + + dvbsubtitle_mgr_printf(10, "%s::%s\n", FILENAME, __FUNCTION__); + + if(Tracks != NULL) { + for (i = 0; i < TrackCount; i++) { + freeTrack(&Tracks[i]); + } + free(Tracks); + Tracks = NULL; + } else + { + dvbsubtitle_mgr_err("%s::%s nothing to delete!\n", FILENAME, __FUNCTION__); + return cERR_DVBSUBTITLE_MGR_ERROR; + } + + TrackCount = 0; + CurrentTrack = -1; + context->playback->isDvbSubtitle = 0; + + dvbsubtitle_mgr_printf(10, "%s::%s return no error\n", FILENAME, __FUNCTION__); + + return cERR_DVBSUBTITLE_MGR_NO_ERROR; +} + + +static int Command(void *_context, ManagerCmd_t command, void * argument) { + Context_t *context = (Context_t*) _context; + int ret = cERR_DVBSUBTITLE_MGR_NO_ERROR; + + dvbsubtitle_mgr_printf(10, "%s::%s\n", FILENAME, __FUNCTION__); + + switch(command) { + case MANAGER_ADD: { + Track_t * track = argument; + + ret = ManagerAdd(context, *track); + break; + } + case MANAGER_LIST: { + *((char***)argument) = (char **)ManagerList(context); + break; + } + case MANAGER_GET: { + dvbsubtitle_mgr_printf(20, "%s::%s MANAGER_GET\n", FILENAME, __FUNCTION__); + + if ((TrackCount > 0) && (CurrentTrack >=0)) + *((int*)argument) = (int)Tracks[CurrentTrack].Id; + else + *((int*)argument) = (int)-1; + break; + } + case MANAGER_GET_TRACK: { + dvbsubtitle_mgr_printf(20, "%s::%s MANAGER_GET_TRACK\n", FILENAME, __FUNCTION__); + + if ((TrackCount > 0) && (CurrentTrack >=0)) + *((Track_t**)argument) = (Track_t*) &Tracks[CurrentTrack]; + else + *((Track_t**)argument) = NULL; + break; + } + case MANAGER_GETENCODING: { + if ((TrackCount > 0) && (CurrentTrack >=0)) + *((char**)argument) = (char *)strdup(Tracks[CurrentTrack].Encoding); + else + *((char**)argument) = (char *)strdup(""); + break; + } + case MANAGER_GETNAME: { + if ((TrackCount > 0) && (CurrentTrack >=0)) + *((char**)argument) = (char *)strdup(Tracks[CurrentTrack].Name); + else + *((char**)argument) = (char *)strdup(""); + break; + } + case MANAGER_SET: { + int id = *((int*)argument); + + dvbsubtitle_mgr_printf(20, "%s::%s MANAGER_SET id=%d\n", FILENAME, __FUNCTION__, id); + + if (id >= TrackCount) { + int mypid = id; + for (id = 0; id < TrackCount; id++) { + if (((AVStream *) (Tracks[id].stream))->id == mypid) + break; + } + } + + if (id < TrackCount) + CurrentTrack = id; + else + { + dvbsubtitle_mgr_err("%s::%s track id out of range (%d - %d)\n", FILENAME, __FUNCTION__, id, TrackCount); + ret = cERR_DVBSUBTITLE_MGR_ERROR; + } + break; + } + case MANAGER_DEL: { + ret = ManagerDel(context); + break; + } + default: + dvbsubtitle_mgr_err("%s::%s ContainerCmd %d not supported!\n", FILENAME, __FUNCTION__, command); + ret = cERR_DVBSUBTITLE_MGR_ERROR; + break; + } + + dvbsubtitle_mgr_printf(10, "%s:%s: returning %d\n", FILENAME, __FUNCTION__,ret); + + return ret; +} + + +struct Manager_s DvbSubtitleManager = { + "DvbSubtitle", + &Command, + NULL +}; +#endif diff --git a/libeplayer3/manager/manager.c b/libeplayer3/manager/manager.c index f4b892a..3aa76ed 100644 --- a/libeplayer3/manager/manager.c +++ b/libeplayer3/manager/manager.c @@ -40,12 +40,20 @@ extern Manager_t AudioManager; extern Manager_t VideoManager; extern Manager_t SubtitleManager; +#ifdef MARTII +extern Manager_t DvbSubtitleManager; +extern Manager_t TeletextManager; +#endif ManagerHandler_t ManagerHandler = { "ManagerHandler", &AudioManager, &VideoManager, &SubtitleManager +#ifdef MARTII + , &DvbSubtitleManager + , &TeletextManager +#endif }; /* ***************************** */ diff --git a/libeplayer3/manager/teletext.c b/libeplayer3/manager/teletext.c new file mode 100644 index 0000000..33ceb0f --- /dev/null +++ b/libeplayer3/manager/teletext.c @@ -0,0 +1,259 @@ +#ifdef MARTII +/* + * teletext manager handling. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* ***************************** */ +/* Includes */ +/* ***************************** */ + +#include +#include + +#include +#include "manager.h" +#include "common.h" + +/* ***************************** */ +/* Makros/Constants */ +/* ***************************** */ +#define TRACKWRAP 20 + +#define TELETEXT_MGR_DEBUG + +#ifdef TELETEXT_MGR_DEBUG + +static short debug_level = 0; + +#define teletext_mgr_printf(level, x...) do { \ +if (debug_level >= level) printf(x); } while (0) +#else +#define teletext_mgr_printf(level, x...) +#endif + +#ifndef TELETEXT_MGR_SILENT +#define teletext_mgr_err(x...) do { printf(x); } while (0) +#else +#define teletext_mgr_err(x...) +#endif + +/* Error Constants */ +#define cERR_TELETEXT_MGR_NO_ERROR 0 +#define cERR_TELETEXT_MGR_ERROR -1 + +static const char FILENAME[] = __FILE__; + +/* ***************************** */ +/* Types */ +/* ***************************** */ + +/* ***************************** */ +/* Varaibles */ +/* ***************************** */ + +static Track_t * Tracks; +static int TrackCount = 0; +static int CurrentTrack = -1; + +/* ***************************** */ +/* Prototypes */ +/* ***************************** */ + +/* ***************************** */ +/* Functions */ +/* ***************************** */ + +static int ManagerAdd(Context_t *context, Track_t track) { + + teletext_mgr_printf(10, "%s::%s name=\"%s\" encoding=\"%s\" id=%d\n", FILENAME, __FUNCTION__, track.Name, track.Encoding, track.Id); + + if (Tracks == NULL) { + Tracks = malloc(sizeof(Track_t) * TRACKWRAP); + } + + if (Tracks == NULL) + { + teletext_mgr_err("%s:%s malloc failed\n", FILENAME, __FUNCTION__); + return cERR_TELETEXT_MGR_ERROR; + } + + if (TrackCount < TRACKWRAP) { + copyTrack(&Tracks[TrackCount], &track); + TrackCount++; + } else { + teletext_mgr_err("%s:%s TrackCount out if range %d - %d\n", FILENAME, __FUNCTION__, TrackCount, TRACKWRAP); + return cERR_TELETEXT_MGR_ERROR; + } + + if (TrackCount > 0) + context->playback->isTeletext = 1; + + teletext_mgr_printf(10, "%s::%s\n", FILENAME, __FUNCTION__); + + return cERR_TELETEXT_MGR_NO_ERROR; +} + +static char ** ManagerList(Context_t *context) { + int i = 0, j = 0; + char ** tracklist = NULL; + + teletext_mgr_printf(10, "%s::%s\n", FILENAME, __FUNCTION__); + + if (Tracks != NULL) { + + tracklist = malloc(sizeof(char *) * ((TrackCount*2) + 1)); + + if (tracklist == NULL) + { + teletext_mgr_err("%s:%s malloc failed\n", FILENAME, __FUNCTION__); + return NULL; + } + + for (i = 0, j = 0; i < TrackCount; i++, j+=2) { + tracklist[j] = strdup(Tracks[i].Name); + tracklist[j+1] = strdup(Tracks[i].Encoding); + } + tracklist[j] = NULL; + } + + teletext_mgr_printf(10, "%s::%s return %p (%d - %d)\n", FILENAME, __FUNCTION__, tracklist, j, TrackCount); + + return tracklist; +} + +static int ManagerDel(Context_t * context) { + + int i = 0; + + teletext_mgr_printf(10, "%s::%s\n", FILENAME, __FUNCTION__); + + if(Tracks != NULL) { + for (i = 0; i < TrackCount; i++) { + freeTrack(&Tracks[i]); + } + free(Tracks); + Tracks = NULL; + } else + { + teletext_mgr_err("%s::%s nothing to delete!\n", FILENAME, __FUNCTION__); + return cERR_TELETEXT_MGR_ERROR; + } + + TrackCount = 0; + CurrentTrack = -1; + context->playback->isTeletext = 0; + + teletext_mgr_printf(10, "%s::%s return no error\n", FILENAME, __FUNCTION__); + + return cERR_TELETEXT_MGR_NO_ERROR; +} + + +static int Command(void *_context, ManagerCmd_t command, void * argument) { + Context_t *context = (Context_t*) _context; + int ret = cERR_TELETEXT_MGR_NO_ERROR; + + teletext_mgr_printf(10, "%s::%s\n", FILENAME, __FUNCTION__); + + switch(command) { + case MANAGER_ADD: { + Track_t * track = argument; + + ret = ManagerAdd(context, *track); + break; + } + case MANAGER_LIST: { + *((char***)argument) = (char **)ManagerList(context); + break; + } + case MANAGER_GET: { + teletext_mgr_printf(20, "%s::%s MANAGER_GET\n", FILENAME, __FUNCTION__); + + if ((TrackCount > 0) && (CurrentTrack >=0)) + *((int*)argument) = (int)Tracks[CurrentTrack].Id; + else + *((int*)argument) = (int)-1; + break; + } + case MANAGER_GET_TRACK: { + teletext_mgr_printf(20, "%s::%s MANAGER_GET_TRACK\n", FILENAME, __FUNCTION__); + + if ((TrackCount > 0) && (CurrentTrack >=0)) + *((Track_t**)argument) = (Track_t*) &Tracks[CurrentTrack]; + else + *((Track_t**)argument) = NULL; + break; + } + case MANAGER_GETENCODING: { + if ((TrackCount > 0) && (CurrentTrack >=0)) + *((char**)argument) = (char *)strdup(Tracks[CurrentTrack].Encoding); + else + *((char**)argument) = (char *)strdup(""); + break; + } + case MANAGER_GETNAME: { + if ((TrackCount > 0) && (CurrentTrack >=0)) + *((char**)argument) = (char *)strdup(Tracks[CurrentTrack].Name); + else + *((char**)argument) = (char *)strdup(""); + break; + } + case MANAGER_SET: { + int id = *((int*)argument); + + teletext_mgr_printf(20, "%s::%s MANAGER_SET id=%d\n", FILENAME, __FUNCTION__, id); + + if (id >= TrackCount) { + int mypid = id; + for (id = 0; id < TrackCount; id++) { + if (((AVStream *) (Tracks[id].stream))->id == mypid) + break; + } + } + + if (id < TrackCount) + CurrentTrack = id; + else + { + teletext_mgr_err("%s::%s track id out of range (%d - %d)\n", FILENAME, __FUNCTION__, id, TrackCount); + ret = cERR_TELETEXT_MGR_ERROR; + } + break; + } + case MANAGER_DEL: { + ret = ManagerDel(context); + break; + } + default: + teletext_mgr_err("%s::%s ContainerCmd %d not supported!\n", FILENAME, __FUNCTION__, command); + ret = cERR_TELETEXT_MGR_ERROR; + break; + } + + teletext_mgr_printf(10, "%s:%s: returning %d\n", FILENAME, __FUNCTION__,ret); + + return ret; +} + + +struct Manager_s TeletextManager = { + "Teletext", + &Command, + NULL +}; +#endif diff --git a/libeplayer3/output/output.c b/libeplayer3/output/output.c index fc65653..58a4b44 100644 --- a/libeplayer3/output/output.c +++ b/libeplayer3/output/output.c @@ -37,8 +37,13 @@ static short debug_level = 0; +#ifdef MARTII +#define output_printf(level, x...) do { \ +if (debug_level >= level) fprintf(stderr, x); } while (0) +#else #define output_printf(level, x...) do { \ if (debug_level >= level) printf(x); } while (0) +#endif #else #define output_printf(level, x...) #endif @@ -97,6 +102,30 @@ static void OutputAdd(Context_t *context, char * port) { for (i = 0; AvailableOutput[i] != NULL; i++) for (j = 0; AvailableOutput[i]->Capabilities[j] != NULL; j++) +#ifdef MARTII + if (!strcmp(AvailableOutput[i]->Capabilities[j], port)) { + if (!strcmp("audio", port)) { + context->output->audio = AvailableOutput[i]; + return; + } + if (!strcmp("video", port)) { + context->output->video = AvailableOutput[i]; + return; + } + if (!strcmp("subtitle", port)) { + context->output->subtitle = AvailableOutput[i]; + return; + } + if (!strcmp("dvbsubtitle", port)) { + context->output->dvbsubtitle = AvailableOutput[i]; + return; + } + if (!strcmp("teletext", port)) { + context->output->teletext = AvailableOutput[i]; + return; + } + } +#else if (!strcmp(AvailableOutput[i]->Capabilities[j], port)) { if (!strcmp("audio", port)) context->output->audio = AvailableOutput[i]; @@ -106,6 +135,7 @@ static void OutputAdd(Context_t *context, char * port) { context->output->subtitle = AvailableOutput[i]; break; } +#endif } static void OutputDel(Context_t *context, char * port) { @@ -117,6 +147,12 @@ static void OutputDel(Context_t *context, char * port) { context->output->video = NULL; else if (!strcmp("subtitle", port)) context->output->subtitle = NULL; +#ifdef MARTII + else if (!strcmp("dvbsubtitle", port)) + context->output->dvbsubtitle = NULL; + else if (!strcmp("teletext", port)) + context->output->teletext = NULL; +#endif } @@ -135,6 +171,12 @@ static int Command(void *_context, OutputCmd_t command, void * argument) { ret |= context->output->audio->Command(context, OUTPUT_OPEN, "audio"); if (context->playback->isSubtitle) ret |= context->output->subtitle->Command(context, OUTPUT_OPEN, "subtitle"); +#ifdef MARTII + if (context->playback->isDvbSubtitle) + ret |= context->output->dvbsubtitle->Command(context, command, "dvbsubtitle"); + if (context->playback->isTeletext) + ret |= context->output->teletext->Command(context, command, "teletext"); +#endif } else ret = cERR_OUTPUT_INTERNAL_ERROR; break; @@ -147,6 +189,12 @@ static int Command(void *_context, OutputCmd_t command, void * argument) { ret |= context->output->audio->Command(context, OUTPUT_CLOSE, "audio"); if (context->playback->isSubtitle) ret |= context->output->subtitle->Command(context, OUTPUT_CLOSE, "subtitle"); +#ifdef MARTII + if (context->playback->isDvbSubtitle) + ret |= context->output->dvbsubtitle->Command(context, command, "dvbsubtitle"); + if (context->playback->isTeletext) + ret |= context->output->teletext->Command(context, command, "teletext"); +#endif } else ret = cERR_OUTPUT_INTERNAL_ERROR; break; @@ -176,6 +224,12 @@ static int Command(void *_context, OutputCmd_t command, void * argument) { if (context->playback->isSubtitle) ret = context->output->subtitle->Command(context, OUTPUT_PLAY, "subtitle"); } +#ifdef MARTII + if (context->playback->isDvbSubtitle) + ret |= context->output->dvbsubtitle->Command(context, command, "dvbsubtitle"); + if (context->playback->isTeletext) + ret |= context->output->teletext->Command(context, command, "teletext"); +#endif } } else ret = cERR_OUTPUT_INTERNAL_ERROR; @@ -189,6 +243,12 @@ static int Command(void *_context, OutputCmd_t command, void * argument) { ret |= context->output->audio->Command(context, OUTPUT_STOP, "audio"); if (context->playback->isSubtitle) ret |= context->output->subtitle->Command(context, OUTPUT_STOP, "subtitle"); +#ifdef MARTII + if (context->playback->isDvbSubtitle) + ret |= context->output->dvbsubtitle->Command(context, command, "dvbsubtitle"); + if (context->playback->isTeletext) + ret |= context->output->teletext->Command(context, command, "teletext"); +#endif } else ret = cERR_OUTPUT_INTERNAL_ERROR; break; @@ -247,6 +307,12 @@ static int Command(void *_context, OutputCmd_t command, void * argument) { ret |= context->output->audio->Command(context, OUTPUT_CONTINUE, "audio"); //if (context->playback->isSubtitle) // ret |= context->output->subtitle->Command(context, OUTPUT_CONTINUE, "subtitle"); +#ifdef MARTII + if (context->playback->isDvbSubtitle) + ret |= context->output->dvbsubtitle->Command(context, command, "dvbsubtitle"); + if (context->playback->isTeletext) + ret |= context->output->teletext->Command(context, command, "teletext"); +#endif } else ret = cERR_OUTPUT_INTERNAL_ERROR; break; @@ -267,6 +333,12 @@ static int Command(void *_context, OutputCmd_t command, void * argument) { ret |= context->output->audio->Command(context, OUTPUT_CLEAR, "audio"); //if (context->playback->isSubtitle && (argument == NULL || *(char *) argument == 's')) // ret |= context->output->subtitle->Command(context, OUTPUT_CLEAR, "subtitle"); +#ifdef MARTII + if (context->playback->isDvbSubtitle) + ret |= context->output->dvbsubtitle->Command(context, command, "dvbsubtitle"); + if (context->playback->isTeletext) + ret |= context->output->teletext->Command(context, command, "teletext"); +#endif } else ret = cERR_OUTPUT_INTERNAL_ERROR; break; @@ -289,6 +361,12 @@ static int Command(void *_context, OutputCmd_t command, void * argument) { return context->output->audio->Command(context, OUTPUT_SWITCH, "audio"); if (context->playback->isVideo) return context->output->video->Command(context, OUTPUT_SWITCH, "video"); +#ifdef MARTII + if (context->playback->isDvbSubtitle) + ret |= context->output->dvbsubtitle->Command(context, command, "dvbsubtitle"); + if (context->playback->isTeletext) + ret |= context->output->teletext->Command(context, command, "teletext"); +#endif } else ret = cERR_OUTPUT_INTERNAL_ERROR; break; @@ -349,5 +427,9 @@ OutputHandler_t OutputHandler = { NULL, NULL, NULL, +#ifdef MARTII + NULL, // dvbsubtitle + NULL, // teletext +#endif &Command }; diff --git a/libeplayer3/output/output_pipe.c b/libeplayer3/output/output_pipe.c new file mode 100644 index 0000000..cd9469d --- /dev/null +++ b/libeplayer3/output/output_pipe.c @@ -0,0 +1,454 @@ +#ifdef MARTII +/* + * Pipe Output handling. + * + * 2012 by martii + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* ***************************** */ +/* Includes */ +/* ***************************** */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "output.h" +#include "stm_ioctls.h" +#include "writer.h" +#include "misc.h" +#include "pes.h" + +/* ***************************** */ +/* Makros/Constants */ +/* ***************************** */ + +#define PIPE_DEBUG + +static short debug_level = 10; + +static const char FILENAME[] = __FILE__; + +#ifdef PIPE_DEBUG +#define pipe_printf(level, fmt, x...) do { \ +if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x ); } while (0) +#else +#define pipe_printf(x...) +#endif + +#ifndef PIPE_SILENT +#define pipe_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) +#else +#define pipe_err(x...) +#endif + +#define cERR_PIPE_NO_ERROR 0 +#define cERR_PIPE_ERROR -1 + +static const char TELETEXTPIPE[] = "/tmp/.eplayer3_teletext"; +static const char DVBSUBTITLEPIPE[] = "/tmp/.eplayer3_dvbsubtitle"; + +static int teletextfd = -1; +static int dvbsubtitlefd = -1; + +pthread_mutex_t Pipemutex; + +/* ***************************** */ +/* Prototypes */ +/* ***************************** */ +int PipeStop(Context_t *context, char * type); + +/* ***************************** */ +/* MISC Functions */ +/* ***************************** */ + +void getPipeMutex(const char *filename, const char *function, int line) { + + pipe_printf(250, "requesting mutex\n"); + + pthread_mutex_lock(&Pipemutex); + + pipe_printf(250, "received mutex\n"); +} + +void releasePipeMutex(const char *filename, const char *function, int line) { + pthread_mutex_unlock(&Pipemutex); + + pipe_printf(250, "released mutex\n"); + +} + +int PipeOpen(Context_t *context, char * type) { + unsigned char teletext = !strcmp("teletext", type); + unsigned char dvbsubtitle = !strcmp("dvbsubtitle", type); + + pipe_printf(10, "t%d d%d\n", teletext, dvbsubtitle); + + if (teletext && teletextfd == -1) { + mkfifo(TELETEXTPIPE, 0644); + teletextfd = open(TELETEXTPIPE, O_RDWR | O_NONBLOCK); + + if (teletextfd < 0) + { + pipe_err("failed to open %s - errno %d\n", TELETEXTPIPE, errno); + pipe_err("%s\n", strerror(errno)); + return cERR_PIPE_ERROR; + } + } + if (dvbsubtitle && dvbsubtitlefd == -1) { + mkfifo(DVBSUBTITLEPIPE, 0644); + dvbsubtitlefd = open(DVBSUBTITLEPIPE, O_RDWR | O_NONBLOCK); + + if (dvbsubtitlefd < 0) + { + pipe_err("failed to open %s - errno %d\n", DVBSUBTITLEPIPE, errno); + pipe_err("%s\n", strerror(errno)); + return cERR_PIPE_ERROR; + } + } + + return cERR_PIPE_NO_ERROR; +} + +int PipeClose(Context_t *context, char * type) { + unsigned char dvbsubtitle = !strcmp("dvbsubtitle", type); + unsigned char teletext = !strcmp("teletext", type); + + pipe_printf(10, "t%d d%d\n", teletext, dvbsubtitle); + + /* closing stand alone is not allowed, so prevent + * user from closing and dont call stop. stop will + * set default values for us (speed and so on). + */ + PipeStop(context, type); + + getPipeMutex(FILENAME, __FUNCTION__,__LINE__); + + if (dvbsubtitle && dvbsubtitlefd != -1) { + close(dvbsubtitlefd); + dvbsubtitlefd = -1; + } + if (teletext && teletextfd != -1) { + close(teletextfd); + teletextfd = -1; + } + + releasePipeMutex(FILENAME, __FUNCTION__,__LINE__); + return cERR_PIPE_NO_ERROR; +} + +int PipePlay(Context_t *context, char * type) { + int ret = cERR_PIPE_NO_ERROR; + Writer_t* writer; + + unsigned char dvbsubtitle = !strcmp("dvbsubtitle", type); + unsigned char teletext = !strcmp("teletext", type); + + pipe_printf(10, "t%d d%d\n", teletext, dvbsubtitle); + + if (dvbsubtitle && dvbsubtitlefd != -1) { + } + if (teletext && teletextfd != -1) { + } + + return ret; +} + +int PipeStop(Context_t *context, char * type) { + int ret = cERR_PIPE_NO_ERROR; + unsigned char dvbsubtitle = !strcmp("dvbsubtitle", type); + unsigned char teletext = !strcmp("teletext", type); + + pipe_printf(10, "t%d d%d\n", teletext, dvbsubtitle); + + getPipeMutex(FILENAME, __FUNCTION__,__LINE__); + + if (dvbsubtitle && dvbsubtitlefd != -1) { + } + if (teletext && teletextfd != -1) { + } + + releasePipeMutex(FILENAME, __FUNCTION__,__LINE__); + + return ret; +} + +int PipeFlush(Context_t *context, char * type) { + unsigned char dvbsubtitle = !strcmp("dvbsubtitle", type); + unsigned char teletext = !strcmp("teletext", type); + + pipe_printf(10, "t%d d%d\n", teletext, dvbsubtitle); + + if ( (dvbsubtitle && dvbsubtitlefd != -1) || (teletext && teletextfd != -1) ) { + getPipeMutex(FILENAME, __FUNCTION__,__LINE__); + + if (dvbsubtitle && dvbsubtitlefd != -1) { + char buf[65536]; + while(0 < read(dvbsubtitlefd, buf, sizeof(buf))); + } + if (teletext && teletextfd != -1) { + char buf[65536]; + while(0 < read(teletextfd, buf, sizeof(buf))); + } + + releasePipeMutex(FILENAME, __FUNCTION__,__LINE__); + } + + pipe_printf(10, "exiting\n"); + + return cERR_PIPE_NO_ERROR; +} + +int PipeClear(Context_t *context, char * type) { + int ret = cERR_PIPE_NO_ERROR; + unsigned char dvbsubtitle = !strcmp("dvbsubtitle", type); + unsigned char teletext = !strcmp("teletext", type); + + pipe_printf(10, "v%d a%d\n", dvbsubtitle, teletext); + + if ( (dvbsubtitle && dvbsubtitlefd != -1) || (teletext && teletextfd != -1) ) { + getPipeMutex(FILENAME, __FUNCTION__,__LINE__); + + if (dvbsubtitle && dvbsubtitlefd != -1) { + char buf[65536]; + while(0 < read(dvbsubtitlefd, buf, sizeof(buf))); + } + if (teletext && teletextfd != -1) { + char buf[65536]; + while(0 < read(teletextfd, buf, sizeof(buf))); + } + + releasePipeMutex(FILENAME, __FUNCTION__,__LINE__); + } + + pipe_printf(10, "exiting\n"); + + return ret; +} + +int PipeSwitch(Context_t *context, char * type) { + unsigned char dvbsubtitle = !strcmp("dvbsubtitle", type); + unsigned char teletext = !strcmp("teletext", type); + Writer_t* writer; + + pipe_printf(10, "v%d a%d\n", dvbsubtitle, teletext); + + if ( (dvbsubtitle && dvbsubtitlefd != -1) || (teletext && teletextfd != -1) ) { + getPipeMutex(FILENAME, __FUNCTION__,__LINE__); + + if (teletext && teletextfd != -1) { + } + + if (dvbsubtitle && dvbsubtitlefd != -1) { + } + + releasePipeMutex(FILENAME, __FUNCTION__,__LINE__); + + } + + pipe_printf(10, "exiting\n"); + + return cERR_PIPE_NO_ERROR; +} + +static int writePESDataTeletext(int fd, char *data, size_t data_len) +{ + int len = 0; + if (data_len > 0) { + len = data_len + 39; + char header[45]; + memset(header, 0, sizeof(header)); + header[2] = 0x01; + header[3] = 0xbd; + header[4] = (len >> 8) & 0xff; + header[5] = len & 0xff; + struct iovec iov[2]; + iov[0].iov_base = header; + iov[0].iov_len = 45; + iov[1].iov_base = data; + iov[1].iov_len = data_len; + len = writev(fd, iov, 2); + if (len != iov[0].iov_len + iov[1].iov_len) { + // writing to pipe failed, clear it. + char buf[65536]; + while(0 < read(fd, buf, sizeof(buf))); + } + } + return len; +} + +static int writePESDataDvbsubtitle(int fd, char *data, size_t data_len, int64_t pts) +{ + int len = 0; + if (data_len > 0) { + len = data_len + 10; + char header[16]; + memset(header, 0, sizeof(header)); + header[2] = 0x01; + header[3] = 0xbd; + header[4] = (len >> 8) & 0xff; + header[5] = len & 0xff; + + if (pts) { + header[7] = 0x80; + header[13] = 0x01 | ((pts << 1) & 0xff); + pts >>= 7; + header[12] = pts & 0xff; + pts >>=8; + header[11] = 0x01 | ((pts << 1) & 0xff); + pts >>= 7; + header[10] = pts & 0xff; + pts >>=8; + header[9] = 0x21 | ((pts << 1) & 0xff); + } + header[8] = 14 - 9; + header[14] = 0x20; + struct iovec iov[2]; + iov[0].iov_base = header; + iov[0].iov_len = 16; + iov[1].iov_base = data; + iov[1].iov_len = data_len; + len = writev(fd, iov, 2); + if (len != iov[0].iov_len + iov[1].iov_len) { + // writing to pipe failed, clear it. + char buf[65536]; + while(0 < read(fd, buf, sizeof(buf))); + } + } + return len; +} + +static int Write(void *_context, void* _out) +{ + Context_t *context = (Context_t *) _context; + AudioVideoOut_t *out = (AudioVideoOut_t*) _out; + int ret = cERR_PIPE_NO_ERROR; + int res = 0; + unsigned char dvbsubtitle; + unsigned char teletext; + Writer_t* writer; + WriterAVCallData_t call; + + if (out == NULL) + { + pipe_err("null pointer passed\n"); + return cERR_PIPE_ERROR; + } + + dvbsubtitle = !strcmp("dvbsubtitle", out->type); + teletext = !strcmp("teletext", out->type); + + pipe_printf(20, "DataLength=%u PrivateLength=%u Pts=%llu FrameRate=%f\n", + out->len, out->extralen, out->pts, out->frameRate); + pipe_printf(20, "v%d a%d\n", dvbsubtitle, teletext); + + if (dvbsubtitle) { + res = writePESDataDvbsubtitle(dvbsubtitlefd, out->data, out->len, out->pts); + + if (res <= 0) + { + ret = cERR_PIPE_ERROR; + } + } else if (teletext) { + res = writePESDataTeletext(teletextfd, out->data, out->len); + + if (res <= 0) + { + ret = cERR_PIPE_ERROR; + } + } + + return ret; +} + +static int reset(Context_t *context) +{ + int ret = cERR_PIPE_NO_ERROR; + + return ret; +} + +static int Command(void *_context, OutputCmd_t command, void * argument) { + Context_t* context = (Context_t*) _context; + int ret = cERR_PIPE_NO_ERROR; + + pipe_printf(50, "Command %d\n", command); + + switch(command) { + case OUTPUT_OPEN: { + ret = PipeOpen(context, (char*)argument); + break; + } + case OUTPUT_CLOSE: { + ret = PipeClose(context, (char*)argument); + reset(context); + break; + } + case OUTPUT_PLAY: { // 4 + ret = PipePlay(context, (char*)argument); + break; + } + case OUTPUT_STOP: { + reset(context); + ret = PipeStop(context, (char*)argument); + break; + } + case OUTPUT_FLUSH: { + ret = PipeFlush(context, (char*)argument); + reset(context); + break; + } + case OUTPUT_CLEAR: { + ret = PipeClear(context, (char*)argument); + break; + } + case OUTPUT_SWITCH: { + ret = PipeSwitch(context, (char*)argument); + break; + } + default: + pipe_err("ContainerCmd %d not supported!\n", command); + ret = cERR_PIPE_ERROR; + break; + } + + pipe_printf(50, "exiting with value %d\n", ret); + + return ret; +} + +static char *PipeCapabilities[] = { "teletext", "dvbsubtitle", NULL }; + +struct Output_s PipeOutput = { + "DVBSubTitle", + &Command, + &Write, + PipeCapabilities +}; +#endif diff --git a/libeplayer3/playback/playback.c b/libeplayer3/playback/playback.c index bbdf902..5a3320a 100644 --- a/libeplayer3/playback/playback.c +++ b/libeplayer3/playback/playback.c @@ -331,6 +331,10 @@ static int PlaybackClose(Context_t *context) { context->manager->audio->Command(context, MANAGER_DEL, NULL); context->manager->video->Command(context, MANAGER_DEL, NULL); context->manager->subtitle->Command(context, MANAGER_DEL, NULL); +#ifdef MARTII + context->manager->dvbsubtitle->Command(context, MANAGER_DEL, NULL); + context->manager->teletext->Command(context, MANAGER_DEL, NULL); +#endif context->playback->isPaused = 0; context->playback->isPlaying = 0; @@ -938,6 +942,61 @@ static int PlaybackSwitchSubtitle(Context_t *context, int* track) { return ret; } +#ifdef MARTII +static int PlaybackSwitchDVBSubtitle(Context_t *context, int* track) { + int ret = cERR_PLAYBACK_NO_ERROR; + + playback_printf(10, "Track: %d\n", *track); + + if (context && context->playback && context->playback->isPlaying ) { + if (context->manager && context->manager->dvbsubtitle) { + if (context->manager->dvbsubtitle->Command(context, MANAGER_SET, track) < 0) + { + playback_err("manager set track failed\n"); + } + } else + { + ret = cERR_PLAYBACK_ERROR; + playback_err("no dvbsubtitle\n"); + } + } else + { + playback_err("not possible\n"); + ret = cERR_PLAYBACK_ERROR; + } + + playback_printf(10, "exiting with value %d\n", ret); + + return ret; +} + +static int PlaybackSwitchTeletext(Context_t *context, int* track) { + int ret = cERR_PLAYBACK_NO_ERROR; + + playback_printf(10, "Track: %d\n", *track); + + if (context && context->playback && context->playback->isPlaying ) { + if (context->manager && context->manager->teletext) { + if (context->manager->teletext->Command(context, MANAGER_SET, track) < 0) + { + playback_err("manager set track failed\n"); + } + } else + { + ret = cERR_PLAYBACK_ERROR; + playback_err("no dvbsubtitle\n"); + } + } else + { + playback_err("not possible\n"); + ret = cERR_PLAYBACK_ERROR; + } + + playback_printf(10, "exiting with value %d\n", ret); + + return ret; +} +#endif static int PlaybackInfo(Context_t *context, char** infoString) { int ret = cERR_PLAYBACK_NO_ERROR; @@ -1044,6 +1103,16 @@ static int Command(void* _context, PlaybackCmd_t command, void * argument) { ret = PlaybackGetFrameCount(context, (unsigned long long int*)argument); break; } +#ifdef MARTII + case PLAYBACK_SWITCH_DVBSUBTITLE: { + ret = PlaybackSwitchDVBSubtitle(context, (int*)argument); + break; + } + case PLAYBACK_SWITCH_TELETEXT: { + ret = PlaybackSwitchTeletext(context, (int*)argument); + break; + } +#endif default: playback_err("PlaybackCmd %d not supported!\n", command); ret = cERR_PLAYBACK_ERROR; @@ -1074,6 +1143,10 @@ PlaybackHandler_t PlaybackHandler = { 0, 0, 0, +#ifdef MARTII + 0, + 0, +#endif &Command, "", 0 diff --git a/libspark/playback_libeplayer3.cpp b/libspark/playback_libeplayer3.cpp index 64645d1..87249db 100644 --- a/libspark/playback_libeplayer3.cpp +++ b/libspark/playback_libeplayer3.cpp @@ -58,7 +58,11 @@ bool cPlayback::Open(playmode_t PlayMode) player->container = &ContainerHandler; player->manager = &ManagerHandler; +#ifdef MARTII + fprintf(stderr, "player output name: %s\n", player->output->Name); +#else printf("%s\n", player->output->Name); +#endif } //Registration of output devices @@ -66,6 +70,10 @@ bool cPlayback::Open(playmode_t PlayMode) player->output->Command(player,OUTPUT_ADD, (void*)"audio"); player->output->Command(player,OUTPUT_ADD, (void*)"video"); player->output->Command(player,OUTPUT_ADD, (void*)"subtitle"); +#ifdef MARTII + player->output->Command(player,OUTPUT_ADD, (void*)"dvbsubtitle"); + player->output->Command(player,OUTPUT_ADD, (void*)"teletext"); +#endif } return 0; @@ -98,6 +106,10 @@ bool cPlayback::Start(char *filename, unsigned short vpid, int vtype, unsigned s init_jump = -1; //create playback path mAudioStream=0; +#ifdef MARTII + mDvbsubtitleStream=-1; + mTeletextStream=0; +#endif char file[400] = {""}; if(!strncmp("http://", filename, 7)) @@ -220,6 +232,10 @@ bool cPlayback::Stop(void) player->output->Command(player,OUTPUT_DEL, (void*)"audio"); player->output->Command(player,OUTPUT_DEL, (void*)"video"); player->output->Command(player,OUTPUT_DEL, (void*)"subtitle"); +#ifdef MARTII + player->output->Command(player,OUTPUT_DEL, (void*)"dvbsubtitle"); + player->output->Command(player,OUTPUT_DEL, (void*)"teletext"); +#endif } if(player && player->playback) @@ -233,7 +249,11 @@ bool cPlayback::Stop(void) return true; } +#ifdef MARTII +bool cPlayback::SetAPid(unsigned short pid, bool ac3 __attribute__((unused))) +#else bool cPlayback::SetAPid(unsigned short pid, bool ac3) +#endif { printf("%s:%s\n", FILENAME, __FUNCTION__); int i=pid; @@ -244,6 +264,30 @@ bool cPlayback::SetAPid(unsigned short pid, bool ac3) } return true; } +#ifdef MARTII +bool cPlayback::SetDvbsubtitlePid(unsigned short pid) +{ + printf("%s:%s\n", FILENAME, __FUNCTION__); + int i=pid; + if(pid!=mDvbsubtitleStream){ + if(player && player->playback) + player->playback->Command(player, PLAYBACK_SWITCH_DVBSUBTITLE, (void*)&i); + mDvbsubtitleStream=pid; + } + return true; +} +bool cPlayback::SetTeletextPid(unsigned short pid) +{ + printf("%s:%s\n", FILENAME, __FUNCTION__); + int i=pid; + if(pid!=mTeletextStream){ + if(player && player->playback) + player->playback->Command(player, PLAYBACK_SWITCH_TELETEXT, (void*)&i); + mTeletextStream=pid; + } + return true; +} +#endif bool cPlayback::SetSpeed(int speed) { @@ -460,6 +504,30 @@ void cPlayback::FindAllPids(uint16_t *apids, unsigned short *ac3flags, uint16_t } } } +#ifdef MARTII +void cPlayback::FindAllDvbsubtitlePids(uint16_t *pids, uint16_t *numpids, std::string *language) +{ + printf("%s:%s\n", FILENAME, __FUNCTION__); + if(player && player->manager && player->manager->dvbsubtitle) { + char ** TrackList = NULL; + player->manager->dvbsubtitle->Command(player, MANAGER_LIST, &TrackList); + if (TrackList != NULL) { + printf("DvbsubtitleTrack List\n"); + int i = 0,j=0; + for (i = 0,j=0; TrackList[i] != NULL; i+=2,j++) { + printf("\t%s - %s\n", TrackList[i], TrackList[i+1]); + pids[j]=j; + // atUnknown, atMPEG, atMP3, atAC3, atDTS, atAAC, atPCM, atOGG, atFLAC + language[j]=TrackList[i]; + free(TrackList[i]); + free(TrackList[i+1]); + } + free(TrackList); + *numpids=j; + } + } +} +#endif // cPlayback::cPlayback(int num) diff --git a/libspark/playback_libeplayer3.h b/libspark/playback_libeplayer3.h index d709abb..06878b6 100644 --- a/libspark/playback_libeplayer3.h +++ b/libspark/playback_libeplayer3.h @@ -15,6 +15,10 @@ class cPlayback bool playing; int nPlaybackSpeed; int mAudioStream; +#ifdef MARTII + int mDvbsubtitleStream; + int mTeletextStream; +#endif bool Stop(void); public: cPlayback(int num = 0); @@ -25,11 +29,21 @@ class cPlayback bool Start(char *filename, unsigned short vpid, int vtype, unsigned short apid, int ac3, unsigned int duration); bool SetAPid(unsigned short pid, bool ac3); +#ifdef MARTII + bool SetDvbsubtitlePid(unsigned short pid); + bool SetTeletextPid(unsigned short pid); + unsigned short GetAPid(void) { return mAudioStream; } + unsigned short GetDvbsubtitlePid(void) { return mDvbsubtitleStream; } + unsigned short GetTeletextPid(void) { return mTeletextStream; } +#endif bool SetSpeed(int speed); bool GetSpeed(int &speed) const; bool GetPosition(int &position, int &duration); bool SetPosition(int position, bool absolute = false); void FindAllPids(uint16_t *apids, unsigned short *ac3flags, uint16_t *numpida, std::string *language); +#ifdef MARTII + void FindAllDvbsubtitlePids(uint16_t *pids, uint16_t *numpids, std::string *language); +#endif #if 0 // Functions that are not used by movieplayer.cpp: bool GetOffset(off64_t &offset);