/* * LinuxDVB Output 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 #include #include #include #include #include #include #include #include #include #include #include #include "common.h" #include "output.h" #include "writer.h" #include "misc.h" #include "pes.h" /* ***************************** */ /* Makros/Constants */ /* ***************************** */ #define LINUXDVB_DEBUG static short debug_level = 0; static const char FILENAME[] = __FILE__; #ifdef LINUXDVB_DEBUG #define linuxdvb_printf(level, fmt, x...) do { \ if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x ); } while (0) #else #define linuxdvb_printf(x...) #endif #ifndef LINUXDVB_SILENT #define linuxdvb_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) #else #define linuxdvb_err(x...) #endif #define cERR_LINUXDVB_NO_ERROR 0 #define cERR_LINUXDVB_ERROR -1 static const char VIDEODEV[] = "/dev/dvb/adapter0/video0"; static const char AUDIODEV[] = "/dev/dvb/adapter0/audio0"; static int videofd = -1; static int audiofd = -1; unsigned long long int sCURRENT_PTS = 0; pthread_mutex_t LinuxDVBmutex; /* ***************************** */ /* Prototypes */ /* ***************************** */ int LinuxDvbStop(Context_t * context, char *type); /* ***************************** */ /* MISC Functions */ /* ***************************** */ void getLinuxDVBMutex(const char *filename __attribute__ ((unused)), const char *function __attribute__ ((unused)), int line __attribute__ ((unused))) { linuxdvb_printf(250, "requesting mutex\n"); pthread_mutex_lock(&LinuxDVBmutex); linuxdvb_printf(250, "received mutex\n"); } void releaseLinuxDVBMutex(const char *filename __attribute__ ((unused)), const char *function __attribute__ ((unused)), int line __attribute__ ((unused))) { pthread_mutex_unlock(&LinuxDVBmutex); linuxdvb_printf(250, "released mutex\n"); } int LinuxDvbOpen(Context_t * context __attribute__ ((unused)), char *type) { unsigned char video = !strcmp("video", type); unsigned char audio = !strcmp("audio", type); linuxdvb_printf(10, "v%d a%d\n", video, audio); if (video && videofd < 0) { videofd = open(VIDEODEV, O_RDWR); if (videofd < 0) { linuxdvb_err("failed to open %s - errno %d\n", VIDEODEV, errno); linuxdvb_err("%s\n", strerror(errno)); return cERR_LINUXDVB_ERROR; } if (ioctl(videofd, VIDEO_CLEAR_BUFFER) == -1) { linuxdvb_err("ioctl failed with errno %d\n", errno); linuxdvb_err("VIDEO_CLEAR_BUFFER: %s\n", strerror(errno)); } if (ioctl (videofd, VIDEO_SELECT_SOURCE, (void *) VIDEO_SOURCE_MEMORY) == -1) { linuxdvb_err("ioctl failed with errno %d\n", errno); linuxdvb_err("VIDEO_SELECT_SOURCE: %s\n", strerror(errno)); } if (ioctl (videofd, VIDEO_SET_STREAMTYPE, (void *) STREAM_TYPE_PROGRAM) == -1) { linuxdvb_err("ioctl failed with errno %d\n", errno); linuxdvb_err("VIDEO_SET_STREAMTYPE: %s\n", strerror(errno)); } if (ioctl(videofd, VIDEO_SET_SPEED, DVB_SPEED_NORMAL_PLAY) == -1) { linuxdvb_err("ioctl failed with errno %d\n", errno); linuxdvb_err("VIDEO_SET_SPEED: %s\n", strerror(errno)); } } if (audio && audiofd < 0) { audiofd = open(AUDIODEV, O_RDWR); if (audiofd < 0) { linuxdvb_err("failed to open %s - errno %d\n", AUDIODEV, errno); linuxdvb_err("%s\n", strerror(errno)); if (videofd < 0) close(videofd); return cERR_LINUXDVB_ERROR; } if (ioctl(audiofd, AUDIO_CLEAR_BUFFER) == -1) { linuxdvb_err("ioctl failed with errno %d\n", errno); linuxdvb_err("AUDIO_CLEAR_BUFFER: %s\n", strerror(errno)); } if (ioctl (audiofd, AUDIO_SELECT_SOURCE, (void *) AUDIO_SOURCE_MEMORY) == -1) { linuxdvb_err("ioctl failed with errno %d\n", errno); linuxdvb_err("AUDIO_SELECT_SOURCE: %s\n", strerror(errno)); } if (ioctl (audiofd, AUDIO_SET_STREAMTYPE, (void *) STREAM_TYPE_PROGRAM) == -1) { linuxdvb_err("ioctl failed with errno %d\n", errno); linuxdvb_err("AUDIO_SET_STREAMTYPE: %s\n", strerror(errno)); } } return cERR_LINUXDVB_NO_ERROR; } int LinuxDvbClose(Context_t * context, char *type) { unsigned char video = !strcmp("video", type); unsigned char audio = !strcmp("audio", type); linuxdvb_printf(10, "v%d a%d\n", video, audio); /* 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). */ LinuxDvbStop(context, type); getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); if (video && videofd != -1) { close(videofd); videofd = -1; } if (audio && audiofd != -1) { close(audiofd); audiofd = -1; } releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); return cERR_LINUXDVB_NO_ERROR; } int LinuxDvbPlay(Context_t * context, char *type) { int ret = cERR_LINUXDVB_NO_ERROR; Writer_t *writer; unsigned char video = !strcmp("video", type); unsigned char audio = !strcmp("audio", type); linuxdvb_printf(10, "v%d a%d\n", video, audio); if (video && videofd != -1) { char *Encoding = NULL; context->manager->video->Command(context, MANAGER_GETENCODING, &Encoding); linuxdvb_printf(10, "V %s\n", Encoding); writer = getWriter(Encoding); if (writer == NULL) { linuxdvb_err ("cannot found writer for encoding %s using default\n", Encoding); if (ioctl (videofd, VIDEO_SET_ENCODING, (void *) VIDEO_ENCODING_AUTO) == -1) { linuxdvb_err("ioctl failed with errno %d\n", errno); linuxdvb_err("VIDEO_SET_ENCODING: %s\n", strerror(errno)); ret = cERR_LINUXDVB_ERROR; } } else { linuxdvb_printf(20, "found writer %s for encoding %s\n", writer->caps->name, Encoding); if (ioctl (videofd, VIDEO_SET_ENCODING, (void *) writer->caps->dvbEncoding) == -1) { linuxdvb_err("ioctl failed with errno %d\n", errno); linuxdvb_err("VIDEO_SET_ENCODING: %s\n", strerror(errno)); ret = cERR_LINUXDVB_ERROR; } } if (ioctl(videofd, VIDEO_PLAY, NULL) == -1) { linuxdvb_err("ioctl failed with errno %d\n", errno); linuxdvb_err("VIDEO_PLAY: %s\n", strerror(errno)); ret = cERR_LINUXDVB_ERROR; } free(Encoding); } if (audio && audiofd != -1) { char *Encoding = NULL; context->manager->audio->Command(context, MANAGER_GETENCODING, &Encoding); linuxdvb_printf(20, "0 A %s\n", Encoding); writer = getWriter(Encoding); if (writer == NULL) { linuxdvb_err ("cannot found writer for encoding %s using default\n", Encoding); if (ioctl (audiofd, AUDIO_SET_ENCODING, (void *) AUDIO_ENCODING_MP3) == -1) { linuxdvb_err("ioctl failed with errno %d\n", errno); linuxdvb_err("AUDIO_SET_ENCODING: %s\n", strerror(errno)); ret = cERR_LINUXDVB_ERROR; } } else { linuxdvb_printf(20, "found writer %s for encoding %s\n", writer->caps->name, Encoding); if (ioctl (audiofd, AUDIO_SET_ENCODING, (void *) writer->caps->dvbEncoding) == -1) { linuxdvb_err("ioctl failed with errno %d\n", errno); linuxdvb_err("AUDIO_SET_ENCODING: %s\n", strerror(errno)); ret = -1; } } if (ioctl(audiofd, AUDIO_PLAY, NULL) == -1) { linuxdvb_err("ioctl failed with errno %d\n", errno); linuxdvb_err("AUDIO_PLAY: %s\n", strerror(errno)); ret = cERR_LINUXDVB_ERROR; } free(Encoding); } return ret; } int LinuxDvbStop(Context_t * context __attribute__ ((unused)), char *type) { int ret = cERR_LINUXDVB_NO_ERROR; unsigned char video = !strcmp("video", type); unsigned char audio = !strcmp("audio", type); linuxdvb_printf(10, "v%d a%d\n", video, audio); getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); if (video && videofd != -1) { if (ioctl(videofd, VIDEO_CLEAR_BUFFER) == -1) { linuxdvb_err("ioctl failed with errno %d\n", errno); linuxdvb_err("VIDEO_CLEAR_BUFFER: %s\n", strerror(errno)); } /* set back to normal speed (end trickmodes) */ if (ioctl(videofd, VIDEO_SET_SPEED, DVB_SPEED_NORMAL_PLAY) == -1) { linuxdvb_err("ioctl failed with errno %d\n", errno); linuxdvb_err("VIDEO_SET_SPEED: %s\n", strerror(errno)); } if (ioctl(videofd, VIDEO_STOP, NULL) == -1) { linuxdvb_err("ioctl failed with errno %d\n", errno); linuxdvb_err("VIDEO_STOP: %s\n", strerror(errno)); ret = cERR_LINUXDVB_ERROR; } } if (audio && audiofd != -1) { if (ioctl(audiofd, AUDIO_CLEAR_BUFFER) == -1) { linuxdvb_err("ioctl failed with errno %d\n", errno); linuxdvb_err("AUDIO_CLEAR_BUFFER: %s\n", strerror(errno)); } /* set back to normal speed (end trickmodes) */ if (ioctl(audiofd, AUDIO_SET_SPEED, DVB_SPEED_NORMAL_PLAY) == -1) { linuxdvb_err("ioctl failed with errno %d\n", errno); linuxdvb_err("AUDIO_SET_SPEED: %s\n", strerror(errno)); } if (ioctl(audiofd, AUDIO_STOP, NULL) == -1) { linuxdvb_err("ioctl failed with errno %d\n", errno); linuxdvb_err("AUDIO_STOP: %s\n", strerror(errno)); ret = cERR_LINUXDVB_ERROR; } } releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); return ret; } int LinuxDvbPause(Context_t * context __attribute__ ((unused)), char *type) { int ret = cERR_LINUXDVB_NO_ERROR; unsigned char video = !strcmp("video", type); unsigned char audio = !strcmp("audio", type); linuxdvb_printf(10, "v%d a%d\n", video, audio); getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); if (video && videofd != -1) { if (ioctl(videofd, VIDEO_FREEZE, NULL) == -1) { linuxdvb_err("ioctl failed with errno %d\n", errno); linuxdvb_err("VIDEO_FREEZE: %s\n", strerror(errno)); ret = cERR_LINUXDVB_ERROR; } } if (audio && audiofd != -1) { if (ioctl(audiofd, AUDIO_PAUSE, NULL) == -1) { linuxdvb_err("ioctl failed with errno %d\n", errno); linuxdvb_err("AUDIO_PAUSE: %s\n", strerror(errno)); ret = cERR_LINUXDVB_ERROR; } } releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); return ret; } int LinuxDvbContinue(Context_t * context __attribute__ ((unused)), char *type) { int ret = cERR_LINUXDVB_NO_ERROR; unsigned char video = !strcmp("video", type); unsigned char audio = !strcmp("audio", type); linuxdvb_printf(10, "v%d a%d\n", video, audio); if (video && videofd != -1) { if (ioctl(videofd, VIDEO_CONTINUE, NULL) == -1) { linuxdvb_err("ioctl failed with errno %d\n", errno); linuxdvb_err("VIDEO_CONTINUE: %s\n", strerror(errno)); ret = cERR_LINUXDVB_ERROR; } } if (audio && audiofd != -1) { if (ioctl(audiofd, AUDIO_CONTINUE, NULL) == -1) { linuxdvb_err("ioctl failed with errno %d\n", errno); linuxdvb_err("AUDIO_CONTINUE: %s\n", strerror(errno)); ret = cERR_LINUXDVB_ERROR; } } linuxdvb_printf(10, "exiting\n"); return ret; } int LinuxDvbReverseDiscontinuity(Context_t * context __attribute__ ((unused)), int *surplus) { int ret = cERR_LINUXDVB_NO_ERROR; int dis_type = VIDEO_DISCONTINUITY_CONTINUOUS_REVERSE | *surplus; linuxdvb_printf(50, "\n"); if (ioctl(videofd, VIDEO_DISCONTINUITY, (void *) dis_type) == -1) { linuxdvb_err("ioctl failed with errno %d\n", errno); linuxdvb_err("VIDEO_DISCONTINUITY: %s\n", strerror(errno)); } linuxdvb_printf(50, "exiting\n"); return ret; } int LinuxDvbAudioMute(Context_t * context __attribute__ ((unused)), char *flag) { int ret = cERR_LINUXDVB_NO_ERROR; linuxdvb_printf(10, "\n"); if (audiofd != -1) { if (*flag == '1') { //AUDIO_SET_MUTE has no effect with new player //if (ioctl(audiofd, AUDIO_SET_MUTE, 1) == -1) if (ioctl(audiofd, AUDIO_STOP, NULL) == -1) { linuxdvb_err("ioctl failed with errno %d\n", errno); //linuxdvb_err("AUDIO_SET_MUTE: %s\n", strerror(errno)); linuxdvb_err("AUDIO_STOP: %s\n", strerror(errno)); ret = cERR_LINUXDVB_ERROR; } } else { //AUDIO_SET_MUTE has no effect with new player //if (ioctl(audiofd, AUDIO_SET_MUTE, 0) == -1) if (ioctl(audiofd, AUDIO_PLAY, NULL) == -1) { linuxdvb_err("ioctl failed with errno %d\n", errno); //linuxdvb_err("AUDIO_SET_MUTE: %s\n", strerror(errno)); linuxdvb_err("AUDIO_PLAY: %s\n", strerror(errno)); ret = cERR_LINUXDVB_ERROR; } } } linuxdvb_printf(10, "exiting\n"); return ret; } int LinuxDvbFlush(Context_t * context __attribute__ ((unused)), char *type) { unsigned char video = !strcmp("video", type); unsigned char audio = !strcmp("audio", type); linuxdvb_printf(10, "v%d a%d\n", video, audio); if ((video && videofd != -1) || (audio && audiofd != -1)) { getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); if (video && videofd != -1) { if (ioctl(videofd, VIDEO_FLUSH, NULL) == -1) { linuxdvb_err("ioctl failed with errno %d\n", errno); linuxdvb_err("VIDEO_FLUSH: %s\n", strerror(errno)); } } if (audio && audiofd != -1) { if (ioctl(audiofd, AUDIO_FLUSH, NULL) == -1) { linuxdvb_err("ioctl failed with errno %d\n", errno); linuxdvb_err("AUDIO_FLUSH: %s\n", strerror(errno)); } } releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); } linuxdvb_printf(10, "exiting\n"); return cERR_LINUXDVB_NO_ERROR; } #ifndef use_set_speed_instead_ff int LinuxDvbFastForward(Context_t * context, char *type) { int ret = cERR_LINUXDVB_NO_ERROR; unsigned char video = !strcmp("video", type); unsigned char audio = !strcmp("audio", type); linuxdvb_printf(10, "v%d a%d speed %d\n", video, audio, context->playback->Speed); if (video && videofd != -1) { getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); /* konfetti comment: speed is a value given in skipped frames */ if (ioctl(videofd, VIDEO_FAST_FORWARD, context->playback->Speed) == -1) { linuxdvb_err("ioctl failed with errno %d\n", errno); linuxdvb_err("VIDEO_FAST_FORWARD: %s\n", strerror(errno)); ret = cERR_LINUXDVB_ERROR; } releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); } linuxdvb_printf(10, "exiting with value %d\n", ret); return ret; } #else static unsigned int SpeedList[] = { 1000, 1100, 1200, 1300, 1500, 2000, 3000, 4000, 5000, 8000, 12000, 16000, 125, 250, 500, 700, 800, 900 }; int LinuxDvbFastForward(Context_t * context, char *type) { int ret = cERR_LINUXDVB_NO_ERROR; int speedIndex; unsigned char video = !strcmp("video", type); unsigned char audio = !strcmp("audio", type); linuxdvb_printf(10, "v%d a%d\n", video, audio); if (video && videofd != -1) { getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); speedIndex = context->playback->Speed % (sizeof(SpeedList) / sizeof(int)); linuxdvb_printf(1, "speedIndex %d\n", speedIndex); if (ioctl(videofd, VIDEO_SET_SPEED, SpeedList[speedIndex]) == -1) { linuxdvb_err("ioctl failed with errno %d\n", errno); linuxdvb_err("VIDEO_SET_SPEED: %s\n", strerror(errno)); ret = cERR_LINUXDVB_ERROR; } releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); } if (audio && audiofd != -1) { getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); speedIndex = context->playback->Speed % (sizeof(SpeedList) / sizeof(int)); linuxdvb_printf(1, "speedIndex %d\n", speedIndex); if (ioctl(audiofd, AUDIO_SET_SPEED, SpeedList[speedIndex]) == -1) { linuxdvb_err("ioctl failed with errno %d\n", errno); linuxdvb_err("AUDIO_SET_SPEED: %s\n", strerror(errno)); ret = cERR_LINUXDVB_ERROR; } releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); } linuxdvb_printf(10, "exiting with value %d\n", ret); return ret; } #endif int LinuxDvbReverse(Context_t * context __attribute__ ((unused)), char *type __attribute__ ((unused))) { int ret = cERR_LINUXDVB_NO_ERROR; return ret; } int LinuxDvbSlowMotion(Context_t * context, char *type) { int ret = cERR_LINUXDVB_NO_ERROR; unsigned char video = !strcmp("video", type); unsigned char audio = !strcmp("audio", type); linuxdvb_printf(10, "v%d a%d\n", video, audio); if ((video && videofd != -1) || (audio && audiofd != -1)) { getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); if (video && videofd != -1) { if (ioctl (videofd, VIDEO_SLOWMOTION, context->playback->SlowMotion) == -1) { linuxdvb_err("ioctl failed with errno %d\n", errno); linuxdvb_err("VIDEO_SLOWMOTION: %s\n", strerror(errno)); ret = cERR_LINUXDVB_ERROR; } } releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); } linuxdvb_printf(10, "exiting with value %d\n", ret); return ret; } int LinuxDvbAVSync(Context_t * context, char *type __attribute__ ((unused))) { int ret = cERR_LINUXDVB_NO_ERROR; /* konfetti: this one is dedicated to audiofd so we * are ignoring what is given by type! I think we should * remove this param. Therefor we should add a variable * setOn or something like that instead, this would remove * using a variable inside the structure. */ if (audiofd != -1) { getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); if (ioctl(audiofd, AUDIO_SET_AV_SYNC, context->playback->AVSync) == -1) { linuxdvb_err("ioctl failed with errno %d\n", errno); linuxdvb_err("AUDIO_SET_AV_SYNC: %s\n", strerror(errno)); ret = cERR_LINUXDVB_ERROR; } releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); } return ret; } int LinuxDvbClear(Context_t * context __attribute__ ((unused)), char *type) { int ret = cERR_LINUXDVB_NO_ERROR; unsigned char video = !strcmp("video", type); unsigned char audio = !strcmp("audio", type); linuxdvb_printf(10, "v%d a%d\n", video, audio); if ((video && videofd != -1) || (audio && audiofd != -1)) { getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); if (video && videofd != -1) { if (ioctl(videofd, VIDEO_CLEAR_BUFFER) == -1) { linuxdvb_err("ioctl failed with errno %d\n", errno); linuxdvb_err("VIDEO_CLEAR_BUFFER: %s\n", strerror(errno)); ret = cERR_LINUXDVB_ERROR; } } if (audio && audiofd != -1) { if (ioctl(audiofd, AUDIO_CLEAR_BUFFER) == -1) { linuxdvb_err("ioctl failed with errno %d\n", errno); linuxdvb_err("AUDIO_CLEAR_BUFFER: %s\n", strerror(errno)); ret = cERR_LINUXDVB_ERROR; } } releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); } linuxdvb_printf(10, "exiting\n"); return ret; } int LinuxDvbPts(Context_t * context __attribute__ ((unused)), unsigned long long int *pts) { int ret = cERR_LINUXDVB_ERROR; linuxdvb_printf(50, "\n"); // pts is a non writting requests and can be done in parallel to other requests //getLinuxDVBMutex(FILENAME, __FUNCTION__,__LINE__); if ((videofd > -1 && !ioctl(videofd, VIDEO_GET_PTS, (void *) &sCURRENT_PTS)) || (audiofd > -1 && !ioctl(audiofd, AUDIO_GET_PTS, (void *) &sCURRENT_PTS))) ret = cERR_LINUXDVB_NO_ERROR; else sCURRENT_PTS = 0; *((unsigned long long int *) pts) = (unsigned long long int) sCURRENT_PTS; //releaseLinuxDVBMutex(FILENAME, __FUNCTION__,__LINE__); return ret; } int LinuxDvbGetFrameCount(Context_t * context __attribute__ ((unused)), unsigned long long int *frameCount) { int ret = cERR_LINUXDVB_NO_ERROR; dvb_play_info_t playInfo; linuxdvb_printf(50, "\n"); getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); if (videofd != -1) { if (ioctl(videofd, VIDEO_GET_PLAY_INFO, (void *) &playInfo) == -1) { linuxdvb_err("ioctl failed with errno %d\n", errno); linuxdvb_err("VIDEO_GET_PLAY_INFO: %s\n", strerror(errno)); ret = cERR_LINUXDVB_ERROR; } else linuxdvb_err("V: %llu\n", playInfo.frame_count); } else if (audiofd != -1) { if (ioctl(audiofd, AUDIO_GET_PLAY_INFO, (void *) &playInfo) == -1) { linuxdvb_err("ioctl failed with errno %d\n", errno); linuxdvb_err("AUDIO_GET_PLAY_INFO: %s\n", strerror(errno)); ret = cERR_LINUXDVB_ERROR; } else linuxdvb_err("A: %llu\n", playInfo.frame_count); } else { ret = cERR_LINUXDVB_ERROR; } if (ret == cERR_LINUXDVB_NO_ERROR) *((unsigned long long int *) frameCount) = playInfo.frame_count; releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); return ret; } int LinuxDvbSwitch(Context_t * context, char *type) { unsigned char audio = !strcmp("audio", type); unsigned char video = !strcmp("video", type); Writer_t *writer; linuxdvb_printf(10, "v%d a%d\n", video, audio); if ((video && videofd != -1) || (audio && audiofd != -1)) { getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); if (audio && audiofd != -1) { char *Encoding = NULL; if (context && context->manager && context->manager->audio) { context->manager->audio->Command(context, MANAGER_GETENCODING, &Encoding); linuxdvb_printf(10, "A %s\n", Encoding); writer = getWriter(Encoding); if (ioctl(audiofd, AUDIO_STOP, NULL) == -1) { linuxdvb_err("ioctl failed with errno %d\n", errno); linuxdvb_err("AUDIO_STOP: %s\n", strerror(errno)); } if (ioctl(audiofd, AUDIO_CLEAR_BUFFER) == -1) { linuxdvb_err("ioctl failed with errno %d\n", errno); linuxdvb_err("AUDIO_CLEAR_BUFFER: %s\n", strerror(errno)); } if (writer == NULL) { linuxdvb_err ("cannot found writer for encoding %s using default\n", Encoding); if (ioctl (audiofd, AUDIO_SET_ENCODING, (void *) AUDIO_ENCODING_MP3) == -1) { linuxdvb_err("ioctl failed with errno %d\n", errno); linuxdvb_err("AUDIO_SET_ENCODING: %s\n", strerror(errno)); } } else { linuxdvb_printf(10, "found writer %s for encoding %s\n", writer->caps->name, Encoding); if (ioctl (audiofd, AUDIO_SET_ENCODING, (void *) writer->caps->dvbEncoding) == -1) { linuxdvb_err("ioctl failed with errno %d\n", errno); linuxdvb_err("AUDIO_SET_ENCODING: %s\n", strerror(errno)); } } if (ioctl(audiofd, AUDIO_PLAY, NULL) == -1) { linuxdvb_err("ioctl failed with errno %d\n", errno); linuxdvb_err("AUDIO_PLAY: %s\n", strerror(errno)); } free(Encoding); } else linuxdvb_printf(20, "no context for Audio\n"); } if (video && videofd != -1) { char *Encoding = NULL; if (context && context->manager && context->manager->video) { context->manager->video->Command(context, MANAGER_GETENCODING, &Encoding); if (ioctl(videofd, VIDEO_STOP, NULL) == -1) { linuxdvb_err("ioctl failed with errno %d\n", errno); linuxdvb_err("VIDEO_STOP: %s\n", strerror(errno)); } if (ioctl(videofd, VIDEO_CLEAR_BUFFER) == -1) { linuxdvb_err("ioctl failed with errno %d\n", errno); linuxdvb_err("VIDEO_CLEAR_BUFFER: %s\n", strerror(errno)); } linuxdvb_printf(10, "V %s\n", Encoding); writer = getWriter(Encoding); if (writer == NULL) { linuxdvb_err ("cannot found writer for encoding %s using default\n", Encoding); if (ioctl (videofd, VIDEO_SET_ENCODING, (void *) VIDEO_ENCODING_AUTO) == -1) { linuxdvb_err("ioctl failed with errno %d\n", errno); linuxdvb_err("VIDEO_SET_ENCODING: %s\n", strerror(errno)); } } else { linuxdvb_printf(10, "found writer %s for encoding %s\n", writer->caps->name, Encoding); if (ioctl (videofd, VIDEO_SET_ENCODING, (void *) writer->caps->dvbEncoding) == -1) { linuxdvb_err("ioctl failed with errno %d\n", errno); linuxdvb_err("VIDEO_SET_ENCODING: %s\n", strerror(errno)); } } if (ioctl(videofd, VIDEO_PLAY, NULL) == -1) { /* konfetti: fixme: think on this, I think we should * return an error here and stop the playback mode */ linuxdvb_err("ioctl failed with errno %d\n", errno); linuxdvb_err("VIDEO_PLAY: %s\n", strerror(errno)); } free(Encoding); } else linuxdvb_printf(20, "no context for Video\n"); } releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); } linuxdvb_printf(10, "exiting\n"); return cERR_LINUXDVB_NO_ERROR; } static int Write(Context_t *context, AudioVideoOut_t *out) { int ret = cERR_LINUXDVB_NO_ERROR; int res = 0; unsigned char video = 0; unsigned char audio = 0; Writer_t *writer; WriterAVCallData_t call; call.stream = out->stream; call.avfc = out->avfc; if (out == NULL) { linuxdvb_err("null pointer passed\n"); return cERR_LINUXDVB_ERROR; } video = !strcmp("video", out->type); audio = !strcmp("audio", out->type); linuxdvb_printf(20, "DataLength=%u Pts=%llu\n", out->packet->size, out->pts); linuxdvb_printf(20, "v%d a%d\n", video, audio); if (video) { char *Encoding = NULL; context->manager->video->Command(context, MANAGER_GETENCODING, &Encoding); linuxdvb_printf(20, "Encoding = %s\n", Encoding); writer = getWriter(Encoding); if (writer == NULL) { linuxdvb_printf(20, "searching default writer ... %s\n", Encoding); writer = getDefaultVideoWriter(); } if (writer == NULL) { linuxdvb_err("unknown video codec and no default writer %s\n", Encoding); ret = cERR_LINUXDVB_ERROR; } else { call.fd = videofd; call.Pts = out->pts; call.packet = out->packet; if (writer->writeData) res = writer->writeData(&call); if (res < 0) { linuxdvb_err("failed to write data %d - %d\n", res, errno); linuxdvb_err("%s\n", strerror(errno)); ret = cERR_LINUXDVB_ERROR; } } free(Encoding); } else if (audio) { char *Encoding = NULL; context->manager->audio->Command(context, MANAGER_GETENCODING, &Encoding); linuxdvb_printf(20, "%s::%s Encoding = %s\n", FILENAME, __FUNCTION__, Encoding); writer = getWriter(Encoding); if (writer == NULL) { linuxdvb_printf(20, "searching default writer ... %s\n", Encoding); writer = getDefaultAudioWriter(); } if (writer == NULL) { linuxdvb_err("unknown audio codec %s and no default writer\n", Encoding); ret = cERR_LINUXDVB_ERROR; } else { call.fd = audiofd; call.Pts = out->pts; call.packet = out->packet; call.restart_audio_resampling = out->restart_audio_resampling; call.context = context; if (writer->writeData) res = writer->writeData(&call); if (res < 0) { linuxdvb_err("failed to write data %d - %d\n", res, errno); linuxdvb_err("%s\n", strerror(errno)); ret = cERR_LINUXDVB_ERROR; } } free(Encoding); } return ret; } static int reset(Context_t * context) { int ret = cERR_LINUXDVB_NO_ERROR; Writer_t *writer; char *Encoding = NULL; context->manager->video->Command(context, MANAGER_GETENCODING, &Encoding); writer = getWriter(Encoding); if (writer == NULL) { linuxdvb_err("unknown video codec %s\n", Encoding); ret = cERR_LINUXDVB_ERROR; } else { writer->reset(); } free(Encoding); context->manager->audio->Command(context, MANAGER_GETENCODING, &Encoding); writer = getWriter(Encoding); if (writer == NULL) { linuxdvb_err("unknown video codec %s\n", Encoding); ret = cERR_LINUXDVB_ERROR; } else { writer->reset(); } free(Encoding); return ret; } static int Command(Context_t *context, OutputCmd_t command, const char *argument) { int ret = cERR_LINUXDVB_NO_ERROR; linuxdvb_printf(50, "Command %d\n", command); switch (command) { case OUTPUT_OPEN:{ ret = LinuxDvbOpen(context, (char *) argument); break; } case OUTPUT_CLOSE:{ ret = LinuxDvbClose(context, (char *) argument); reset(context); sCURRENT_PTS = 0; break; } case OUTPUT_PLAY:{ // 4 sCURRENT_PTS = 0; ret = LinuxDvbPlay(context, (char *) argument); break; } case OUTPUT_STOP:{ reset(context); ret = LinuxDvbStop(context, (char *) argument); sCURRENT_PTS = 0; break; } case OUTPUT_FLUSH:{ ret = LinuxDvbFlush(context, (char *) argument); reset(context); sCURRENT_PTS = 0; break; } case OUTPUT_PAUSE:{ ret = LinuxDvbPause(context, (char *) argument); break; } case OUTPUT_CONTINUE:{ ret = LinuxDvbContinue(context, (char *) argument); break; } case OUTPUT_FASTFORWARD:{ return LinuxDvbFastForward(context, (char *) argument); break; } case OUTPUT_REVERSE:{ return LinuxDvbReverse(context, (char *) argument); break; } case OUTPUT_AVSYNC:{ ret = LinuxDvbAVSync(context, (char *) argument); break; } case OUTPUT_CLEAR:{ ret = LinuxDvbClear(context, (char *) argument); reset(context); sCURRENT_PTS = 0; break; } case OUTPUT_PTS:{ unsigned long long int pts = 0; ret = LinuxDvbPts(context, &pts); *((unsigned long long int *) argument) = (unsigned long long int) pts; break; } case OUTPUT_SWITCH:{ ret = LinuxDvbSwitch(context, (char *) argument); break; } case OUTPUT_SLOWMOTION:{ return LinuxDvbSlowMotion(context, (char *) argument); break; } case OUTPUT_AUDIOMUTE:{ return LinuxDvbAudioMute(context, (char *) argument); break; } case OUTPUT_DISCONTINUITY_REVERSE:{ return LinuxDvbReverseDiscontinuity(context, (int *) argument); break; } case OUTPUT_GET_FRAME_COUNT:{ unsigned long long int frameCount = 0; ret = LinuxDvbGetFrameCount(context, &frameCount); *((unsigned long long int *) argument) = (unsigned long long int) frameCount; break; } default: linuxdvb_err("ContainerCmd %d not supported!\n", command); ret = cERR_LINUXDVB_ERROR; break; } linuxdvb_printf(50, "exiting with value %d\n", ret); return ret; } static const char *LinuxDvbCapabilities[] = { "audio", "video", NULL }; struct Output_s LinuxDvbOutput = { "LinuxDvb", &Command, &Write, LinuxDvbCapabilities };