source: titan/libeplayer3/output/writer/common/writer.c @ 44970

Last change on this file since 44970 was 44970, checked in by obi, 20 months ago

update player

  • Property svn:executable set to *
File size: 7.7 KB
Line 
1/*
2 * linuxdvb output/writer handling.
3 *
4 * konfetti 2010
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22/* ***************************** */
23/* Includes                      */
24/* ***************************** */
25#include <stdlib.h>
26#include <string.h>
27#include <errno.h>
28#include <pthread.h>
29
30#include "misc.h"
31#include "writer.h"
32#include "common.h"
33#include "debug.h"
34
35/* ***************************** */
36/* Makros/Constants              */
37/* ***************************** */
38#define getDVBMutex(pmtx) do { if (pmtx) pthread_mutex_lock(pmtx);} while(false);
39#define releaseDVBMutex(pmtx) do { if (pmtx) pthread_mutex_unlock(pmtx);} while(false);
40
41/* ***************************** */
42/* Types                         */
43/* ***************************** */
44typedef enum {
45    DVB_STS_UNKNOWN,
46    DVB_STS_SEEK,
47    DVB_STS_PAUSE,
48    DVB_STS_EXIT
49} DVBState_t;
50
51/* ***************************** */
52/* Varaibles                     */
53/* ***************************** */
54
55static Writer_t * AvailableWriter[] = {
56    &WriterAudioAAC,
57    &WriterAudioAACLATM,
58    &WriterAudioAACPLUS,
59    &WriterAudioAC3,
60    &WriterAudioEAC3,
61    &WriterAudioMP3,
62    &WriterAudioMPEGL3,
63    &WriterAudioPCM,
64    &WriterAudioIPCM,
65    &WriterAudioLPCM,
66    &WriterAudioDTS,
67    &WriterAudioWMA,
68    &WriterAudioWMAPRO,
69    &WriterAudioOPUS,
70    &WriterAudioVORBIS,
71
72    &WriterVideoH264,
73    &WriterVideoH265,
74    &WriterVideoH263,
75    &WriterVideoMPEG4,
76    &WriterVideoMPEG2,
77    &WriterVideoMPEG1,
78    &WriterVideoVC1,
79    &WriterVideoDIVX3,
80    &WriterVideoVP6,
81    &WriterVideoVP8,
82    &WriterVideoVP9,
83    &WriterVideoFLV,
84    &WriterVideoWMV,
85    &WriterVideoMJPEG,
86    &WriterVideoRV40,
87    &WriterVideoRV30,
88    &WriterVideoAVS2,
89    NULL
90};
91
92/* ***************************** */
93/* Prototypes                    */
94/* ***************************** */
95
96/* ***************************** */
97/*  Functions                    */
98/* ***************************** */
99ssize_t WriteWithRetry(Context_t *context, int pipefd, int fd, void *pDVBMtx, const void *buf, int size)
100{
101    fd_set rfds;
102    fd_set wfds;
103
104    ssize_t ret;
105    int retval = -1;
106    int maxFd = pipefd > fd ? pipefd : fd;
107    struct timeval tv;
108
109//    while(size > 0 && !context->playback->isSeeking)
110    while(size > 0 && 0 == PlaybackDieNow(0) && !context->playback->isSeeking)
111    {
112        FD_ZERO(&rfds);
113        FD_ZERO(&wfds);
114
115        FD_SET(pipefd, &rfds);
116        FD_SET(fd, &wfds);
117
118        /* When we PAUSE LINUX DVB outputs buffers, then audio/video buffers
119         * will continue to be filled. Unfortunately, in such case after resume
120         * select() will never return with fd set - bug in DVB drivers?
121         * There are to workarounds possible:
122         *   1. write to pipe at resume to return from select() immediately
123         *   2. make timeout select(), limit max time spend in the select()
124         *      to for example 0,1s
125         *   (at now first workaround is used)
126         */
127        //tv.tv_sec = 0;
128        //tv.tv_usec = 100000; // 100ms
129       
130        retval = select(maxFd + 1, &rfds, &wfds, NULL, NULL); //&tv);
131        if (retval < 0)
132        {
133            break;
134        }
135       
136        //if (retval == 0)
137        //{
138        //    //printf("RETURN FROM SELECT DUE TO TIMEOUT\n");
139        //    continue;
140        //}
141       
142        if(FD_ISSET(pipefd, &rfds))
143        {
144            FlushPipe(pipefd);
145            //printf("RETURN FROM SELECT DUE TO pipefd SET\n");
146            continue;
147        }
148       
149        if(FD_ISSET(fd, &wfds))
150        {
151            ret = write(fd, buf, size);
152            if (ret < 0)
153            {
154                switch(errno)
155                {
156                    case EINTR:
157                    case EAGAIN:
158                        continue;
159                    default:
160                        retval = -3;
161                        break;
162                }
163                if (retval < 0)
164                {
165                    break;
166                }
167               
168                return ret;
169            }
170            else if (ret == 0)
171            {
172                // printf("This should not happen. Select return fd ready to write, but write return 0, errno [%d]\n", errno);
173                // wait 10ms before next try
174                tv.tv_sec = 0;
175                tv.tv_usec = 10000; // 10ms
176                retval = select(pipefd + 1, &rfds, NULL, NULL, &tv);
177                if (retval)
178                    FlushPipe(pipefd);
179                continue;
180            }
181           
182            size -= ret;
183            buf += ret;
184        }
185    }
186    return 0;
187}
188
189ssize_t write_with_retry(int fd, const void *buf, int size)
190{
191    ssize_t ret;
192    int retval = 0;
193//    while(size > 0 && 0 == PlaybackDieNow(0))
194    while(size > 0)
195    {
196        ret = write(fd, buf, size);
197        if (ret < 0)
198        {
199            switch(errno)
200            {
201                case EINTR:
202                case EAGAIN:
203                    usleep(1000);
204                    continue;
205                default:
206                    retval = -3;
207                    break;
208            }
209            if (retval < 0)
210            {
211                break;
212            }
213        }
214           
215        if (ret < 0)
216        {
217            return ret;
218        }
219       
220        size -= ret;
221        buf += ret;
222       
223        if(size > 0)
224        {
225            if( usleep(1000) )
226            {
227                writer_err("usleep error \n");
228            }
229        }
230    }
231    return 0;
232}
233
234ssize_t writev_with_retry(int fd, const struct iovec *iov, int ic)
235{
236    ssize_t len = 0;
237    int i = 0;
238    for(i=0; i<ic; ++i)
239    {
240        write_with_retry(fd, iov[i].iov_base, iov[i].iov_len);
241        len += iov[i].iov_len;
242        if(PlaybackDieNow(0))
243        {
244//            return -1;
245        }
246    }
247    return len;
248}
249
250Writer_t* getWriter(char* encoding)
251{
252    int i;
253
254    for (i = 0; AvailableWriter[i] != NULL; i++)
255    {
256        if (strcmp(AvailableWriter[i]->caps->textEncoding, encoding) == 0)
257        {
258            writer_printf(50, "%s: found writer \"%s\" for \"%s\"\n", __func__, AvailableWriter[i]->caps->name, encoding);
259            return AvailableWriter[i];
260        }
261    }
262
263    writer_printf(1, "%s: no writer found for \"%s\"\n", __func__, encoding);
264
265    return NULL;
266}
267
268Writer_t* getDefaultVideoWriter()
269{
270    int i;
271
272    for (i = 0; AvailableWriter[i] != NULL; i++)
273    {
274        if (strcmp(AvailableWriter[i]->caps->textEncoding, "V_MPEG2") == 0)
275        {
276            writer_printf(50, "%s: found writer \"%s\"\n", __func__, AvailableWriter[i]->caps->name);
277            return AvailableWriter[i];
278        }
279    }
280
281    writer_printf(1, "%s: no writer found\n", __func__);
282
283    return NULL;
284}
285
286Writer_t* getDefaultAudioWriter()
287{
288    int i;
289
290    for (i = 0; AvailableWriter[i] != NULL; i++)
291    {
292        if (strcmp(AvailableWriter[i]->caps->textEncoding, "A_MP3") == 0)
293        {
294            writer_printf(50, "%s: found writer \"%s\"\n", __func__, AvailableWriter[i]->caps->name);
295            return AvailableWriter[i];
296        }
297    }
298
299    writer_printf(1, "%s: no writer found\n", __func__);
300
301    return NULL;
302}
303
Note: See TracBrowser for help on using the repository browser.