Ticket #3053: coreavc.patch

File coreavc.patch, 13.8 KB (added by stuartm, 4 years ago)

Update Coreavc patch to compile against trunk

  • libs/libmythtv/avformatdecoder.cpp

     
    11// C headers 
    22#include <cassert> 
    33#include <unistd.h> 
     4#include <fcntl.h> 
    45 
    56// C++ headers 
    67#include <algorithm> 
     
    89using namespace std; 
    910 
    1011#include <q3tl.h> 
     12#include <qdir.h> 
    1113 
    1214// MythTV headers 
    1315#include "mythconfig.h" 
     
    4345#include "../libavcodec/ac3_parser.h" 
    4446#include "../libmythmpeg2/mpeg2.h" 
    4547#include "ivtv_myth.h" 
     48#include "libavformat/riff.h" 
    4649// from libavcodec 
    4750extern const uint8_t *ff_find_start_code(const uint8_t * restrict p, const uint8_t *end, uint32_t * restrict state); 
    4851} 
     
    132135 
    133136typedef MythDeque<AVFrame*> avframe_q; 
    134137 
     138struct vd_struct { 
     139  union { 
     140    uint32_t ret; 
     141    uint32_t cmd; 
     142  }; 
     143  uint32_t buflen; 
     144  uint64_t pts; 
     145  uint32_t unused[8]; 
     146} __attribute__((__packed__)); 
     147 
     148enum { 
     149  VD_END = 1, 
     150  VD_DECODE = 2, 
     151  VD_SEEK = 3, 
     152  VD_HAS_BIH = 0x10000, 
     153  VD_VERSION_MASK = 0xFFFF, 
     154}; 
     155 
     156#include <semaphore.h> 
     157#include <sys/mman.h> 
     158typedef struct { 
     159    int fd; 
     160    void *mem; 
     161    char *data; 
     162    char *picture; 
     163    int picsize; 
     164    sem_t *sem_rd; 
     165    sem_t *sem_wr; 
     166    struct vd_struct *vd; 
     167} ds_mpi_t; 
     168 
    135169/** 
    136170 * Management of libmpeg2 decoding 
    137171 */ 
    138172class AvFormatDecoderPrivate 
    139173{ 
    140174  public: 
    141     AvFormatDecoderPrivate(bool allow_libmpeg2) 
    142         : mpeg2dec(NULL), dvdvdec(NULL), allow_mpeg2dec(allow_libmpeg2) { ; } 
    143    ~AvFormatDecoderPrivate() { DestroyMPEG2(); } 
     175    AvFormatDecoderPrivate(bool allow_libmpeg2, bool allow_directshow) 
     176        : mpeg2dec(NULL), dvdvdec(NULL), allow_mpeg2dec(allow_libmpeg2), 
     177          ds_mpi(NULL), allow_dshow(allow_directshow) { ; } 
     178   ~AvFormatDecoderPrivate() { DestroyMPEG2(); DestroyDirectShow();} 
    144179     
    145180    bool InitMPEG2(const QString &dec); 
    146181    bool HasMPEG2Dec(void) const { return (bool)(mpeg2dec); } 
    147182    bool HasDVDVDec(void) const { return (bool)(dvdvdec); } 
    148183    bool HasDecoder(void) const { return HasMPEG2Dec() || HasDVDVDec(); } 
    149184 
     185    bool InitDirectShow(AVCodecContext *enc); 
     186    bool HasDirectShow() const { return (bool)(ds_mpi); } 
     187 
    150188    void DestroyMPEG2(); 
    151189    void ResetMPEG2(); 
    152190    int DecodeMPEG2Video(AVCodecContext *avctx, AVFrame *picture, 
     
    156194    bool SetVideoSize(const QSize &video_dim); 
    157195    DVDV *GetDVDVDecoder(void) { return dvdvdec; } 
    158196 
     197    void DestroyDirectShow(); 
     198    void ResetDirectShow(); 
     199    int DecodeDirectShowVideo(AVCodecContext *avctx, AVFrame *picture, 
     200                         int *got_picture_ptr, uint8_t *buf, int buf_size); 
     201 
    159202  private: 
    160203    mpeg2dec_t *mpeg2dec; 
    161204    DVDV       *dvdvdec; 
    162205    bool        allow_mpeg2dec; 
     206    ds_mpi_t   *ds_mpi; 
     207    bool        allow_dshow; 
    163208    avframe_q   partialFrames; 
    164209}; 
    165210 
     211static int sem_twait(sem_t *sem, int t) { 
     212    struct timespec ts; 
     213    clock_gettime(CLOCK_REALTIME, &ts); 
     214    ts.tv_sec += t; 
     215    return(sem_timedwait(sem, &ts)); 
     216} 
     217bool AvFormatDecoderPrivate::InitDirectShow(AVCodecContext *enc) 
     218{ 
     219    typedef struct { 
     220        uint32_t f1; 
     221        uint16_t f2; 
     222        uint16_t f3; 
     223        uint8_t  f4[8]; 
     224    } GUID; 
     225 
     226    const struct AVCodecTag *bmp_taglists[] = {codec_bmp_tags, 0}; 
     227 
     228    if(enc->codec_tag == 0) 
     229        enc->codec_tag = av_codec_get_tag(bmp_taglists, enc->codec_id); 
     230//    VERBOSE(VB_IMPORTANT, QString("Trying DirectShow for FOURCC 0x%1") 
     231//            .arg(enc->codec_tag, 8, 16, 0)); 
     232    if (!allow_dshow) 
     233        return false; 
     234    DestroyDirectShow(); 
     235    if (enc->codec_tag == 0) { 
     236        allow_dshow = false; 
     237        return false; 
     238    } 
     239//    QString dec = gContext->GetSetting("UseDirectShowVideoDecoder", "no"); 
     240    QString dec = "yes"; 
     241 
     242    if (dec == "yes") 
     243    { 
     244        bool found = false; 
     245        QString codec; 
     246        GUID guid = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}}; 
     247        QString codec_file = QDir::homeDirPath() + 
     248                            QString("/.mythtv/dshowcodecs"); 
     249        if (! QFileInfo(codec_file).isFile()) { 
     250            allow_dshow = false; 
     251            return false; 
     252        } 
     253        QString videotype; 
     254        AVCodec *avc = avcodec_find_decoder(enc->codec_id); 
     255        if (! avc) { 
     256           allow_dshow = false; 
     257           return false; 
     258        } 
     259        videotype = avc->name; 
     260        QFile fh (codec_file); 
     261        QString line; 
     262        fh.open(IO_ReadOnly); 
     263        while (! fh.atEnd() && ! found) { 
     264            QStringList fourc, guidlist; 
     265            QTextStream filein(&fh); 
     266            line = filein.readLine(1024); 
     267            codec = line.section(':', 0, 0).stripWhiteSpace(); 
     268            fourc = QStringList::split(",",line.section(':', 1, 1)); 
     269            guidlist  = QStringList::split(",",line.section(':', 2, 2)); 
     270            if (guidlist.count() != 11) 
     271                continue; 
     272            for (QStringList::Iterator it = fourc.begin(); 
     273                 it != fourc.end(); it++) 
     274            { 
     275                if ((*it).stripWhiteSpace() == videotype) 
     276                { 
     277                    guid.f1 = guidlist[0].toUInt(0, 0); 
     278                    guid.f2 = guidlist[1].toUShort(0, 0); 
     279                    guid.f3 = guidlist[2].toUShort(0, 0); 
     280                    for (int i = 0; i < 8; i++) 
     281                        guid.f4[i] = guidlist[i + 3].toUShort(0, 0); 
     282                    found = true; 
     283                } 
     284            } 
     285            if (found) 
     286                break; 
     287        } 
     288        fh.close(); 
     289        if (found) { 
     290            int ret; 
     291            char cmd[255], shm[80], sem1[80], sem2[80]; 
     292            uint32_t out_fmt; 
     293            int bpp; 
     294            //out_fmt = 0x30323449; bpp = 12; //I420 12bpp 
     295            out_fmt = 0x32595559; bpp = 16; //YUY2 16bpp 
     296            snprintf(cmd, 255, "dshowserver -c %s -s %dx%d " 
     297                     "-g %08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x " 
     298                     "-f 0x%08x -b %d -o 0x%08x -p %d -i %x %s&", 
     299                codec.ascii(), enc->width, enc->height, 
     300                guid.f1, guid.f2, guid.f3, 
     301                      guid.f4[0], guid.f4[1], guid.f4[2], guid.f4[3], 
     302                      guid.f4[4], guid.f4[5], guid.f4[6], guid.f4[7], 
     303                enc->codec_tag, bpp, out_fmt, getpid(), *(int *)pthread_self(), 
     304                ((print_verbose_messages & VB_PLAYBACK == VB_PLAYBACK) ? 
     305                            "-d" : "")); 
     306            ds_mpi = new ds_mpi_t; 
     307            snprintf(shm, 80, "/dshow_shm.%x", *(int *)pthread_self()); 
     308            snprintf(sem1, 80, "/dshow_sem1.%x", *(int *)pthread_self()); 
     309            snprintf(sem2, 80, "/dshow_sem2.%x", *(int *)pthread_self()); 
     310            ds_mpi->fd = shm_open(shm, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); 
     311            ds_mpi->picsize =  enc->width * enc->height * bpp / 8; 
     312            int extra = 0; 
     313            if (enc->height % 16) 
     314                extra = (16 - enc->height % 16) * bpp / 8; 
     315            int memsize = sizeof(struct vd_struct) + enc->width * enc->height + 
     316                          ds_mpi->picsize + extra; 
     317            ftruncate(ds_mpi->fd, memsize); 
     318            ds_mpi->mem = mmap(NULL, memsize, PROT_READ | PROT_WRITE, 
     319                               MAP_SHARED, ds_mpi->fd, 0); 
     320            if(ds_mpi->mem == MAP_FAILED) { 
     321              perror("mmap"); 
     322              allow_dshow = false; 
     323              return false; 
     324            } 
     325            memset((char *)ds_mpi->mem, 0, sizeof(struct vd_struct)); 
     326 
     327            if (extra) 
     328                memset((char *)ds_mpi->mem + (memsize - extra), 0, extra); 
     329            ds_mpi->vd = (struct vd_struct *)ds_mpi->mem; 
     330            ds_mpi->data = ((char *)ds_mpi->mem) + sizeof(struct vd_struct); 
     331            ds_mpi->picture = ds_mpi->data + enc->width * enc->height; 
     332            //Create read/write semaphores in locked state 
     333            ds_mpi->sem_wr = sem_open(sem1, O_CREAT, 0644, 0); 
     334            ds_mpi->sem_rd = sem_open(sem2, O_CREAT, 0644, 0); 
     335            system(cmd); 
     336            ret = sem_twait(ds_mpi->sem_rd, 10); 
     337            shm_unlink(shm); 
     338            sem_unlink(sem1); 
     339            sem_unlink(sem2); 
     340            if(ret != 0) { 
     341                VERBOSE(VB_IMPORTANT, LOC + "DirectShow filter failed"); 
     342            } else { 
     343                VERBOSE(VB_IMPORTANT, LOC + "Found DirectShow filter"); 
     344                return true; 
     345            } 
     346       } 
     347    } 
     348    allow_dshow = false; 
     349    return false; 
     350} 
     351 
     352void AvFormatDecoderPrivate::DestroyDirectShow() 
     353{ 
     354    if (ds_mpi) 
     355    { 
     356        VERBOSE(VB_PLAYBACK, LOC + "Destroying filter"); 
     357        ds_mpi->vd->cmd = VD_END; //'1' is cmd for terminating 
     358        sem_post(ds_mpi->sem_wr); 
     359        close(ds_mpi->fd); 
     360        sem_close(ds_mpi->sem_wr); 
     361        sem_close(ds_mpi->sem_rd); 
     362        delete ds_mpi; 
     363        ds_mpi = NULL; 
     364    } 
     365} 
     366 
     367void AvFormatDecoderPrivate::ResetDirectShow() 
     368{ 
     369} 
     370 
     371void yuy2i420(AVFrame *dst, char *src, int w, int l) 
     372{ 
     373    int count; 
     374  uint8_t *y, *u, *v; 
     375  y = dst->data[0]; 
     376  u = dst->data[1]; 
     377  v = dst->data[2]; 
     378  int i,j; 
     379  for(i=0; i < l; i++) { 
     380    for(j=0; j < w; j+=2) { 
     381      *(y++) = *(src++); 
     382      *(u++) = *(src++); 
     383      *(y++) = *(src++); 
     384      *(v++) = *(src++); 
     385    } 
     386    i++; 
     387    for(j=0; j < w; j+=2) { 
     388      *(y++) = *src; 
     389      src+=2; 
     390      *(y++) = *src; 
     391      src+=2; 
     392   } 
     393  } 
     394} 
     395 
     396int AvFormatDecoderPrivate::DecodeDirectShowVideo(AVCodecContext *avctx, 
     397                                             AVFrame *picture, 
     398                                             int *got_picture_ptr, 
     399                                             uint8_t *buf, int buf_size) 
     400{ 
     401    int ret; 
     402    ds_mpi->vd->cmd = VD_DECODE; //'1' is cmd for decoding 
     403    memcpy(ds_mpi->data, buf, buf_size); 
     404    ds_mpi->vd->buflen = buf_size; 
     405    sem_post(ds_mpi->sem_wr); 
     406    ret = sem_twait(ds_mpi->sem_rd, 10); 
     407    if(ret == 0 && ds_mpi->vd->ret && ! (ds_mpi->vd->ret & (1<<31))) { 
     408        *got_picture_ptr = 1; 
     409        picture->interlaced_frame = (ds_mpi->vd->ret & 10) ? true : false; 
     410        avctx->get_buffer(avctx, picture); 
     411#if 0  //Using YV12 
     412        if(avctx->height & 0x0f) { 
     413           unsigned long pos, pos1, siz = avctx->height * avctx->width; 
     414           memcpy(picture->data[0], ds_mpi->picture, siz); 
     415           pos = siz; 
     416           pos1 = siz + avctx->width * (16 - avctx->height % 16); 
     417           siz /= 4; 
     418           memcpy(picture->data[0]+pos1, ds_mpi->picture+pos, siz); 
     419           pos+=siz; 
     420           pos1+=siz + avctx->width * ( 16 - avctx->height % 16) / 4; 
     421           memcpy(picture->data[0]+pos1, ds_mpi->picture+pos, siz); 
     422        } else { 
     423          memcpy(picture->data[0], ds_mpi->picture, ds_mpi->picsize); 
     424        } 
     425#else //Using YUY2 
     426        //YUY2 is a packed format so padding is easier 
     427        //int extra = 0; 
     428        //if(avctx->height % 16) 
     429            //extra = (16 - avctx->height % 16); 
     430        yuy2i420(picture, ds_mpi->picture, 
     431                 avctx->width, avctx->height); 
     432#endif 
     433    } else { 
     434      *got_picture_ptr = 0; 
     435    } 
     436    return buf_size; 
     437} 
     438 
     439/*************************************************/ 
     440 
    166441/** 
    167442 * \brief Initialise either libmpeg2, or DVDV (Mac HW accel), to do decoding 
    168443 * 
     
    384659                                 bool use_null_videoout, 
    385660                                 bool allow_libmpeg2) 
    386661    : DecoderBase(parent, pginfo), 
    387       d(new AvFormatDecoderPrivate(allow_libmpeg2)), 
     662      d(new AvFormatDecoderPrivate(allow_libmpeg2, true)), 
    388663      is_db_ignored(gContext->IsDatabaseIgnored()), 
    389664      h264_kf_seq(new H264::KeyframeSequencer()), 
    390665      ic(NULL), 
     
    15321807                        } 
    15331808                    } 
    15341809 
     1810                    if (CODEC_ID_H264 == enc->codec_id) 
     1811                      force_xv = true; 
     1812 
    15351813                    MythCodecID mcid; 
    15361814                    mcid = VideoOutputXv::GetBestSupportedCodec( 
    15371815                        /* disp dim     */ width, height, 
     
    15411819                        /* test surface */ kCodec_NORMAL_END > video_codec_id, 
    15421820                        /* force_xv     */ force_xv); 
    15431821                    bool vcd, idct, mc; 
     1822 
    15441823                    enc->codec_id = (CodecID) 
    15451824                        myth2av_codecid(mcid, vcd, idct, mc); 
    15461825 
     
    15961875                } 
    15971876 
    15981877                // Initialize alternate decoders when needed... 
     1878              if (! d->InitDirectShow(enc)) 
    15991879                if (((dec == "libmpeg2") && 
    16001880                     (CODEC_ID_MPEG1VIDEO == enc->codec_id || 
    16011881                      CODEC_ID_MPEG2VIDEO == enc->codec_id)) || 
     
    35893869                    int gotpicture = 0; 
    35903870 
    35913871                    avcodeclock.lock(); 
    3592                     if (d->HasDecoder()) 
     3872/*                    printf("Trying: %d\n",len); 
     3873                    if (0) { 
     3874                      static int fnum = 0; 
     3875                      char str[80]; 
     3876                      int fh; 
     3877                      sprintf(str,"enc%d", fnum++);; 
     3878                      fh = open(str, 01101,00777); 
     3879                      write(fh, ptr, len); 
     3880                      close(fh); 
     3881                    } 
     3882*/ 
     3883                    if (d->HasDirectShow()) 
     3884                        ret = d->DecodeDirectShowVideo(context, &mpa_pic, 
     3885                                                  &gotpicture, ptr, len); 
     3886                    else if (d->HasDecoder()) 
    35933887                    { 
    35943888                        if (decodeStillFrame) 
    35953889                        { 
  • libs/libmythtv/libmythtv.pro

     
    3737LIBS += -lmythmpeg2-$$LIBVERSION    -lmythdvdnav-$$LIBVERSION 
    3838LIBS += -lmythfreemheg-$$LIBVERSION -lmythlivemedia-$$LIBVERSION 
    3939LIBS += -lz $$EXTRA_LIBS 
     40LIBS += -lrt 
    4041 
    4142TARGETDEPS += ../libmyth/libmyth-$${MYTH_SHLIB_EXT} 
    4243TARGETDEPS += ../libavutil/libmythavutil-$${MYTH_SHLIB_EXT}