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
19 #include "mythconfig.h"
20 #include "avformatdecoder.h"
23 #include "../libmythmpeg2/mpeg2.h"
24 #include "ivtv_myth.h"
25 +#include "libavformat/riff.h"
28 #define LOC QString("AFD: ")
31 typedef MythDeque<AVFrame*> avframe_q;
41 +} __attribute__((__packed__));
47 + VD_HAS_BIH = 0x10000,
48 + VD_VERSION_MASK = 0xFFFF,
51 +#include <semaphore.h>
52 +#include <sys/mman.h>
61 + struct vd_struct *vd;
65 * Management of libmpeg2 decoding
67 class AvFormatDecoderPrivate
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();}
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(); }
83 + bool InitDirectShow(AVCodecContext *enc);
84 + bool HasDirectShow() const { return (bool)(ds_mpi); }
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; }
93 + void DestroyDirectShow();
94 + void ResetDirectShow();
95 + int DecodeDirectShowVideo(AVCodecContext *avctx, AVFrame *picture,
96 + int *got_picture_ptr, uint8_t *buf, int buf_size,
100 mpeg2dec_t *mpeg2dec;
105 avframe_q partialFrames;
108 +static int sem_twait(sem_t *sem, int t) {
109 + struct timespec ts;
110 + clock_gettime(CLOCK_REALTIME, &ts);
112 + return(sem_timedwait(sem, &ts));
114 +bool AvFormatDecoderPrivate::InitDirectShow(AVCodecContext *enc)
123 + const struct AVCodecTag *bmp_taglists[] = {codec_bmp_tags, 0};
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));
131 + DestroyDirectShow();
132 + if (enc->codec_tag == 0) {
133 + allow_dshow = false;
136 +// QString dec = gContext->GetSetting("UseDirectShowVideoDecoder", "no");
137 + QString dec = "yes";
141 + bool found = false;
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;
151 + AVCodec *avc = avcodec_find_decoder(enc->codec_id);
153 + allow_dshow = false;
156 + videotype = avc->name;
157 + QFile fh (codec_file);
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)
168 + for (QStringList::Iterator it = fourc.begin();
169 + it != fourc.end(); it++)
171 + if ((*it).simplified() == videotype)
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);
187 + char cmd[255], shm[80], sem1[80], sem2[80];
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 ?
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;
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) {
218 + allow_dshow = false;
221 + memset((char *)ds_mpi->mem, 0, sizeof(struct vd_struct));
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);
232 + ret = sem_twait(ds_mpi->sem_rd, 10);
237 + VERBOSE(VB_IMPORTANT, LOC + "DirectShow filter failed");
239 + VERBOSE(VB_IMPORTANT, LOC + "Found DirectShow filter");
244 + allow_dshow = false;
248 +void AvFormatDecoderPrivate::DestroyDirectShow()
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);
256 + sem_close(ds_mpi->sem_wr);
257 + sem_close(ds_mpi->sem_rd);
263 +void AvFormatDecoderPrivate::ResetDirectShow()
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);
272 +void yuy2i420(AVFrame *dst, char *src, int w, int l)
274 + uint8_t *y, *u, *v;
279 + for(i=0; i < l; i++) {
280 + for(j=0; j < w; j+=2) {
287 + for(j=0; j < w; j+=2) {
296 +int AvFormatDecoderPrivate::DecodeDirectShowVideo(AVCodecContext *avctx,
298 + int *got_picture_ptr,
299 + uint8_t *buf, int buf_size,
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;
314 + picture->interlaced_frame = (ds_mpi->vd->ret & 10) ? true : false;
315 + avctx->get_buffer(avctx, picture);
317 + if(avctx->height & 0x0f) {
318 + unsigned long pos, pos1, siz = avctx->height * avctx->width;
319 + memcpy(picture->data[0], ds_mpi->picture, siz);
321 + pos1 = siz + avctx->width * (16 - avctx->height % 16);
323 + memcpy(picture->data[0]+pos1, ds_mpi->picture+pos, siz);
325 + pos1+=siz + avctx->width * ( 16 - avctx->height % 16) / 4;
326 + memcpy(picture->data[0]+pos1, ds_mpi->picture+pos, siz);
328 + memcpy(picture->data[0], ds_mpi->picture, ds_mpi->picsize);
331 + //YUY2 is a packed format so padding is easier
333 + //if(avctx->height % 16)
334 + //extra = (16 - avctx->height % 16);
335 + yuy2i420(picture, ds_mpi->picture,
336 + avctx->width, avctx->height);
339 + *got_picture_ptr = 0;
344 +/*************************************************/
347 * \brief Initialise either libmpeg2, or DVDV (Mac HW accel), to do decoding
350 bool use_null_videoout,
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()),
359 avcodec_flush_buffers(enc);
362 + d->ResetDirectShow();
365 // Discard all the queued up decoded frames
366 @@ -1584,6 +1871,9 @@
370 + if (CODEC_ID_H264 == enc->codec_id)
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;
381 enc->codec_id = (CodecID)
382 myth2av_codecid(mcid, vcd, idct, mc, vdpau);
384 @@ -1668,6 +1959,7 @@
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 @@
396 - if (d->HasDecoder())
397 +/* printf("Trying: %d\n",len);
399 + static int fnum = 0;
402 + sprintf(str,"enc%d", fnum++);;
403 + fh = open(str, 01101,00777);
404 + write(fh, ptr, len);
408 + if (d->HasDirectShow())
409 + ret = d->DecodeDirectShowVideo(context, &mpa_pic,
410 + &gotpicture, ptr, len, &pts);
411 + else if (d->HasDecoder())
413 if (decodeStillFrame)
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
420 using_backend: LIBS += -lmp3lame
421 LIBS += -lz $$EXTRA_LIBS $$QMAKE_LIBS_DYNLOAD
424 TARGETDEPS += ../libmyth/libmyth-$${MYTH_SHLIB_EXT}
425 TARGETDEPS += ../libavutil/libmythavutil-$${MYTH_SHLIB_EXT}