]> git.pld-linux.org Git - packages/mythtv.git/blame - mythtv-dshowserver-0.22.patch
- updated to build snv fixes for stable mythtv-0.22
[packages/mythtv.git] / mythtv-dshowserver-0.22.patch
CommitLineData
765b517e 1Index: 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 {
401Index: 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}
413Index: 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+
815Index: 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.184888 seconds and 4 git commands to generate.