source: titan/libeplayer3/output/linuxdvb_sh4.c @ 44958

Last change on this file since 44958 was 44958, checked in by obi, 3 years ago

[libeplayer3] update to v68

File size: 38.1 KB
Line 
1/*
2 * LinuxDVB Output handling.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 */
19
20/* ***************************** */
21/* Includes                      */
22/* ***************************** */
23
24#include <stdio.h>
25#include <string.h>
26#include <stdlib.h>
27#include <unistd.h>
28#include <fcntl.h>
29#include <sys/types.h>
30#include <sys/stat.h>
31#include <sys/ioctl.h>
32#include <linux/dvb/video.h>
33#include <linux/dvb/audio.h>
34#include <memory.h>
35#include <asm/types.h>
36#include <pthread.h>
37#include <errno.h>
38#include <poll.h>
39#include <sys/uio.h>
40
41#include "bcm_ioctls.h"
42#include "stm_ioctls.h"
43
44#include "common.h"
45#include "debug.h"
46#include "output.h"
47#include "writer.h"
48#include "misc.h"
49#include "pes.h"
50
51/* ***************************** */
52/* Makros/Constants              */
53/* ***************************** */
54#define cERR_LINUXDVB_NO_ERROR      0
55#define cERR_LINUXDVB_ERROR        -1
56
57static const char VIDEODEV[]    = "/dev/dvb/adapter0/video0";
58static const char AUDIODEV[]    = "/dev/dvb/adapter0/audio0";
59
60static int videofd      = -1;
61static int audiofd      = -1;
62struct DVBApiVideoInfo_s
63{
64    int aspect_ratio;
65    int progressive;
66    int frame_rate;
67    int width, height;
68};
69static struct DVBApiVideoInfo_s videoInfo = {-1,-1,-1,-1,-1};
70
71unsigned long long int sCURRENT_PTS = 0;
72bool isBufferedOutput = false;
73
74pthread_mutex_t LinuxDVBmutex;
75
76/* ***************************** */
77/* Prototypes                    */
78/* ***************************** */
79int32_t LinuxDvbBuffOpen(Context_t *context, char *type, int outfd, void *mtx);
80int32_t LinuxDvbBuffClose(Context_t *context);
81int32_t LinuxDvbBuffFlush(Context_t *context);
82int32_t LinuxDvbBuffResume(Context_t *context);
83
84ssize_t BufferingWriteV(int fd, const struct iovec *iov, int ic);
85int32_t LinuxDvbBuffSetSize(const uint32_t bufferSize);
86uint32_t LinuxDvbBuffGetSize();
87
88int LinuxDvbStop(Context_t  *context, char * type);
89
90/* ***************************** */
91/* MISC Functions                */
92/* ***************************** */
93
94#define getLinuxDVBMutex() pthread_mutex_lock(&LinuxDVBmutex)
95#define releaseLinuxDVBMutex() pthread_mutex_unlock(&LinuxDVBmutex)
96
97int LinuxDvbOpen(Context_t  *context __attribute__((unused)), char * type) {
98    unsigned char video = !strcmp("video", type);
99    unsigned char audio = !strcmp("audio", type);
100
101    linuxdvb_printf(10, "v%d a%d\n", video, audio);
102
103    if (video && videofd < 0)
104    {
105   
106        videofd = open(VIDEODEV, O_RDWR);
107        if (videofd < 0)
108        {
109            linuxdvb_err("failed to open %s - errno %d\n", VIDEODEV, errno);
110            linuxdvb_err("%s\n", strerror(errno));
111            return cERR_LINUXDVB_ERROR;
112        }
113
114        if (ioctl( videofd, VIDEO_CLEAR_BUFFER) == -1)
115        {
116            linuxdvb_err("ioctl failed with errno %d\n", errno);
117            linuxdvb_err("VIDEO_CLEAR_BUFFER: %s\n", strerror(errno));
118        }
119
120        if (ioctl( videofd, VIDEO_SELECT_SOURCE, (void*)VIDEO_SOURCE_MEMORY) == -1)
121        {
122            linuxdvb_err("ioctl failed with errno %d\n", errno);
123            linuxdvb_err("VIDEO_SELECT_SOURCE: %s\n", strerror(errno));
124        }
125
126        if (ioctl( videofd, VIDEO_SET_STREAMTYPE, (void*)STREAM_TYPE_PROGRAM) == -1)
127        {
128            linuxdvb_err("ioctl failed with errno %d\n", errno);
129            linuxdvb_err("VIDEO_SET_STREAMTYPE: %s\n", strerror(errno));
130        }
131
132        if (ioctl(videofd, VIDEO_SET_SPEED, DVB_SPEED_NORMAL_PLAY) == -1)
133        {
134            linuxdvb_err("ioctl failed with errno %d\n", errno);
135            linuxdvb_err("VIDEO_SET_SPEED: %s\n", strerror(errno));
136        }
137
138        if (isBufferedOutput)
139            LinuxDvbBuffOpen(context, type, videofd, &LinuxDVBmutex);
140    }
141    if (audio && audiofd < 0)
142    {
143        audiofd = open(AUDIODEV, O_RDWR);
144        if (audiofd < 0)
145        {
146            linuxdvb_err("failed to open %s - errno %d\n", AUDIODEV, errno);
147            linuxdvb_err("%s\n", strerror(errno));
148
149            if (videofd < 0)
150                close(videofd);
151            return cERR_LINUXDVB_ERROR;
152        }
153
154        if (ioctl( audiofd, AUDIO_CLEAR_BUFFER) == -1)
155        {
156            linuxdvb_err("ioctl failed with errno %d\n", errno);
157            linuxdvb_err("AUDIO_CLEAR_BUFFER: %s\n", strerror(errno));
158        }
159
160        if (ioctl( audiofd, AUDIO_SELECT_SOURCE, (void*)AUDIO_SOURCE_MEMORY) == -1)
161        {
162            linuxdvb_err("ioctl failed with errno %d\n", errno);
163            linuxdvb_err("AUDIO_SELECT_SOURCE: %s\n", strerror(errno));
164        }
165
166        if (ioctl( audiofd, AUDIO_SET_STREAMTYPE, (void*)STREAM_TYPE_PROGRAM) == -1)
167        {
168            linuxdvb_err("ioctl failed with errno %d\n", errno);
169            linuxdvb_err("AUDIO_SET_STREAMTYPE: %s\n", strerror(errno));
170        }
171       
172        if (isBufferedOutput)
173            LinuxDvbBuffOpen(context, type, audiofd, &LinuxDVBmutex);
174    }
175
176    return cERR_LINUXDVB_NO_ERROR;
177}
178
179int LinuxDvbClose(Context_t  *context, char * type)
180{
181    uint8_t video = !strcmp("video", type);
182    uint8_t audio = !strcmp("audio", type);
183
184    linuxdvb_printf(10, "v%d a%d\n", video, audio);
185
186    /* closing stand alone is not allowed, so prevent
187     * user from closing and dont call stop. stop will
188     * set default values for us (speed and so on).
189     */
190    LinuxDvbStop(context, type);
191
192    getLinuxDVBMutex();
193
194    if (isBufferedOutput)
195        LinuxDvbBuffClose(context);
196
197    if (video && videofd != -1)
198    {
199        close(videofd);
200        videofd = -1;
201    }
202    if (audio && audiofd != -1)
203    {
204        close(audiofd);
205        audiofd = -1;
206    }
207
208    releaseLinuxDVBMutex();
209    return cERR_LINUXDVB_NO_ERROR;
210}
211
212int LinuxDvbPlay(Context_t  *context, char * type) {
213    int ret = cERR_LINUXDVB_NO_ERROR;
214    Writer_t* writer;
215
216    unsigned char video = !strcmp("video", type);
217    unsigned char audio = !strcmp("audio", type);
218
219    linuxdvb_printf(10, "v%d a%d\n", video, audio);
220
221    if (video && videofd != -1) {
222        char * Encoding = NULL;
223        context->manager->video->Command(context, MANAGER_GETENCODING, &Encoding);
224
225        linuxdvb_printf(10, "V %s\n", Encoding);
226
227        writer = getWriter(Encoding);
228
229        if (writer == NULL)
230        {
231            linuxdvb_err("cannot found writer for encoding %s using default\n", Encoding);
232            if (ioctl( videofd, VIDEO_SET_ENCODING, VIDEO_ENCODING_AUTO) == -1)
233            {
234                linuxdvb_err("ioctl failed with errno %d\n", errno);
235                linuxdvb_err("VIDEO_SET_ENCODING: %s\n", strerror(errno));
236                ret = cERR_LINUXDVB_ERROR;
237            }
238        } else
239        {
240            linuxdvb_printf(20, "found writer %s for encoding %s\n", writer->caps->name, Encoding);
241            if (ioctl( videofd, VIDEO_SET_ENCODING, writer->caps->dvbEncoding) == -1)
242            {
243                linuxdvb_err("ioctl failed with errno %d\n", errno);
244                linuxdvb_err("VIDEO_SET_ENCODING: %s\n", strerror(errno));
245                ret = cERR_LINUXDVB_ERROR;
246            }
247        }
248
249        if (ioctl(videofd, VIDEO_PLAY, NULL) == -1)
250        {
251            linuxdvb_err("ioctl failed with errno %d\n", errno);
252            linuxdvb_err("VIDEO_PLAY: %s\n", strerror(errno));
253            ret = cERR_LINUXDVB_ERROR;
254        }
255        free(Encoding);
256    }
257    if (audio && audiofd != -1) {
258        char * Encoding = NULL;
259        context->manager->audio->Command(context, MANAGER_GETENCODING, &Encoding);
260
261        linuxdvb_printf(20, "0 A %s\n", Encoding);
262
263        writer = getWriter(Encoding);
264
265        if (writer == NULL)
266        {
267            linuxdvb_err("cannot found writer for encoding %s using default\n", Encoding);
268            if (ioctl( audiofd, AUDIO_SET_ENCODING, (void*)AUDIO_ENCODING_MP3) == -1)
269            {
270                linuxdvb_err("ioctl failed with errno %d\n", errno);
271                linuxdvb_err("AUDIO_SET_ENCODING: %s\n", strerror(errno));
272                ret = cERR_LINUXDVB_ERROR;
273            }
274        } else
275        {
276            linuxdvb_printf(20, "found writer %s for encoding %s\n", writer->caps->name, Encoding);
277            if (ioctl( audiofd, AUDIO_SET_ENCODING, writer->caps->dvbEncoding) == -1)
278            {
279                linuxdvb_err("ioctl failed with errno %d\n", errno);
280                linuxdvb_err("AUDIO_SET_ENCODING: %s\n", strerror(errno));
281                ret = -1;
282            }
283        }
284
285        if (ioctl(audiofd, AUDIO_PLAY, NULL) == -1)
286        {
287            linuxdvb_err("ioctl failed with errno %d\n", errno);
288            linuxdvb_err("AUDIO_PLAY: %s\n", strerror(errno));
289            ret = cERR_LINUXDVB_ERROR;
290        }
291        free(Encoding);
292    }
293
294    return ret;
295}
296
297int LinuxDvbStop(Context_t  *context __attribute__((unused)), char * type) {
298    int ret = cERR_LINUXDVB_NO_ERROR;
299    unsigned char video = !strcmp("video", type);
300    unsigned char audio = !strcmp("audio", type);
301
302    linuxdvb_printf(10, "v%d a%d\n", video, audio);
303
304    getLinuxDVBMutex();
305
306    if (video && videofd != -1) {
307        if (ioctl(videofd, VIDEO_CLEAR_BUFFER) == -1)
308        {
309            linuxdvb_err("ioctl failed with errno %d\n", errno);
310            linuxdvb_err("VIDEO_CLEAR_BUFFER: %s\n", strerror(errno));
311        }
312
313        /* set back to normal speed (end trickmodes) */
314        if (ioctl(videofd, VIDEO_SET_SPEED, DVB_SPEED_NORMAL_PLAY) == -1)
315        {
316            linuxdvb_err("ioctl failed with errno %d\n", errno);
317            linuxdvb_err("VIDEO_SET_SPEED: %s\n", strerror(errno));
318        }
319        if (ioctl(videofd, VIDEO_STOP, NULL) == -1)
320        {
321            linuxdvb_err("ioctl failed with errno %d\n", errno);
322            linuxdvb_err("VIDEO_STOP: %s\n", strerror(errno));
323            ret = cERR_LINUXDVB_ERROR;
324        }
325    }
326    if (audio && audiofd != -1) {
327        if (ioctl(audiofd, AUDIO_CLEAR_BUFFER) == -1)
328        {
329            linuxdvb_err("ioctl failed with errno %d\n", errno);
330            linuxdvb_err("AUDIO_CLEAR_BUFFER: %s\n", strerror(errno));
331        }
332
333        /* set back to normal speed (end trickmodes) */
334        if (ioctl(audiofd, AUDIO_SET_SPEED, DVB_SPEED_NORMAL_PLAY) == -1)
335        {
336            linuxdvb_err("ioctl failed with errno %d\n", errno);
337            linuxdvb_err("AUDIO_SET_SPEED: %s\n", strerror(errno));
338        }
339        if (ioctl(audiofd, AUDIO_STOP, NULL) == -1)
340        {
341            linuxdvb_err("ioctl failed with errno %d\n", errno);
342            linuxdvb_err("AUDIO_STOP: %s\n", strerror(errno));
343            ret = cERR_LINUXDVB_ERROR;
344        }
345    }
346
347    releaseLinuxDVBMutex();
348
349    return ret;
350}
351
352int LinuxDvbPause(Context_t  *context __attribute__((unused)), char * type) {
353    int ret = cERR_LINUXDVB_NO_ERROR;
354    unsigned char video = !strcmp("video", type);
355    unsigned char audio = !strcmp("audio", type);
356
357    linuxdvb_printf(10, "v%d a%d\n", video, audio);
358
359    getLinuxDVBMutex();
360
361    if (video && videofd != -1) {
362        if (ioctl(videofd, VIDEO_FREEZE, NULL) == -1)
363        {
364            linuxdvb_err("ioctl failed with errno %d\n", errno);
365            linuxdvb_err("VIDEO_FREEZE: %s\n", strerror(errno));
366            ret = cERR_LINUXDVB_ERROR;
367        }
368    }
369    if (audio && audiofd != -1) {
370        if (ioctl(audiofd, AUDIO_PAUSE, NULL) == -1)
371        {
372            linuxdvb_err("ioctl failed with errno %d\n", errno);
373            linuxdvb_err("AUDIO_PAUSE: %s\n", strerror(errno));
374            ret = cERR_LINUXDVB_ERROR;
375        }
376    }
377
378    releaseLinuxDVBMutex();
379
380    return ret;
381}
382
383int LinuxDvbContinue(Context_t  *context __attribute__((unused)), char * type) {
384    int ret = cERR_LINUXDVB_NO_ERROR;
385    unsigned char video = !strcmp("video", type);
386    unsigned char audio = !strcmp("audio", type);
387
388    linuxdvb_printf(10, "v%d a%d\n", video, audio);
389
390    if (video && videofd != -1) {
391        if (ioctl(videofd, VIDEO_CONTINUE, NULL) == -1)
392        {
393            linuxdvb_err("ioctl failed with errno %d\n", errno);
394            linuxdvb_err("VIDEO_CONTINUE: %s\n", strerror(errno));
395            ret = cERR_LINUXDVB_ERROR;
396        }
397    }
398    if (audio && audiofd != -1) {
399        if (ioctl(audiofd, AUDIO_CONTINUE, NULL) == -1)
400        {
401            linuxdvb_err("ioctl failed with errno %d\n", errno);
402            linuxdvb_err("AUDIO_CONTINUE: %s\n", strerror(errno));
403            ret = cERR_LINUXDVB_ERROR;
404        }
405    }
406   
407    if (isBufferedOutput)
408        LinuxDvbBuffResume(context);
409
410    linuxdvb_printf(10, "exiting\n");
411
412
413    return ret;
414}
415
416int LinuxDvbReverseDiscontinuity(Context_t  *context __attribute__((unused)), int* surplus) {
417    int ret = cERR_LINUXDVB_NO_ERROR;
418    int dis_type = VIDEO_DISCONTINUITY_CONTINUOUS_REVERSE | *surplus;
419   
420    linuxdvb_printf(50, "\n");
421
422    if (ioctl( videofd, VIDEO_DISCONTINUITY, dis_type) == -1)
423    {
424        linuxdvb_err("ioctl failed with errno %d\n", errno);
425        linuxdvb_err("VIDEO_DISCONTINUITY: %s\n", strerror(errno));
426    }
427
428    linuxdvb_printf(50, "exiting\n");
429
430    return ret;
431}
432
433int LinuxDvbAudioMute(Context_t  *context __attribute__((unused)), char *flag) {
434    int ret = cERR_LINUXDVB_NO_ERROR;
435
436    linuxdvb_printf(10, "\n");
437
438    if (audiofd != -1) {
439        if(*flag == '1')
440        {
441            //AUDIO_SET_MUTE has no effect with new player
442            //if (ioctl(audiofd, AUDIO_SET_MUTE, 1) == -1)
443            if (ioctl(audiofd, AUDIO_STOP, NULL) == -1)
444            {
445                linuxdvb_err("ioctl failed with errno %d\n", errno);
446                //linuxdvb_err("AUDIO_SET_MUTE: %s\n", strerror(errno));
447                linuxdvb_err("AUDIO_STOP: %s\n", strerror(errno));
448                ret = cERR_LINUXDVB_ERROR;
449            }
450        }
451        else
452        {
453            //AUDIO_SET_MUTE has no effect with new player
454            //if (ioctl(audiofd, AUDIO_SET_MUTE, 0) == -1)
455            if (ioctl(audiofd, AUDIO_PLAY, NULL) == -1)
456            {
457                linuxdvb_err("ioctl failed with errno %d\n", errno);
458                //linuxdvb_err("AUDIO_SET_MUTE: %s\n", strerror(errno));
459                linuxdvb_err("AUDIO_PLAY: %s\n", strerror(errno));
460                ret = cERR_LINUXDVB_ERROR;
461            }
462        }
463    }
464
465    linuxdvb_printf(10, "exiting\n");
466
467    return ret;
468}
469
470
471int LinuxDvbFlush(Context_t  *context __attribute__((unused)), char * type) {
472    unsigned char video = !strcmp("video", type);
473    unsigned char audio = !strcmp("audio", type);
474
475    linuxdvb_printf(10, "v%d a%d\n", video, audio);
476
477    if ( (video && videofd != -1) || (audio && audiofd != -1) ) {
478        getLinuxDVBMutex();
479
480        if (video && videofd != -1) {
481            if (ioctl(videofd, VIDEO_FLUSH, NULL) == -1)
482            {
483                linuxdvb_err("ioctl failed with errno %d\n", errno);
484                linuxdvb_err("VIDEO_FLUSH: %s\n", strerror(errno));
485            }
486        }
487
488        if (audio && audiofd != -1) {
489            if (ioctl(audiofd, AUDIO_FLUSH, NULL) == -1)
490            {
491                linuxdvb_err("ioctl failed with errno %d\n", errno);
492                linuxdvb_err("AUDIO_FLUSH: %s\n", strerror(errno));
493            }
494        }
495
496        releaseLinuxDVBMutex();
497    }
498
499    linuxdvb_printf(10, "exiting\n");
500
501    return cERR_LINUXDVB_NO_ERROR;
502}
503
504#ifndef use_set_speed_instead_ff
505int LinuxDvbFastForward(Context_t  *context, char * type) {
506    int ret = cERR_LINUXDVB_NO_ERROR;
507
508    unsigned char video = !strcmp("video", type);
509    unsigned char audio = !strcmp("audio", type);
510
511    linuxdvb_printf(10, "v%d a%d speed %d\n", video, audio, context->playback->Speed);
512
513    if (video && videofd != -1) {
514
515        getLinuxDVBMutex();
516
517        /* konfetti comment: speed is a value given in skipped frames */
518
519        if (ioctl(videofd, VIDEO_FAST_FORWARD, context->playback->Speed) == -1)
520        {
521            linuxdvb_err("ioctl failed with errno %d\n", errno);
522            linuxdvb_err("VIDEO_FAST_FORWARD: %s\n", strerror(errno));
523            ret = cERR_LINUXDVB_ERROR;
524        }
525
526        releaseLinuxDVBMutex();
527    }
528
529    linuxdvb_printf(10, "exiting with value %d\n", ret);
530
531    return ret;
532}
533#else
534
535static unsigned int SpeedList[] =
536{
537    1000, 1100, 1200, 1300, 1500,
538    2000, 3000, 4000, 5000, 8000,
539    12000, 16000,
540    125, 250, 500, 700, 800, 900
541};
542
543int LinuxDvbFastForward(Context_t  *context, char * type) {
544    int ret = cERR_LINUXDVB_NO_ERROR;
545    int speedIndex;
546    unsigned char video = !strcmp("video", type);
547    unsigned char audio = !strcmp("audio", type);
548
549    linuxdvb_printf(10, "v%d a%d\n", video, audio);
550
551    if (video && videofd != -1) {
552
553        getLinuxDVBMutex();
554
555        speedIndex = context->playback->Speed % (sizeof (SpeedList) / sizeof (int));
556
557        linuxdvb_printf(1, "speedIndex %d\n", speedIndex);
558
559        if (ioctl(videofd, VIDEO_SET_SPEED, SpeedList[speedIndex]) == -1)
560        {
561            linuxdvb_err("ioctl failed with errno %d\n", errno);
562            linuxdvb_err("VIDEO_SET_SPEED: %s\n", strerror(errno));
563            ret = cERR_LINUXDVB_ERROR;
564        }
565
566        releaseLinuxDVBMutex();
567    }
568
569    if (audio && audiofd != -1) {
570
571        getLinuxDVBMutex();
572
573        speedIndex = context->playback->Speed % (sizeof (SpeedList) / sizeof (int));
574
575        linuxdvb_printf(1, "speedIndex %d\n", speedIndex);
576
577        if (ioctl(audiofd, AUDIO_SET_SPEED, SpeedList[speedIndex]) == -1)
578        {
579            linuxdvb_err("ioctl failed with errno %d\n", errno);
580            linuxdvb_err("AUDIO_SET_SPEED: %s\n", strerror(errno));
581            ret = cERR_LINUXDVB_ERROR;
582        }
583
584        releaseLinuxDVBMutex();
585    }
586
587    linuxdvb_printf(10, "exiting with value %d\n", ret);
588
589    return ret;
590}
591#endif
592
593
594int LinuxDvbReverse(Context_t  *context __attribute__((unused)), char * type __attribute__((unused))) {
595    int ret = cERR_LINUXDVB_NO_ERROR;
596    return ret;
597}
598
599int LinuxDvbSlowMotion(Context_t  *context, char * type) {
600    int ret = cERR_LINUXDVB_NO_ERROR;
601
602    unsigned char video = !strcmp("video", type);
603    unsigned char audio = !strcmp("audio", type);
604
605    linuxdvb_printf(10, "v%d a%d\n", video, audio);
606
607    if ( (video && videofd != -1) || (audio && audiofd != -1) ) {
608        getLinuxDVBMutex();
609
610        if (video && videofd != -1) {
611            if (ioctl(videofd, VIDEO_SLOWMOTION, context->playback->SlowMotion) == -1)
612            {
613                linuxdvb_err("ioctl failed with errno %d\n", errno);
614                linuxdvb_err("VIDEO_SLOWMOTION: %s\n", strerror(errno));
615                ret = cERR_LINUXDVB_ERROR;
616            }
617        }
618
619        releaseLinuxDVBMutex();
620    }
621
622    linuxdvb_printf(10, "exiting with value %d\n", ret);
623
624    return ret;
625}
626
627int LinuxDvbAVSync(Context_t  *context, char * type __attribute__((unused))) {
628    int ret = cERR_LINUXDVB_NO_ERROR;
629    /* konfetti: this one is dedicated to audiofd so we
630     * are ignoring what is given by type! I think we should
631     * remove this param. Therefor we should add a variable
632     * setOn or something like that instead, this would remove
633     * using a variable inside the structure.
634     */
635    if (audiofd != -1) {
636        getLinuxDVBMutex();
637
638        if (ioctl(audiofd, AUDIO_SET_AV_SYNC, context->playback->AVSync) == -1)
639        {
640            linuxdvb_err("ioctl failed with errno %d\n", errno);
641            linuxdvb_err("AUDIO_SET_AV_SYNC: %s\n", strerror(errno));
642            ret = cERR_LINUXDVB_ERROR;
643        }
644
645        releaseLinuxDVBMutex();
646    }
647
648    return ret;
649}
650
651int LinuxDvbClear(Context_t  *context __attribute__((unused)), char * type)
652{
653    int32_t ret = cERR_LINUXDVB_NO_ERROR;
654    uint8_t video = !strcmp("video", type);
655    uint8_t audio = !strcmp("audio", type);
656
657    linuxdvb_printf(10, ">>>>>>>>>>LinuxDvbClear v%d a%d\n", video, audio);
658
659    if ( (video && videofd != -1) || (audio && audiofd != -1) )
660    {
661        getLinuxDVBMutex();
662
663        if (video && videofd != -1)
664        {
665            if (ioctl(videofd, VIDEO_CLEAR_BUFFER) == -1)
666            {
667                linuxdvb_err("ioctl failed with errno %d\n", errno);
668                linuxdvb_err("VIDEO_CLEAR_BUFFER: %s\n", strerror(errno));
669                ret = cERR_LINUXDVB_ERROR;
670            }
671        }
672        else if (audio && audiofd != -1)
673        {
674            if (ioctl(audiofd, AUDIO_CLEAR_BUFFER) == -1)
675            {
676                linuxdvb_err("ioctl failed with errno %d\n", errno);
677                linuxdvb_err("AUDIO_CLEAR_BUFFER: %s\n", strerror(errno));
678                ret = cERR_LINUXDVB_ERROR;
679            }
680        }
681
682        releaseLinuxDVBMutex();
683    }
684
685    linuxdvb_printf(10, "exiting\n");
686
687    return ret;
688}
689
690int LinuxDvbPts(Context_t  *context __attribute__((unused)), unsigned long long int* pts) {
691    int ret = cERR_LINUXDVB_ERROR;
692   
693    linuxdvb_printf(50, "\n");
694
695    // pts is a non writting requests and can be done in parallel to other requests
696    //getLinuxDVBMutex();
697
698    if (videofd > -1 && !ioctl(videofd, VIDEO_GET_PTS, (void*)&sCURRENT_PTS))
699    {
700        ret = cERR_LINUXDVB_NO_ERROR;
701    }
702    else
703    {
704        linuxdvb_err("VIDEO_GET_PTS: %d (%s)\n", errno, strerror(errno));
705    }
706
707    if (ret != cERR_LINUXDVB_NO_ERROR)
708    {
709        if (audiofd > -1 && !ioctl(audiofd, AUDIO_GET_PTS, (void*)&sCURRENT_PTS))
710        {
711            ret = cERR_LINUXDVB_NO_ERROR;
712        }
713        else
714        {
715            linuxdvb_err("AUDIO_GET_PTS: %d (%s)\n", errno, strerror(errno));
716        }
717    }
718
719    if (ret != cERR_LINUXDVB_NO_ERROR)
720    {
721        sCURRENT_PTS = 0;
722    }
723
724    *((unsigned long long int *)pts)=(unsigned long long int)sCURRENT_PTS;
725
726    //releaseLinuxDVBMutex();
727
728    return ret;
729}
730
731int LinuxDvbGetFrameCount(Context_t  *context __attribute__((unused)), unsigned long long int* frameCount) {
732    int ret = cERR_LINUXDVB_NO_ERROR;
733    dvb_play_info_t playInfo;
734
735    linuxdvb_printf(50, "\n");
736
737    getLinuxDVBMutex();
738
739    if (videofd != -1)
740    {
741        if (ioctl(videofd, VIDEO_GET_PLAY_INFO, (void*)&playInfo) == -1)
742        {
743            linuxdvb_err("ioctl failed with errno %d\n", errno);
744            linuxdvb_err("VIDEO_GET_PLAY_INFO: %s\n", strerror(errno));
745            ret = cERR_LINUXDVB_ERROR;
746        }
747        else linuxdvb_err("V: %llu\n", playInfo.frame_count);
748    }
749    else if (audiofd != -1)
750    {
751        if (ioctl(audiofd, AUDIO_GET_PLAY_INFO, (void*)&playInfo) == -1)
752        {
753            linuxdvb_err("ioctl failed with errno %d\n", errno);
754            linuxdvb_err("AUDIO_GET_PLAY_INFO: %s\n", strerror(errno));
755            ret = cERR_LINUXDVB_ERROR;
756        }
757        else linuxdvb_err("A: %llu\n", playInfo.frame_count);
758    }
759    else {
760        ret = cERR_LINUXDVB_ERROR;
761    }
762
763    if(ret == cERR_LINUXDVB_NO_ERROR)
764        *((unsigned long long int *)frameCount) = playInfo.frame_count;
765
766    releaseLinuxDVBMutex();
767
768    return ret;
769}
770
771int LinuxDvbSwitch(Context_t  *context, char * type)
772{
773    unsigned char audio = !strcmp("audio", type);
774    unsigned char video = !strcmp("video", type);
775    Writer_t* writer;
776
777    linuxdvb_printf(10, "v%d a%d\n", video, audio);
778
779    if ( (video && videofd != -1) || (audio && audiofd != -1) ) {
780        getLinuxDVBMutex();
781
782        if (audio && audiofd != -1) {
783            char * Encoding = NULL;
784            if (context && context->manager && context->manager->audio) {
785                context->manager->audio->Command(context, MANAGER_GETENCODING, &Encoding);
786
787                linuxdvb_printf(10, "A %s\n", Encoding);
788
789                writer = getWriter(Encoding);
790
791                if (ioctl(audiofd, AUDIO_STOP ,NULL) == -1)
792                {
793                    linuxdvb_err("ioctl failed with errno %d\n", errno);
794                    linuxdvb_err("AUDIO_STOP: %s\n", strerror(errno));
795
796                }
797
798                if (ioctl(audiofd, AUDIO_CLEAR_BUFFER) == -1)
799                {
800                    linuxdvb_err("ioctl failed with errno %d\n", errno);
801                    linuxdvb_err("AUDIO_CLEAR_BUFFER: %s\n", strerror(errno));
802
803                }
804
805                if (writer == NULL)
806                {
807                    linuxdvb_err("cannot found writer for encoding %s using default\n", Encoding);
808                    if (ioctl( audiofd, AUDIO_SET_ENCODING, AUDIO_ENCODING_MP3) == -1)
809                    {
810                        linuxdvb_err("ioctl failed with errno %d\n", errno);
811                        linuxdvb_err("AUDIO_SET_ENCODING: %s\n", strerror(errno));
812                    }
813                } else
814                {
815                    linuxdvb_printf(10, "found writer %s for encoding %s\n", writer->caps->name, Encoding);
816                    if (ioctl( audiofd, AUDIO_SET_ENCODING, writer->caps->dvbEncoding) == -1)
817                    {
818                        linuxdvb_err("ioctl failed with errno %d\n", errno);
819                        linuxdvb_err("AUDIO_SET_ENCODING: %s\n", strerror(errno));
820                    }
821                }
822
823                if (ioctl(audiofd, AUDIO_PLAY, NULL) == -1)
824                {
825                    linuxdvb_err("ioctl failed with errno %d\n", errno);
826                    linuxdvb_err("AUDIO_PLAY: %s\n", strerror(errno));
827                }
828                free(Encoding);
829            }
830            else
831                linuxdvb_printf(20, "no context for Audio\n");
832        }
833
834        if (video && videofd != -1) {
835            char * Encoding = NULL;
836            if (context && context->manager && context->manager->video) {
837                context->manager->video->Command(context, MANAGER_GETENCODING, &Encoding);
838
839                if (ioctl(videofd, VIDEO_STOP ,NULL) == -1)
840                {
841                    linuxdvb_err("ioctl failed with errno %d\n", errno);
842                    linuxdvb_err("VIDEO_STOP: %s\n", strerror(errno));
843                }
844
845                if (ioctl(videofd, VIDEO_CLEAR_BUFFER) == -1)
846                {
847                    linuxdvb_err("ioctl failed with errno %d\n", errno);
848                    linuxdvb_err("VIDEO_CLEAR_BUFFER: %s\n", strerror(errno));
849                }
850
851                linuxdvb_printf(10, "V %s\n", Encoding);
852
853                writer = getWriter(Encoding);
854
855                if (writer == NULL)
856                {
857                    linuxdvb_err("cannot found writer for encoding %s using default\n", Encoding);
858                    if (ioctl( videofd, VIDEO_SET_ENCODING, (void*) VIDEO_ENCODING_AUTO) == -1)
859                    {
860                        linuxdvb_err("ioctl failed with errno %d\n", errno);
861                        linuxdvb_err("VIDEO_SET_ENCODING: %s\n", strerror(errno));
862                    }
863                } else
864                {
865                    linuxdvb_printf(10, "found writer %s for encoding %s\n", writer->caps->name, Encoding);
866                    if (ioctl( videofd, VIDEO_SET_ENCODING, writer->caps->dvbEncoding) == -1)
867                    {
868                        linuxdvb_err("ioctl failed with errno %d\n", errno);
869                        linuxdvb_err("VIDEO_SET_ENCODING: %s\n", strerror(errno));
870                    }
871                }
872
873                if (ioctl(videofd, VIDEO_PLAY, NULL) == -1)
874                {
875                    /* konfetti: fixme: think on this, I think we should
876                     * return an error here and stop the playback mode
877                     */
878                    linuxdvb_err("ioctl failed with errno %d\n", errno);
879                    linuxdvb_err("VIDEO_PLAY: %s\n", strerror(errno));
880                }
881                free(Encoding);
882            }
883            else
884                linuxdvb_printf(20, "no context for Video\n");
885        }
886
887        releaseLinuxDVBMutex();
888
889    }
890
891    linuxdvb_printf(10, "exiting\n");
892
893    return cERR_LINUXDVB_NO_ERROR;
894}
895
896static int Write(void  *_context, void* _out)
897{
898    Context_t          *context  = (Context_t  *) _context;
899    AudioVideoOut_t    *out      = (AudioVideoOut_t*) _out;
900    int                ret       = cERR_LINUXDVB_NO_ERROR;
901    int                res       = 0;
902    unsigned char      video     = 0;
903    unsigned char      audio     = 0;
904    Writer_t*          writer;
905    WriterAVCallData_t call;
906
907    if (out == NULL)
908    {
909       linuxdvb_err("null pointer passed\n");
910       return cERR_LINUXDVB_ERROR;
911    }
912   
913    video = !strcmp("video", out->type);
914    audio = !strcmp("audio", out->type);
915 
916    linuxdvb_printf(20, "DataLength=%u PrivateLength=%u Pts=%llu FrameRate=%f\n",
917                                                    out->len, out->extralen, out->pts, out->frameRate);
918    linuxdvb_printf(20, "v%d a%d\n", video, audio);
919
920    if (video)
921    {
922        char * Encoding = NULL;
923        context->manager->video->Command(context, MANAGER_GETENCODING, &Encoding);
924
925        linuxdvb_printf(20, "Encoding = %s\n", Encoding);
926
927        writer = getWriter(Encoding);
928
929        if (writer == NULL)
930        {
931            linuxdvb_printf(20, "searching default writer ... %s\n", Encoding);
932            writer = getDefaultVideoWriter();
933        }
934
935        if (writer == NULL)
936        {
937            linuxdvb_err("unknown video codec and no default writer %s\n",Encoding);
938            ret = cERR_LINUXDVB_ERROR;
939        }
940        else
941        {
942            struct pollfd pfd[1];
943            pfd[0].fd = videofd;
944            pfd[0].events = POLLPRI;
945            int pollret = poll(pfd, 1, 0);
946            if (pollret > 0 && pfd[0].revents & POLLPRI)
947            {
948                struct video_event evt;
949                if (ioctl(videofd, VIDEO_GET_EVENT, &evt) == -1)
950                {
951                    linuxdvb_err("ioctl failed with errno %d\n", errno);
952                    linuxdvb_err("VIDEO_GET_EVENT: %s\n", strerror(errno));
953                }
954                else
955                {
956                    if (evt.type == VIDEO_EVENT_SIZE_CHANGED)
957                    {
958                        linuxdvb_printf(10, "VIDEO_EVENT_SIZE_CHANGED\n", evt.type);
959                        linuxdvb_printf(10, "width  : %d\n", evt.u.size.w);
960                        linuxdvb_printf(10, "height : %d\n", evt.u.size.h);
961                        linuxdvb_printf(10, "aspect : %d\n", evt.u.size.aspect_ratio);
962                        videoInfo.width = evt.u.size.w;
963                        videoInfo.height = evt.u.size.h;
964                        videoInfo.aspect_ratio = evt.u.size.aspect_ratio;
965                    }
966                    else if (evt.type == VIDEO_EVENT_FRAME_RATE_CHANGED)
967                    {
968                        linuxdvb_printf(10, "VIDEO_EVENT_FRAME_RATE_CHANGED\n", evt.type);
969                        linuxdvb_printf(10, "framerate : %d\n", evt.u.frame_rate);
970                        videoInfo.frame_rate = evt.u.frame_rate;
971                    }
972                    else if (evt.type == 16 /*VIDEO_EVENT_PROGRESSIVE_CHANGED*/)
973                    {
974                        linuxdvb_printf(10, "VIDEO_EVENT_PROGRESSIVE_CHANGED\n", evt.type);
975                        linuxdvb_printf(10, "progressive : %d\n", evt.u.frame_rate);
976                        videoInfo.progressive = evt.u.frame_rate;
977                        context->manager->video->Command(context, MANAGER_UPDATED_TRACK_INFO, NULL);
978                    }
979                    else
980                    {
981                        linuxdvb_err("unhandled DVBAPI Video Event %d\n", evt.type);
982                    }
983                }
984            }
985
986            call.fd           = videofd;
987            call.data         = out->data;
988            call.len          = out->len;
989            call.Pts          = out->pts;
990            call.Dts          = out->dts;
991            call.private_data = out->extradata;
992            call.private_size = out->extralen;
993            call.FrameRate    = out->frameRate;
994            call.FrameScale   = out->timeScale;
995            call.Width        = out->width;
996            call.Height       = out->height;
997            call.InfoFlags      = out->infoFlags;
998            call.Version      = 0; // is unsingned char
999            call.WriteV       = isBufferedOutput ? BufferingWriteV : writev;
1000
1001            if (writer->writeData)
1002            {
1003                res = writer->writeData(&call);
1004            }
1005
1006            if (res < 0)
1007            {
1008                linuxdvb_err("failed to write data %d - %d\n", res, errno);
1009                linuxdvb_err("%s\n", strerror(errno));
1010                ret = cERR_LINUXDVB_ERROR;
1011            }
1012        }
1013
1014        free(Encoding);
1015    }
1016    else if (audio)
1017    {
1018        char * Encoding = NULL;
1019        context->manager->audio->Command(context, MANAGER_GETENCODING, &Encoding);
1020
1021        linuxdvb_printf(20, "%s::%s Encoding = %s\n", FILENAME, __FUNCTION__, Encoding);
1022
1023        writer = getWriter(Encoding);
1024
1025        if (writer == NULL)
1026        {
1027            linuxdvb_printf(20, "searching default writer ... %s\n", Encoding);
1028            writer = getDefaultAudioWriter();
1029        }
1030
1031        if (writer == NULL)
1032        {
1033            linuxdvb_err("unknown audio codec %s and no default writer\n",Encoding);
1034            ret = cERR_LINUXDVB_ERROR;
1035        }
1036        else
1037        {
1038            call.fd             = audiofd;
1039            call.data           = out->data;
1040            call.len            = out->len;
1041            call.Pts            = out->pts;
1042            call.Dts            = out->dts;
1043            call.private_data   = out->extradata;
1044            call.private_size   = out->extralen;
1045            call.FrameRate      = out->frameRate;
1046            call.FrameScale     = out->timeScale;
1047            call.InfoFlags      = out->infoFlags;
1048            call.Version        = 0; /* -1; unsigned char cannot be negative */
1049            call.WriteV         = isBufferedOutput ? BufferingWriteV : writev;
1050           
1051            if (writer->writeData)
1052            {
1053                res = writer->writeData(&call);
1054            }
1055
1056            if (res < 0)
1057            {
1058                linuxdvb_err("failed to write data %d - %d\n", res, errno);
1059                linuxdvb_err("%s\n", strerror(errno));
1060                ret = cERR_LINUXDVB_ERROR;
1061            }
1062        }
1063
1064        free(Encoding);
1065    }
1066
1067    return ret;
1068}
1069
1070static int reset(Context_t  *context)
1071{
1072    int ret = cERR_LINUXDVB_NO_ERROR;
1073    Writer_t*   writer;
1074    char * Encoding = NULL;
1075
1076    context->manager->video->Command(context, MANAGER_GETENCODING, &Encoding);
1077
1078    writer = getWriter(Encoding);
1079
1080    if (writer == NULL)
1081    {
1082        linuxdvb_err("unknown video codec %s\n",Encoding);
1083        ret = cERR_LINUXDVB_ERROR;
1084    } else
1085    {
1086        writer->reset();
1087    }
1088
1089    free(Encoding);
1090
1091    context->manager->audio->Command(context, MANAGER_GETENCODING, &Encoding);
1092
1093    writer = getWriter(Encoding);
1094
1095    if (writer == NULL)
1096    {
1097        linuxdvb_err("unknown video codec %s\n",Encoding);
1098        ret = cERR_LINUXDVB_ERROR;
1099    } else
1100    {
1101        writer->reset();
1102    }
1103
1104    free(Encoding);
1105   
1106    if (isBufferedOutput)
1107        LinuxDvbBuffFlush(context);
1108
1109    return ret;
1110}
1111
1112static int Command(void  *_context, OutputCmd_t command, void * argument) {
1113    Context_t* context = (Context_t*) _context;
1114    int ret = cERR_LINUXDVB_NO_ERROR;
1115   
1116    linuxdvb_printf(50, "Command %d\n", command);
1117
1118    switch(command) {
1119    case OUTPUT_OPEN: {
1120        ret = LinuxDvbOpen(context, (char*)argument);
1121        break;
1122    }
1123    case OUTPUT_CLOSE: {
1124        ret = LinuxDvbClose(context, (char*)argument);
1125        reset(context);
1126        sCURRENT_PTS = 0;
1127        break;
1128    }
1129    case OUTPUT_PLAY: { // 4
1130        sCURRENT_PTS = 0;
1131        ret = LinuxDvbPlay(context, (char*)argument);
1132        break;
1133    }
1134    case OUTPUT_STOP: {
1135        reset(context);
1136        ret = LinuxDvbStop(context, (char*)argument);
1137        sCURRENT_PTS = 0;
1138        break;
1139    }
1140    case OUTPUT_FLUSH: {
1141        ret = LinuxDvbFlush(context, (char*)argument);
1142        reset(context);
1143        sCURRENT_PTS = 0;
1144        break;
1145    }
1146    case OUTPUT_PAUSE: {
1147        ret = LinuxDvbPause(context, (char*)argument);
1148        break;
1149    }
1150    case OUTPUT_CONTINUE: {
1151        ret = LinuxDvbContinue(context, (char*)argument);
1152        break;
1153    }
1154    case OUTPUT_FASTFORWARD: {
1155        return LinuxDvbFastForward(context, (char*)argument);
1156        break;
1157    }
1158    case OUTPUT_REVERSE: {
1159        return LinuxDvbReverse(context, (char*)argument);
1160        break;
1161    }
1162    case OUTPUT_AVSYNC: {
1163        ret = LinuxDvbAVSync(context, (char*)argument);
1164        break;
1165    }
1166    case OUTPUT_CLEAR: {
1167        reset(context);
1168        ret = LinuxDvbClear(context, (char*)argument);
1169        reset(context);
1170        sCURRENT_PTS = 0;
1171        break;
1172    }
1173    case OUTPUT_PTS: {
1174        unsigned long long int pts = 0;
1175        ret = LinuxDvbPts(context, &pts);
1176        *((unsigned long long int*)argument) = (unsigned long long int)pts;
1177        break;
1178    }
1179    case OUTPUT_SWITCH: {
1180        ret = LinuxDvbSwitch(context, (char*)argument);
1181        break;
1182    }
1183    case OUTPUT_SLOWMOTION: {
1184        return LinuxDvbSlowMotion(context, (char*)argument);
1185        break;
1186    }
1187    case OUTPUT_AUDIOMUTE: {
1188        return LinuxDvbAudioMute(context, (char*)argument);
1189        break;
1190    }
1191    case OUTPUT_DISCONTINUITY_REVERSE: {
1192        return LinuxDvbReverseDiscontinuity(context, (int*)argument);
1193        break;
1194    }
1195    case OUTPUT_GET_FRAME_COUNT: {
1196        unsigned long long int frameCount = 0;
1197        ret = LinuxDvbGetFrameCount(context, &frameCount);
1198        *((unsigned long long int*)argument) = (unsigned long long int)frameCount;
1199        break;
1200    }
1201    case OUTPUT_GET_PROGRESSIVE: {
1202        ret = cERR_LINUXDVB_NO_ERROR;
1203        *((int*)argument) = videoInfo.progressive;
1204        break;
1205    }
1206    case OUTPUT_SET_BUFFER_SIZE: {
1207        ret = cERR_LINUXDVB_ERROR;
1208        if (!isBufferedOutput)
1209        {
1210            uint32_t bufferSize = *((uint32_t*)argument);
1211            ret = cERR_LINUXDVB_NO_ERROR;
1212            if (bufferSize > 0)
1213            {
1214                LinuxDvbBuffSetSize(bufferSize);
1215                isBufferedOutput = true;
1216            }
1217        }
1218        break;
1219    }
1220    case OUTPUT_GET_BUFFER_SIZE: {
1221        ret = cERR_LINUXDVB_NO_ERROR;
1222        *((uint32_t*)argument) = LinuxDvbBuffGetSize();
1223        break;
1224    }
1225    default:
1226        linuxdvb_err("ContainerCmd %d not supported!\n", command);
1227        ret = cERR_LINUXDVB_ERROR;
1228        break;
1229    }
1230
1231    linuxdvb_printf(50, "exiting with value %d\n", ret);
1232
1233    return ret;
1234}
1235
1236static char *LinuxDvbCapabilities[] = { "audio", "video", NULL };
1237
1238struct Output_s LinuxDvbOutput = {
1239    "LinuxDvb",
1240    &Command,
1241    &Write,
1242    LinuxDvbCapabilities
1243};
Note: See TracBrowser for help on using the repository browser.