]> git.pld-linux.org Git - packages/mythtv.git/blob - mythtv-dshowserver_trunk.patch
- updated to build snv fixes for stable mythtv-0.22
[packages/mythtv.git] / mythtv-dshowserver_trunk.patch
1 diff -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                          {
415 diff -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.073072 seconds and 3 git commands to generate.