]> git.pld-linux.org Git - packages/mythtv.git/blame - mythtv-dshowserver_trunk.patch
- updated to build snv fixes for stable mythtv-0.22
[packages/mythtv.git] / mythtv-dshowserver_trunk.patch
CommitLineData
1b2ca44a 1diff -urN mythtv-0.22.orig/libs/libmythtv/avformatdecoder.cpp mythtv-0.22/libs/libmythtv/avformatdecoder.cpp
2--- mythtv-0.22.orig/libs/libmythtv/avformatdecoder.cpp 2009-02-17 19:57:44.000000000 +0100
3+++ mythtv-0.22/libs/libmythtv/avformatdecoder.cpp 2009-03-02 20:04:25.000000000 +0100
4@@ -2,12 +2,16 @@
5 #include <cassert>
6 #include <unistd.h>
7 #include <cmath>
8+#include <fcntl.h>
9
10 // C++ headers
11 #include <algorithm>
12 #include <iostream>
13 using namespace std;
14
15+// QT headers
16+#include "qdir.h"
17+
18 // MythTV headers
19 #include "mythconfig.h"
20 #include "avformatdecoder.h"
21@@ -53,6 +57,7 @@
22 #include "avio.h"
23 #include "../libmythmpeg2/mpeg2.h"
24 #include "ivtv_myth.h"
25+#include "libavformat/riff.h"
26 }
27
28 #define LOC QString("AFD: ")
29@@ -149,21 +154,56 @@
30
31 typedef MythDeque<AVFrame*> avframe_q;
32
33+struct vd_struct {
34+ union {
35+ uint32_t ret;
36+ uint32_t cmd;
37+ };
38+ uint32_t buflen;
39+ uint64_t pts;
40+ uint32_t unused[8];
41+} __attribute__((__packed__));
42+
43+enum {
44+ VD_END = 1,
45+ VD_DECODE = 2,
46+ VD_SEEK = 3,
47+ VD_HAS_BIH = 0x10000,
48+ VD_VERSION_MASK = 0xFFFF,
49+};
50+
51+#include <semaphore.h>
52+#include <sys/mman.h>
53+typedef struct {
54+ int fd;
55+ void *mem;
56+ char *data;
57+ char *picture;
58+ int picsize;
59+ sem_t *sem_rd;
60+ sem_t *sem_wr;
61+ struct vd_struct *vd;
62+} ds_mpi_t;
63+
64 /**
65 * Management of libmpeg2 decoding
66 */
67 class AvFormatDecoderPrivate
68 {
69 public:
70- AvFormatDecoderPrivate(bool allow_libmpeg2)
71- : mpeg2dec(NULL), dvdvdec(NULL), allow_mpeg2dec(allow_libmpeg2) { ; }
72- ~AvFormatDecoderPrivate() { DestroyMPEG2(); }
73+ AvFormatDecoderPrivate(bool allow_libmpeg2, bool allow_directshow)
74+ : mpeg2dec(NULL), dvdvdec(NULL), allow_mpeg2dec(allow_libmpeg2),
75+ ds_mpi(NULL), allow_dshow(allow_directshow) { ; }
76+ ~AvFormatDecoderPrivate() { DestroyMPEG2(); DestroyDirectShow();}
77
78 bool InitMPEG2(const QString &dec);
79 bool HasMPEG2Dec(void) const { return (bool)(mpeg2dec); }
80 bool HasDVDVDec(void) const { return (bool)(dvdvdec); }
81 bool HasDecoder(void) const { return HasMPEG2Dec() || HasDVDVDec(); }
82
83+ bool InitDirectShow(AVCodecContext *enc);
84+ bool HasDirectShow() const { return (bool)(ds_mpi); }
85+
86 void DestroyMPEG2();
87 void ResetMPEG2();
88 int DecodeMPEG2Video(AVCodecContext *avctx, AVFrame *picture,
89@@ -173,13 +213,259 @@
90 bool SetVideoSize(const QSize &video_dim);
91 DVDV *GetDVDVDecoder(void) { return dvdvdec; }
92
93+ void DestroyDirectShow();
94+ void ResetDirectShow();
95+ int DecodeDirectShowVideo(AVCodecContext *avctx, AVFrame *picture,
96+ int *got_picture_ptr, uint8_t *buf, int buf_size,
97+ long long *pts);
98+
99 private:
100 mpeg2dec_t *mpeg2dec;
101 DVDV *dvdvdec;
102 bool allow_mpeg2dec;
103+ ds_mpi_t *ds_mpi;
104+ bool allow_dshow;
105 avframe_q partialFrames;
106 };
107
108+static int sem_twait(sem_t *sem, int t) {
109+ struct timespec ts;
110+ clock_gettime(CLOCK_REALTIME, &ts);
111+ ts.tv_sec += t;
112+ return(sem_timedwait(sem, &ts));
113+}
114+bool AvFormatDecoderPrivate::InitDirectShow(AVCodecContext *enc)
115+{
116+ typedef struct {
117+ uint32_t f1;
118+ uint16_t f2;
119+ uint16_t f3;
120+ uint8_t f4[8];
121+ } GUID;
122+
123+ const struct AVCodecTag *bmp_taglists[] = {codec_bmp_tags, 0};
124+
125+ if(enc->codec_tag == 0)
126+ enc->codec_tag = av_codec_get_tag(bmp_taglists, enc->codec_id);
127+ VERBOSE(VB_IMPORTANT, LOC + QString("Trying DirectShow for FOURCC 0x%1")
128+ .arg(enc->codec_tag, 8, 16));
129+ if (!allow_dshow)
130+ return false;
131+ DestroyDirectShow();
132+ if (enc->codec_tag == 0) {
133+ allow_dshow = false;
134+ return false;
135+ }
136+// QString dec = gContext->GetSetting("UseDirectShowVideoDecoder", "no");
137+ QString dec = "yes";
138+
139+ if (dec == "yes")
140+ {
141+ bool found = false;
142+ QString codec;
143+ GUID guid = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
144+ QString codec_file = QDir::homePath() +
145+ QString("/.mythtv/dshowcodecs");
146+ if (! QFileInfo(codec_file).isFile()) {
147+ allow_dshow = false;
148+ return false;
149+ }
150+ QString videotype;
151+ AVCodec *avc = avcodec_find_decoder(enc->codec_id);
152+ if (! avc) {
153+ allow_dshow = false;
154+ return false;
155+ }
156+ videotype = avc->name;
157+ QFile fh (codec_file);
158+ QString line;
159+ fh.open(QIODevice::ReadOnly);
160+ while (! fh.atEnd() && ! found) {
161+ QStringList fourc, guidlist;
162+ line = fh.readLine(1024);
163+ codec = line.section(':', 0, 0).simplified();
164+ fourc = line.section(':', 1, 1).split(",");
165+ guidlist = line.section(':', 2, 2).split(",");
166+ if (guidlist.count() != 11)
167+ continue;
168+ for (QStringList::Iterator it = fourc.begin();
169+ it != fourc.end(); it++)
170+ {
171+ if ((*it).simplified() == videotype)
172+ {
173+ guid.f1 = guidlist[0].toUInt(0, 0);
174+ guid.f2 = guidlist[1].toUShort(0, 0);
175+ guid.f3 = guidlist[2].toUShort(0, 0);
176+ for (int i = 0; i < 8; i++)
177+ guid.f4[i] = guidlist[i + 3].toUShort(0, 0);
178+ found = true;
179+ }
180+ }
181+ if (found)
182+ break;
183+ }
184+ fh.close();
185+ if (found) {
186+ int ret;
187+ char cmd[255], shm[80], sem1[80], sem2[80];
188+ uint32_t out_fmt;
189+ int bpp;
190+ //out_fmt = 0x30323449; bpp = 12; //I420 12bpp
191+ out_fmt = 0x32595559; bpp = 16; //YUY2 16bpp
192+ snprintf(cmd, 255, "dshowserver -c %s -s %dx%d "
193+ "-g %08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x "
194+ "-f 0x%08x -b %d -o 0x%08x -p %d -i %x %s&",
195+ codec.toAscii().constData(), enc->width, enc->height,
196+ guid.f1, guid.f2, guid.f3,
197+ guid.f4[0], guid.f4[1], guid.f4[2], guid.f4[3],
198+ guid.f4[4], guid.f4[5], guid.f4[6], guid.f4[7],
199+ enc->codec_tag, bpp, out_fmt, getpid(), *(int *)pthread_self(),
200+ ((print_verbose_messages & VB_PLAYBACK) == VB_PLAYBACK ?
201+ "-d" : ""));
202+ ds_mpi = new ds_mpi_t;
203+ snprintf(shm, 80, "/dshow_shm.%x", *(int *)pthread_self());
204+ snprintf(sem1, 80, "/dshow_sem1.%x", *(int *)pthread_self());
205+ snprintf(sem2, 80, "/dshow_sem2.%x", *(int *)pthread_self());
206+ ds_mpi->fd = shm_open(shm, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
207+ ds_mpi->picsize = enc->width * enc->height * bpp / 8;
208+ int extra = 0;
209+ if (enc->height % 16)
210+ extra = (16 - enc->height % 16) * bpp / 8;
211+ int memsize = sizeof(struct vd_struct) + enc->width * enc->height +
212+ ds_mpi->picsize + extra;
213+ ftruncate(ds_mpi->fd, memsize);
214+ ds_mpi->mem = mmap(NULL, memsize, PROT_READ | PROT_WRITE,
215+ MAP_SHARED, ds_mpi->fd, 0);
216+ if(ds_mpi->mem == MAP_FAILED) {
217+ perror("mmap");
218+ allow_dshow = false;
219+ return false;
220+ }
221+ memset((char *)ds_mpi->mem, 0, sizeof(struct vd_struct));
222+
223+ if (extra)
224+ memset((char *)ds_mpi->mem + (memsize - extra), 0, extra);
225+ ds_mpi->vd = (struct vd_struct *)ds_mpi->mem;
226+ ds_mpi->data = ((char *)ds_mpi->mem) + sizeof(struct vd_struct);
227+ ds_mpi->picture = ds_mpi->data + enc->width * enc->height;
228+ //Create read/write semaphores in locked state
229+ ds_mpi->sem_wr = sem_open(sem1, O_CREAT, 0644, 0);
230+ ds_mpi->sem_rd = sem_open(sem2, O_CREAT, 0644, 0);
231+ myth_system(cmd);
232+ ret = sem_twait(ds_mpi->sem_rd, 10);
233+ shm_unlink(shm);
234+ sem_unlink(sem1);
235+ sem_unlink(sem2);
236+ if(ret != 0) {
237+ VERBOSE(VB_IMPORTANT, LOC + "DirectShow filter failed");
238+ } else {
239+ VERBOSE(VB_IMPORTANT, LOC + "Found DirectShow filter");
240+ return true;
241+ }
242+ }
243+ }
244+ allow_dshow = false;
245+ return false;
246+}
247+
248+void AvFormatDecoderPrivate::DestroyDirectShow()
249+{
250+ if (ds_mpi)
251+ {
252+ VERBOSE(VB_PLAYBACK, LOC + "Destroying filter");
253+ ds_mpi->vd->cmd = VD_END; //'1' is cmd for terminating
254+ sem_post(ds_mpi->sem_wr);
255+ close(ds_mpi->fd);
256+ sem_close(ds_mpi->sem_wr);
257+ sem_close(ds_mpi->sem_rd);
258+ delete ds_mpi;
259+ ds_mpi = NULL;
260+ }
261+}
262+
263+void AvFormatDecoderPrivate::ResetDirectShow()
264+{
265+ if (ds_mpi) {
266+ ds_mpi->vd->cmd = VD_SEEK; //'3' is cmd for seek
267+ sem_post(ds_mpi->sem_wr);
268+ sem_twait(ds_mpi->sem_rd, 10);
269+ }
270+}
271+
272+void yuy2i420(AVFrame *dst, char *src, int w, int l)
273+{
274+ uint8_t *y, *u, *v;
275+ y = dst->data[0];
276+ u = dst->data[1];
277+ v = dst->data[2];
278+ int i,j;
279+ for(i=0; i < l; i++) {
280+ for(j=0; j < w; j+=2) {
281+ *(y++) = *(src++);
282+ *(u++) = *(src++);
283+ *(y++) = *(src++);
284+ *(v++) = *(src++);
285+ }
286+ i++;
287+ for(j=0; j < w; j+=2) {
288+ *(y++) = *src;
289+ src+=2;
290+ *(y++) = *src;
291+ src+=2;
292+ }
293+ }
294+}
295+
296+int AvFormatDecoderPrivate::DecodeDirectShowVideo(AVCodecContext *avctx,
297+ AVFrame *picture,
298+ int *got_picture_ptr,
299+ uint8_t *buf, int buf_size,
300+ long long *pts)
301+{
302+ int ret;
303+ ds_mpi->vd->cmd = VD_DECODE; //'1' is cmd for decoding
304+ memcpy(ds_mpi->data, buf, buf_size);
305+ ds_mpi->vd->buflen = buf_size;
306+ ds_mpi->vd->pts = (uint64_t)*pts;
307+ sem_post(ds_mpi->sem_wr);
308+ ret = sem_twait(ds_mpi->sem_rd, 10);
309+ if (ret == 0 && ds_mpi->vd->ret && ! (ds_mpi->vd->ret & (1<<31))) {
310+ *got_picture_ptr = 1;
311+ if (ds_mpi->vd->pts) {
312+ *pts = (long long)ds_mpi->vd->pts;
313+ }
314+ picture->interlaced_frame = (ds_mpi->vd->ret & 10) ? true : false;
315+ avctx->get_buffer(avctx, picture);
316+#if 0 //Using YV12
317+ if(avctx->height & 0x0f) {
318+ unsigned long pos, pos1, siz = avctx->height * avctx->width;
319+ memcpy(picture->data[0], ds_mpi->picture, siz);
320+ pos = siz;
321+ pos1 = siz + avctx->width * (16 - avctx->height % 16);
322+ siz /= 4;
323+ memcpy(picture->data[0]+pos1, ds_mpi->picture+pos, siz);
324+ pos+=siz;
325+ pos1+=siz + avctx->width * ( 16 - avctx->height % 16) / 4;
326+ memcpy(picture->data[0]+pos1, ds_mpi->picture+pos, siz);
327+ } else {
328+ memcpy(picture->data[0], ds_mpi->picture, ds_mpi->picsize);
329+ }
330+#else //Using YUY2
331+ //YUY2 is a packed format so padding is easier
332+ //int extra = 0;
333+ //if(avctx->height % 16)
334+ //extra = (16 - avctx->height % 16);
335+ yuy2i420(picture, ds_mpi->picture,
336+ avctx->width, avctx->height);
337+#endif
338+ } else {
339+ *got_picture_ptr = 0;
340+ }
341+ return buf_size;
342+}
343+
344+/*************************************************/
345+
346 /**
347 * \brief Initialise either libmpeg2, or DVDV (Mac HW accel), to do decoding
348 *
349@@ -401,7 +687,7 @@
350 bool use_null_videoout,
351 bool allow_libmpeg2)
352 : DecoderBase(parent, pginfo),
353- d(new AvFormatDecoderPrivate(allow_libmpeg2)),
354+ d(new AvFormatDecoderPrivate(allow_libmpeg2, true)),
355 is_db_ignored(gContext->IsDatabaseIgnored()),
356 m_h264_parser(new H264Parser()),
357 ic(NULL),
358@@ -684,6 +970,7 @@
359 avcodec_flush_buffers(enc);
360 }
361 d->ResetMPEG2();
362+ d->ResetDirectShow();
363 }
364
365 // Discard all the queued up decoded frames
366@@ -1584,6 +1871,9 @@
367 }
368 }
369
370+ if (CODEC_ID_H264 == enc->codec_id)
371+ force_xv = true;
372+
373 MythCodecID mcid;
374 mcid = VideoOutputXv::GetBestSupportedCodec(
375 /* disp dim */ width, height,
376@@ -1593,6 +1883,7 @@
377 /* test surface */ kCodec_NORMAL_END > video_codec_id,
378 /* force_xv */ force_xv);
379 bool vcd, idct, mc, vdpau;
380+
381 enc->codec_id = (CodecID)
382 myth2av_codecid(mcid, vcd, idct, mc, vdpau);
383
384@@ -1668,6 +1959,7 @@
385 }
386
387 // Initialize alternate decoders when needed...
388+ if (! d->InitDirectShow(enc))
389 if (((dec == "libmpeg2") &&
390 (CODEC_ID_MPEG1VIDEO == enc->codec_id ||
391 CODEC_ID_MPEG2VIDEO == enc->codec_id)) ||
392@@ -3756,7 +4048,21 @@
393 int gotpicture = 0;
394
395 avcodeclock.lock();
396- if (d->HasDecoder())
397+/* printf("Trying: %d\n",len);
398+ if (0) {
399+ static int fnum = 0;
400+ char str[80];
401+ int fh;
402+ sprintf(str,"enc%d", fnum++);;
403+ fh = open(str, 01101,00777);
404+ write(fh, ptr, len);
405+ close(fh);
406+ }
407+*/
408+ if (d->HasDirectShow())
409+ ret = d->DecodeDirectShowVideo(context, &mpa_pic,
410+ &gotpicture, ptr, len, &pts);
411+ else if (d->HasDecoder())
412 {
413 if (decodeStillFrame)
414 {
415diff -urN mythtv-0.22.orig/libs/libmythtv/libmythtv.pro mythtv-0.22/libs/libmythtv/libmythtv.pro
416--- mythtv-0.22.orig/libs/libmythtv/libmythtv.pro 2009-02-17 19:57:44.000000000 +0100
417+++ mythtv-0.22/libs/libmythtv/libmythtv.pro 2009-03-02 19:54:23.000000000 +0100
418@@ -57,6 +57,7 @@
419 }
420 using_backend: LIBS += -lmp3lame
421 LIBS += -lz $$EXTRA_LIBS $$QMAKE_LIBS_DYNLOAD
422+LIBS += -lrt
423
424 TARGETDEPS += ../libmyth/libmyth-$${MYTH_SHLIB_EXT}
425 TARGETDEPS += ../libavutil/libmythavutil-$${MYTH_SHLIB_EXT}
This page took 0.134249 seconds and 4 git commands to generate.