]> git.pld-linux.org Git - packages/mythtv.git/blob - mythtv-dshowserver-0.22.patch
- updated to build snv fixes for stable mythtv-0.22
[packages/mythtv.git] / mythtv-dshowserver-0.22.patch
1 Index: libs/libmythtv/avformatdecoder.cpp
2 ===================================================================
3 --- libs/libmythtv/avformatdecoder.cpp.orig     2010-01-02 15:05:30.000000000 -0800
4 +++ libs/libmythtv/avformatdecoder.cpp  2010-01-02 15:26:03.000000000 -0800
5 @@ -2,12 +2,16 @@
6  #include <cassert>
7  #include <unistd.h>
8  #include <cmath>
9 +#include <fcntl.h>
10  
11  // C++ headers
12  #include <algorithm>
13  #include <iostream>
14  using namespace std;
15  
16 +// QT headers
17 +#include "qdir.h"
18 +
19  // MythTV headers
20  #include "mythconfig.h"
21  #include "avformatdecoder.h"
22 @@ -53,6 +57,7 @@
23  #include "avio.h"
24  #include "../libmythmpeg2/mpeg2.h"
25  #include "ivtv_myth.h"
26 +#include "libavformat/riff.h"
27  }
28  
29  #define LOC QString("AFD: ")
30 @@ -181,21 +186,56 @@
31  
32  typedef MythDeque<AVFrame*> avframe_q;
33  
34 +struct vd_struct {
35 +  union {
36 +    uint32_t ret;
37 +    uint32_t cmd;
38 +  };
39 +  uint32_t buflen;
40 +  uint64_t pts;
41 +  uint32_t unused[8];
42 +} __attribute__((__packed__));
43 +
44 +enum {
45 +  VD_END = 1,
46 +  VD_DECODE = 2,
47 +  VD_SEEK = 3,
48 +  VD_HAS_BIH = 0x10000,
49 +  VD_VERSION_MASK = 0xFFFF,
50 +};
51 +#include "timeout_sem.c"
52 +#include <sys/mman.h>
53 +
54 +typedef struct {
55 +    int fd;
56 +    void *mem;
57 +    char *data;
58 +    char *picture;
59 +    int picsize;
60 +    void *sem;
61 +    struct vd_struct *vd;
62 +} ds_mpi_t;
63 +
64 +
65  /**
66   * Management of libmpeg2 decoding
67   */
68  class AvFormatDecoderPrivate
69  {
70    public:
71 -    AvFormatDecoderPrivate(bool allow_libmpeg2)
72 -        : mpeg2dec(NULL), dvdvdec(NULL), allow_mpeg2dec(allow_libmpeg2) { ; }
73 -   ~AvFormatDecoderPrivate() { DestroyMPEG2(); }
74 +    AvFormatDecoderPrivate(bool allow_libmpeg2, bool allow_directshow)
75 +        : mpeg2dec(NULL), dvdvdec(NULL), allow_mpeg2dec(allow_libmpeg2),
76 +          ds_mpi(NULL), allow_dshow(allow_directshow) { ; }
77 +   ~AvFormatDecoderPrivate() { DestroyMPEG2(); DestroyDirectShow();}
78  
79      bool InitMPEG2(const QString &dec);
80      bool HasMPEG2Dec(void) const { return (bool)(mpeg2dec); }
81      bool HasDVDVDec(void) const { return (bool)(dvdvdec); }
82      bool HasDecoder(void) const { return HasMPEG2Dec() || HasDVDVDec(); }
83  
84 +    bool InitDirectShow(AVCodecContext *enc);
85 +    bool HasDirectShow() const { return (bool)(ds_mpi); }
86 +
87      void DestroyMPEG2();
88      void ResetMPEG2();
89      int DecodeMPEG2Video(AVCodecContext *avctx, AVFrame *picture,
90 @@ -205,13 +245,252 @@
91      bool SetVideoSize(const QSize &video_dim);
92      DVDV *GetDVDVDecoder(void) { return dvdvdec; }
93  
94 +    void DestroyDirectShow();
95 +    void ResetDirectShow();
96 +    int DecodeDirectShowVideo(AVCodecContext *avctx, AVFrame *picture,
97 +                         int *got_picture_ptr, uint8_t *buf, int buf_size,
98 +                         long long *pts);
99 +
100    private:
101      mpeg2dec_t *mpeg2dec;
102      DVDV       *dvdvdec;
103      bool        allow_mpeg2dec;
104 +    ds_mpi_t   *ds_mpi;
105 +    bool        allow_dshow;
106      avframe_q   partialFrames;
107  };
108  
109 +bool AvFormatDecoderPrivate::InitDirectShow(AVCodecContext *enc)
110 +{
111 +    typedef struct {
112 +        uint32_t f1;
113 +        uint16_t f2;
114 +        uint16_t f3;
115 +        uint8_t  f4[8];
116 +    } GUID;
117 +    unsigned int codec_tag;
118 +    const struct AVCodecTag *bmp_taglists[] = {ff_codec_bmp_tags, 0};
119 +
120 +    codec_tag = av_codec_get_tag(bmp_taglists, enc->codec_id);
121 +    VERBOSE(VB_IMPORTANT, LOC + QString("Trying DirectShow for FOURCC 0x%1")
122 +            .arg(codec_tag, 8, 16));
123 +    if (!allow_dshow)
124 +        return false;
125 +    DestroyDirectShow();
126 +    if (codec_tag == 0) {
127 +        allow_dshow = false;
128 +        return false;
129 +    }
130 +//    QString dec = gContext->GetSetting("UseDirectShowVideoDecoder", "no");
131 +    QString dec = "yes";
132 +
133 +    if (dec == "yes")
134 +    {
135 +        bool found = false;
136 +        QString codec;
137 +        GUID guid = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
138 +        QString codec_file = QDir::homePath() +
139 +                            QString("/.mythtv/dshowcodecs");
140 +        if (! QFileInfo(codec_file).isFile()) {
141 +            allow_dshow = false;
142 +            return false;
143 +        }
144 +        QString videotype;
145 +        AVCodec *avc = avcodec_find_decoder(enc->codec_id);
146 +        if (! avc) {
147 +           allow_dshow = false;
148 +           return false;
149 +        }
150 +        videotype = avc->name;
151 +        QFile fh (codec_file);
152 +        QString line;
153 +        fh.open(QIODevice::ReadOnly);
154 +        while (! fh.atEnd() && ! found) {
155 +            QStringList fourc, guidlist;
156 +            line = fh.readLine(1024);
157 +            codec = line.section(':', 0, 0).simplified();
158 +            fourc = line.section(':', 1, 1).split(",");
159 +            guidlist  = line.section(':', 2, 2).split(",");
160 +            if (guidlist.count() != 11)
161 +                continue;
162 +            for (QStringList::Iterator it = fourc.begin();
163 +                 it != fourc.end(); it++)
164 +            {
165 +                if ((*it).simplified() == videotype)
166 +                {
167 +                    guid.f1 = guidlist[0].toUInt(0, 0);
168 +                    guid.f2 = guidlist[1].toUShort(0, 0);
169 +                    guid.f3 = guidlist[2].toUShort(0, 0);
170 +                    for (int i = 0; i < 8; i++)
171 +                        guid.f4[i] = guidlist[i + 3].toUShort(0, 0);
172 +                    found = true;
173 +                }
174 +            }
175 +            if (found)
176 +                break;
177 +        }
178 +        fh.close();
179 +        if (found) {
180 +            int ret;
181 +            char cmd[255], shm[80];
182 +            uint32_t out_fmt;
183 +            int bpp;
184 +            int port = 0;
185 +            //out_fmt = 0x30323449; bpp = 12; //I420 12bpp
186 +            out_fmt = 0x32595559; bpp = 16; //YUY2 16bpp
187 +            snprintf(cmd, 255, "dshowserver --codec %s --size %dx%d "
188 +                     "--guid %08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x "
189 +                     "--fourc 0x%08x --bits %d --outfmt 0x%08x --pid %d --id %x "
190 +                     "--port %d %s&",
191 +                codec.toAscii().constData(), enc->width, enc->height,
192 +                guid.f1, guid.f2, guid.f3,
193 +                      guid.f4[0], guid.f4[1], guid.f4[2], guid.f4[3],
194 +                      guid.f4[4], guid.f4[5], guid.f4[6], guid.f4[7],
195 +                codec_tag, bpp, out_fmt, getpid(), *(int *)pthread_self(), port,
196 +                ((print_verbose_messages & VB_PLAYBACK) == VB_PLAYBACK ?
197 +                            "-d" : ""));
198 +            ds_mpi = new ds_mpi_t;
199 +            snprintf(shm, 80, "/dshow_shm.%x", *(int *)pthread_self());
200 +            ds_mpi->fd = shm_open(shm, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
201 +
202 +            ds_mpi->picsize =  enc->width * enc->height * bpp / 8;
203 +            int extra = 0;
204 +            if (enc->height % 16)
205 +                extra = (16 - enc->height % 16) * bpp / 8;
206 +            int memsize = sizeof(struct vd_struct) + enc->width * enc->height +
207 +                          ds_mpi->picsize + extra;
208 +            ftruncate(ds_mpi->fd, memsize);
209 +            ds_mpi->mem = mmap(NULL, memsize, PROT_READ | PROT_WRITE,
210 +                               MAP_SHARED, ds_mpi->fd, 0);
211 +            if(ds_mpi->mem == MAP_FAILED) {
212 +              perror("mmap");
213 +              allow_dshow = false;
214 +              return false;
215 +            }
216 +            memset((char *)ds_mpi->mem, 0, sizeof(struct vd_struct));
217 +
218 +            if (extra)
219 +                memset((char *)ds_mpi->mem + (memsize - extra), 0, extra);
220 +            ds_mpi->vd = (struct vd_struct *)ds_mpi->mem;
221 +            ds_mpi->data = ((char *)ds_mpi->mem) + sizeof(struct vd_struct);
222 +            ds_mpi->picture = ds_mpi->data + enc->width * enc->height;
223 +
224 +            //Create read/write semaphores in locked state
225 +            ds_mpi->sem = timed_seminit(DS_SOCKET, &port, 1);
226 +            //ds_mpi->sem = timed_seminit(DS_SEMAPHORE, *(int *)pthread_self(), 1);
227 +
228 +            myth_system(cmd);
229 +            ret = timed_semwait(ds_mpi->sem, 10);
230 +            shm_unlink(shm);
231 +            if(ret <= 0) {
232 +                VERBOSE(VB_IMPORTANT, LOC + "DirectShow filter failed");
233 +            } else {
234 +                VERBOSE(VB_IMPORTANT, LOC + "Found DirectShow filter");
235 +                return true;
236 +            }
237 +       }
238 +    }
239 +    allow_dshow = false;
240 +    return false;
241 +}
242 +
243 +void AvFormatDecoderPrivate::DestroyDirectShow()
244 +{
245 +    if (ds_mpi)
246 +    {
247 +        VERBOSE(VB_PLAYBACK, LOC + "Destroying filter");
248 +        ds_mpi->vd->cmd = VD_END; //'1' is cmd for terminating
249 +        timed_sempost(ds_mpi->sem);
250 +        close(ds_mpi->fd);
251 +       timed_semdelete(ds_mpi->sem);
252 +        delete ds_mpi;
253 +        ds_mpi = NULL;
254 +    }
255 +}
256 +
257 +void AvFormatDecoderPrivate::ResetDirectShow()
258 +{
259 +    if (ds_mpi) {
260 +      ds_mpi->vd->cmd = VD_SEEK; //'3' is cmd for seek
261 +      timed_sempost(ds_mpi->sem);
262 +      timed_semwait(ds_mpi->sem, 10);
263 +    }
264 +}
265 +
266 +void yuy2i420(AVFrame *dst, char *src, int w, int l)
267 +{
268 +  uint8_t *y, *u, *v;
269 +  y = dst->data[0];
270 +  u = dst->data[1];
271 +  v = dst->data[2];
272 +  int i,j;
273 +  for(i=0; i < l; i++) {
274 +    for(j=0; j < w; j+=2) {
275 +      *(y++) = *(src++);
276 +      *(u++) = *(src++);
277 +      *(y++) = *(src++);
278 +      *(v++) = *(src++);
279 +    }
280 +    i++;
281 +    for(j=0; j < w; j+=2) {
282 +      *(y++) = *src;
283 +      src+=2;
284 +      *(y++) = *src;
285 +      src+=2;
286 +   }
287 +  }
288 +}
289 +
290 +int AvFormatDecoderPrivate::DecodeDirectShowVideo(AVCodecContext *avctx,
291 +                                             AVFrame *picture,
292 +                                             int *got_picture_ptr,
293 +                                             uint8_t *buf, int buf_size,
294 +                                             long long *pts)
295 +{
296 +    int ret;
297 +    ds_mpi->vd->cmd = VD_DECODE; //'1' is cmd for decoding
298 +    memcpy(ds_mpi->data, buf, buf_size);
299 +    ds_mpi->vd->buflen = buf_size;
300 +    ds_mpi->vd->pts = (uint64_t)*pts;
301 +    timed_sempost(ds_mpi->sem);
302 +    ret = timed_semwait(ds_mpi->sem, 10);
303 +    if (ret == 1 && ds_mpi->vd->ret && ! (ds_mpi->vd->ret & (1<<31))) {
304 +        *got_picture_ptr = 1;
305 +        if (ds_mpi->vd->pts) {
306 +            *pts = (long long)ds_mpi->vd->pts;
307 +        }
308 +        picture->interlaced_frame = (ds_mpi->vd->ret & 10) ? true : false;
309 +        avctx->get_buffer(avctx, picture);
310 +#if 0  //Using YV12
311 +        if(avctx->height & 0x0f) {
312 +           unsigned long pos, pos1, siz = avctx->height * avctx->width;
313 +           memcpy(picture->data[0], ds_mpi->picture, siz);
314 +           pos = siz;
315 +           pos1 = siz + avctx->width * (16 - avctx->height % 16);
316 +           siz /= 4;
317 +           memcpy(picture->data[0]+pos1, ds_mpi->picture+pos, siz);
318 +           pos+=siz;
319 +           pos1+=siz + avctx->width * ( 16 - avctx->height % 16) / 4;
320 +           memcpy(picture->data[0]+pos1, ds_mpi->picture+pos, siz);
321 +        } else {
322 +          memcpy(picture->data[0], ds_mpi->picture, ds_mpi->picsize);
323 +        }
324 +#else //Using YUY2
325 +        //YUY2 is a packed format so padding is easier
326 +        //int extra = 0;
327 +        //if(avctx->height % 16)
328 +            //extra = (16 - avctx->height % 16);
329 +        yuy2i420(picture, ds_mpi->picture,
330 +                 avctx->width, avctx->height);
331 +#endif
332 +    } else {
333 +      *got_picture_ptr = 0;
334 +    }
335 +    return buf_size;
336 +}
337 +
338 +/*************************************************/
339 +
340  /**
341   * \brief Initialise either libmpeg2, or DVDV (Mac HW accel), to do decoding
342   *
343 @@ -434,7 +713,7 @@
344                                   bool allow_libmpeg2,
345                                   bool no_hardware_decode)
346      : DecoderBase(parent, pginfo),
347 -      d(new AvFormatDecoderPrivate(allow_libmpeg2)),
348 +      d(new AvFormatDecoderPrivate(allow_libmpeg2, true)),
349        is_db_ignored(gContext->IsDatabaseIgnored()),
350        m_h264_parser(new H264Parser()),
351        ic(NULL),
352 @@ -723,6 +1002,7 @@
353                  avcodec_flush_buffers(enc);
354          }
355          d->ResetMPEG2();
356 +        d->ResetDirectShow();
357      }
358  
359      // Discard all the queued up decoded frames
360 @@ -1673,6 +1953,9 @@
361                          }
362                      }
363  
364 +                    if (CODEC_ID_H264 == enc->codec_id)
365 +                      force_xv = true;
366 +
367                      MythCodecID mcid;
368                      mcid = VideoOutputXv::GetBestSupportedCodec(
369                          /* disp dim     */ width, height,
370 @@ -1754,6 +2037,7 @@
371                  }
372  
373                  // Initialize alternate decoders when needed...
374 +              if (! d->InitDirectShow(enc))
375                  if ((dec == "libmpeg2") &&
376                      (CODEC_IS_MPEG(enc->codec_id)))
377                  {
378 @@ -3905,7 +4189,21 @@
379                      int gotpicture = 0;
380  
381                      avcodeclock.lock();
382 -                    if (d->HasDecoder())
383 +/*                    printf("Trying: %d\n",len);
384 +                    if (0) {
385 +                      static int fnum = 0;
386 +                      char str[80];
387 +                      int fh;
388 +                      sprintf(str,"enc%d", fnum++);;
389 +                      fh = open(str, 01101,00777);
390 +                      write(fh, ptr, len);
391 +                      close(fh);
392 +                    }
393 +*/
394 +                    if (d->HasDirectShow())
395 +                        ret = d->DecodeDirectShowVideo(context, &mpa_pic,
396 +                                                  &gotpicture, ptr, len, &pts);
397 +                    else if (d->HasDecoder())
398                      {
399                          if (decodeStillFrame)
400                          {
401 Index: libs/libmythtv/libmythtv.pro
402 ===================================================================
403 --- libs/libmythtv/libmythtv.pro.orig   2010-01-02 15:05:30.000000000 -0800
404 +++ libs/libmythtv/libmythtv.pro        2010-01-02 15:06:01.000000000 -0800
405 @@ -55,6 +55,7 @@
406  using_hdhomerun: LIBS += -L../libmythhdhomerun -lmythhdhomerun-$$LIBVERSION
407  using_backend: LIBS += -lmp3lame
408  LIBS += -lz $$EXTRA_LIBS $$QMAKE_LIBS_DYNLOAD
409 +LIBS += -lrt
410  
411  TARGETDEPS += ../libmyth/libmyth-$${MYTH_SHLIB_EXT}
412  TARGETDEPS += ../libavutil/libmythavutil-$${MYTH_SHLIB_EXT}
413 Index: libs/libmythtv/timeout_sem.c
414 ===================================================================
415 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
416 +++ libs/libmythtv/timeout_sem.c        2010-01-02 15:07:56.000000000 -0800
417 @@ -0,0 +1,397 @@
418 +#include <stdio.h>
419 +#include <stdlib.h>
420 +#include <unistd.h>
421 +#include <fcntl.h>
422 +#include <errno.h>
423 +#include <string.h>
424 +
425 +#ifndef __MINGW32__
426 +  #include <netdb.h>
427 +  #include <netinet/in.h>
428 +  #include <sys/socket.h>
429 +  #include <arpa/inet.h>
430 +  #include <sys/wait.h>
431 +
432 +  #define DS_EINPROGRESS EINPROGRESS
433 +  #define DS_ETIMEDOUT   ETIMEDOUT
434 +  #define DS_EWOULDBLOCK EWOULDBLOCK
435 +#else
436 +  #define _WIN32_WINNT 0x0501
437 +  #include <windows.h>
438 +  #include <winsock2.h>
439 +  #include <ws2tcpip.h>
440 +
441 +  #define DS_EINPROGRESS WSAEINPROGRESS
442 +  #define DS_ETIMEDOUT   WSAETIMEDOUT
443 +  #define DS_EWOULDBLOCK WSAEWOULDBLOCK
444 +#endif
445 +
446 +#include "timeout_sem.h"
447 +#ifdef __MINGW32__
448 +  #undef DS_SEMAPHORE
449 +#endif
450 +
451 +#ifdef DS_SEMAPHORE
452 +#include <time.h>
453 +#include <semaphore.h>
454 +#endif
455 +
456 +struct sem {
457 +  int type;
458 +  int initialized;
459 +  int sockfd;
460 +  int listenfd;
461 +  void *id;
462 +  char mutex_rx[1];
463 +  char mutex_tx[1];
464 +#ifdef DS_SEMAPHORE
465 +  sem_t *sem_rd;
466 +  sem_t *sem_wr;
467 +#endif /*DS_SEMAPHORE*/
468 +};
469 +
470 +#ifdef DS_SEMAPHORE
471 +#ifdef __APPLE__
472 +  void ALRMhandler(int sig) {
473 +  }
474 +  int sem_twait(sem_t *sem, int t) {
475 +    int ret;
476 +    alarm(t);
477 +    ret = sem_wait(sem);
478 +    printf("twait complete\n");
479 +    return ret;
480 +  }
481 +  void init_twait() {
482 +    sigset_t none;
483 +    struct sigaction sa;
484 +    sigemptyset(&none);
485 +    sigprocmask(SIG_SETMASK, &none, 0);
486 +
487 +    sa.sa_handler = ALRMhandler;
488 +    sa.sa_flags = 0;
489 +    sigemptyset(&sa.sa_mask);
490 +    sigaction(SIGALRM, &sa, 0);
491 +  }
492 +#else
493 +  int sem_twait(sem_t *sem, int t) {
494 +    struct timespec ts;
495 +    clock_gettime(CLOCK_REALTIME, &ts);
496 +    ts.tv_sec += t;
497 +    return(sem_timedwait(sem, &ts));
498 +  }
499 +  void init_twait() {}
500 +#endif
501 +#endif /*DS_SEMAPHORE */
502 +
503 +int setblocking(int sock, int block)
504 +{
505 +       unsigned long opts;
506 +#ifndef __MINGW32__
507 +       opts = fcntl(sock,F_GETFL);
508 +       if (opts < 0) {
509 +               perror("fcntl(F_GETFL)");
510 +               exit(EXIT_FAILURE);
511 +       }
512 +       opts = block ? (opts & ~O_NONBLOCK)
513 +                     : (opts | O_NONBLOCK);
514 +       if (fcntl(sock,F_SETFL,opts) < 0) {
515 +               perror("fcntl(F_SETFL)");
516 +               exit(EXIT_FAILURE);
517 +       }
518 +#else
519 +       opts = !(block);
520 +       if ( ioctlsocket( sock, FIONBIO, &opts ) == SOCKET_ERROR )
521 +       {
522 +               perror("ioctlsocket");
523 +               exit(EXIT_FAILURE);
524 +       }
525 +#endif
526 +       return 0;
527 +}
528 +
529 +int timed_connect(int sockfd, const struct sockaddr *serv_addr,
530 +                   socklen_t addrlen, int secs) {
531 +  //Socket should already be non-blocking
532 +  int res;
533 +  fd_set myset;
534 +  struct timeval tv;
535 +  int valopt;
536 +  socklen_t lon;
537 +
538 +  // Trying to connect with timeout
539 +  res = connect(sockfd, serv_addr, addrlen);
540 +  if (res < 0 ) {
541 +     if (errno == DS_EINPROGRESS || errno == DS_EWOULDBLOCK || errno == 0) {
542 +        fprintf(stderr, "EINPROGRESS in connect() - selecting\n");
543 +        do {
544 +           tv.tv_sec = secs;
545 +           tv.tv_usec = 0;
546 +           FD_ZERO(&myset);
547 +           FD_SET(sockfd, &myset);
548 +           res = select(sockfd+1, NULL, &myset, &myset, &tv);
549 +           if (res < 0 && errno != EINTR) {
550 +              fprintf(stderr, "Error connecting (select) %d - %s\n", errno, strerror(errno));
551 +              return -1;
552 +           }
553 +           else if (res > 0) {
554 +              // Socket selected for write
555 +              lon = sizeof(int);
556 +              if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void*)(&valopt), &lon) < 0) {
557 +                 fprintf(stderr, "Error in getsockopt() %d - %s\n", errno, strerror(errno));
558 +                 return -1;
559 +              }
560 +              // Check the value returned...
561 +              if (valopt) {
562 +                 fprintf(stderr, "Error in delayed connection() %d - %s\n", valopt, strerror(valopt)
563 +);
564 +                 return -1;
565 +              }
566 +              break;
567 +           }
568 +           else {
569 +              fprintf(stderr, "Timeout in select() - Cancelling!\n");
570 +              return -1;
571 +           }
572 +        } while (1);
573 +     }
574 +     else {
575 +        fprintf(stderr, "Error connecting (connect) %d - %s\n", errno, strerror(errno));
576 +        return -1;
577 +     }
578 +  }
579 +  // I hope that is all
580 +  return 0;
581 +}
582 +int timed_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int secs) {
583 +  //Socket should already be non-blocking
584 +  int res;
585 +  fd_set myset;
586 +  struct timeval tv;
587 +
588 +  tv.tv_sec = secs;
589 +  tv.tv_usec = 0;
590 +  FD_ZERO(&myset);
591 +  FD_SET(sockfd, &myset);
592 +  res = select(sockfd+1, &myset, NULL, NULL, &tv);
593 +  if (res < 0 && errno != EINTR) {
594 +    fprintf(stderr, "Error accepting %d - %s\n", errno, strerror(errno));
595 +    return -1;
596 +  }
597 +  else if (res > 0) {
598 +    // Socket selected for read
599 +    return accept(sockfd, NULL, NULL);
600 +  }
601 +  errno = DS_ETIMEDOUT;
602 +  return -1;
603 +}
604 +int timed_recv(int sockfd, void *buf, size_t len, int flags, int secs) {
605 +  //Socket should already be non-blocking
606 +  int res;
607 +  fd_set myset;
608 +  struct timeval tv;
609 +
610 +  tv.tv_sec = secs;
611 +  tv.tv_usec = 0;
612 +  FD_ZERO(&myset);
613 +  FD_SET(sockfd, &myset);
614 +  res = select(sockfd+1, &myset, NULL, NULL, &tv);
615 +  if (res < 0 && errno != EINTR) {
616 +    fprintf(stderr, "Error accepting %d - %s\n", errno, strerror(errno));
617 +    return -1;
618 +  }
619 +  else if (res > 0) {
620 +    // Socket selected for read
621 +    return recv(sockfd, buf, len, flags);
622 +  }
623 +  errno = DS_ETIMEDOUT;
624 +  return -1;
625 +}
626 +
627 +int timed_sockinit(int *port, int is_server)
628 +{
629 +    int sockfd;  // listen on sock_fd
630 +    struct sockaddr_in my_addr;
631 +    socklen_t peer_addr_size = sizeof(struct sockaddr_in);
632 +    int yes=1;
633 +
634 +#ifdef __MINGW32__
635 +    WSADATA wsaData;
636 +    if(WSAStartup(MAKEWORD(2, 2), &wsaData) !=0) {
637 +      printf("WSAStartup failed\n");
638 +      exit(1);
639 +    }
640 +#endif
641 +
642 +    memset(&my_addr, 0, sizeof(my_addr));
643 +    my_addr.sin_family = AF_INET;
644 +    my_addr.sin_addr.s_addr=INADDR_ANY;
645 +    my_addr.sin_port = *port;
646 +    if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
647 +            perror("server: socket");
648 +            exit(1);
649 +    }
650 +
651 +    setblocking(sockfd, 0);
652 +    if (is_server) {
653 +      if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const char *)&yes,
654 +              sizeof(int)) == -1) {
655 +        perror("setsockopt");
656 +        exit(1);
657 +      }
658 +
659 +      if (bind(sockfd, (struct sockaddr *) &my_addr,  sizeof(struct sockaddr_in)) == -1) {
660 +              close(sockfd);
661 +              perror("server: bind");
662 +              exit(1);
663 +      }
664 +      if (listen(sockfd, 1) == -1) {
665 +        perror("listen");
666 +        exit(1);
667 +      }
668 +      if (getsockname(sockfd, (struct sockaddr *)&my_addr, &peer_addr_size) == -1) {
669 +        perror("getsockname");
670 +        exit(1);
671 +      }
672 +      if(my_addr.sin_port == 0) {
673 +        printf("Failed to get port\n");
674 +        exit(1);
675 +      }
676 +      *port = my_addr.sin_port;
677 +    } else {
678 +      if (timed_connect(sockfd, (struct sockaddr *) &my_addr,  sizeof(struct sockaddr_in), 10) == -1)
679 +      {
680 +        close(sockfd);
681 +        perror("client: connect");
682 +        exit(1);
683 +      }
684 +    }
685 +
686 +    return sockfd;
687 +}
688 +
689 +int timed_semwait(void *_sem, int secs) {
690 +  struct sem *sem = (struct sem *)_sem;
691 +  int ok = -1;
692 +  if(sem->type == DS_SOCKET) {
693 +    if(! sem->initialized) {
694 +      ok = timed_accept(sem->sockfd, NULL, NULL, secs);
695 +      if(ok != -1) {
696 +        sem->listenfd = sem->sockfd;
697 +        sem->sockfd = ok;
698 +        ok = 1;
699 +        sem->initialized = 1;
700 +      }
701 +    } else {
702 +      ok = (timed_recv(sem->sockfd, sem->mutex_rx, 1, 0, secs) == 1);
703 +    }
704 +  }
705 +#ifdef DS_SEMAPHORE
706 +  else if(sem->type == DS_SEMAPHORE) {
707 +    ok = (sem_twait(sem->sem_rd, secs) == 0);
708 +    if(! sem->initialized) {
709 +      timed_semclean(sem);
710 +      sem->initialized = 1;
711 +    }
712 +  }
713 +#endif
714 +  if(!ok && errno == DS_ETIMEDOUT) {
715 +    ok = DS_TIMEOUT;
716 +  }
717 +  return ok;
718 +}
719 +
720 +void timed_sempost(void *_sem) {
721 +  struct sem *sem = (struct sem *)_sem;
722 +  if(sem->type == DS_SOCKET) {
723 +    send(sem->sockfd, sem->mutex_tx, 1, 0);
724 +  }
725 +#ifdef DS_SEMAPHORE
726 +  else if(sem->type == DS_SEMAPHORE) {
727 +    sem_post(sem->sem_wr);
728 +  }
729 +#endif
730 +}
731 +
732 +void timed_semclean(void * _sem) {
733 +#ifdef DS_SEMAPHORE
734 +  struct sem *sem = (struct sem *) _sem;
735 +  if(sem->type == DS_SEMAPHORE) {
736 +    char sem1[80], sem2[80];
737 +    snprintf(sem1, 80, "/dshow_sem1.%s", (char *)sem->id);
738 +    snprintf(sem2, 80, "/dshow_sem2.%s", (char *)sem->id);
739 +    sem_unlink(sem1);
740 +    sem_unlink(sem2);
741 +  }
742 +#endif
743 +}
744 +
745 +void *timed_seminit(unsigned int semtype, void *id, int is_host) {
746 +  struct sem *sem;
747 +  sem = (struct sem *)malloc(sizeof(struct sem));
748 +  memset(sem, 0, sizeof(struct sem));
749 +  sem->type = semtype;
750 +  sem->id = id;
751 +  sem->initialized = !(is_host);
752 +  if(semtype == DS_SOCKET) {
753 +    sem->listenfd = -1;
754 +    sem->sockfd = timed_sockinit((int *)id, is_host);
755 +    if(sem->sockfd == -1) {
756 +      perror("sock_init");
757 +      exit(1);
758 +    }
759 +  }
760 +#ifdef DS_SEMAPHORE
761 +  else if(semtype == DS_SEMAPHORE) {
762 +    char semrd[80], semwr[80];
763 +    init_twait();
764 +    snprintf(semrd, 80, "/dshow_sem%d.%s", is_host ? 2 : 1, (char *)id);
765 +    snprintf(semwr, 80, "/dshow_sem%d.%s", is_host ? 1 : 2, (char *)id);
766 +    if(is_host) {
767 +      sem->sem_rd = sem_open(semrd, O_CREAT, 0644, 0);
768 +      sem->sem_wr = sem_open(semwr, O_CREAT, 0644, 0);
769 +    } else {
770 +      sem->sem_rd = sem_open(semrd, 0);
771 +      sem->sem_wr = sem_open(semwr, 0);
772 +      sem_unlink(semwr);
773 +      sem_unlink(semrd);
774 +    }
775 +    if(sem->sem_rd == SEM_FAILED) {
776 +      timed_semclean(sem);
777 +      perror("sem_open(1)");
778 +      exit(1);
779 +    }
780 +    if(sem->sem_wr == SEM_FAILED) {
781 +      timed_semclean(sem);
782 +      perror("sem_open(2)");
783 +      exit(1);
784 +    }
785 +    //tell calling procedure that we are awake;
786 +    if(! is_host) {
787 +      sem_post(sem->sem_wr);
788 +    }
789 +  }
790 +#endif /*DS_SEMAPHORE*/
791 +  else {
792 +    fprintf(stderr, "Unknown type specified: %d\n", semtype);
793 +    exit(1);
794 +  }
795 +  return sem;
796 +}
797 +
798 +void timed_semdelete(void *_sem) {
799 +  struct sem *sem = (struct sem *) _sem;
800 +  if(sem->type == DS_SOCKET) {
801 +    close(sem->sockfd);
802 +    if(sem->listenfd != -1)
803 +      close(sem->listenfd);
804 +#ifdef DS_SEMAPHORE
805 +  } else if(sem->type == DS_SEMAPHORE) {
806 +    if(! sem->initialized)
807 +      timed_semclean(sem);
808 +    sem_close(sem->sem_wr);
809 +    sem_close(sem->sem_rd);
810 +#endif
811 +  }
812 +  free(sem);
813 +}
814 +
815 Index: libs/libmythtv/timeout_sem.h
816 ===================================================================
817 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
818 +++ libs/libmythtv/timeout_sem.h        2010-01-02 15:07:59.000000000 -0800
819 @@ -0,0 +1,10 @@
820 +#define DS_SOCKET 0x01
821 +#define DS_SEMAPHORE 0x02
822 +
823 +#define DS_TIMEOUT -1
824 +
825 +void *timed_seminit(unsigned int semtype, void *id, int is_host);
826 +void timed_semclean(void *_sem);
827 +void timed_sempost(void *_sem);
828 +int timed_semwait(void *_sem, int secs);
829 +void timed_semdelete(void *_sem);
This page took 0.69252 seconds and 3 git commands to generate.