Ticket #11579: 0001-Add-passing-of-DVD-NAV-blocks-to-ffmpeg.patch

File 0001-Add-passing-of-DVD-NAV-blocks-to-ffmpeg.patch, 18.0 KB (added by peper03@…, 11 years ago)

Corresponds to https://github.com/FFmpeg/FFmpeg/commit/9cde9f7

  • mythtv/external/FFmpeg/libavcodec/Makefile

    From fed4ad551d01bfdbded86394389d08705372a977 Mon Sep 17 00:00:00 2001
    From: Richard <peper03@yahoo.com>
    Date: Thu, 4 Apr 2013 23:09:00 +0200
    Subject: [PATCH 1/4] Add passing of DVD NAV blocks to ffmpeg
    
    ---
     mythtv/external/FFmpeg/libavcodec/Makefile         |    1 +
     mythtv/external/FFmpeg/libavcodec/allcodecs.c      |    1 +
     mythtv/external/FFmpeg/libavcodec/avcodec.h        |    1 +
     mythtv/external/FFmpeg/libavcodec/codec_desc.c     |    6 +
     mythtv/external/FFmpeg/libavcodec/dvd_nav_parser.c |  116 +++++++++++
     mythtv/external/FFmpeg/libavcodec/utils-mythtv.c   |    2 +
     mythtv/external/FFmpeg/libavformat/mpeg.c          |  219 +++++++++++++-------
     7 files changed, 272 insertions(+), 74 deletions(-)
     create mode 100644 mythtv/external/FFmpeg/libavcodec/dvd_nav_parser.c
    
    diff --git a/mythtv/external/FFmpeg/libavcodec/Makefile b/mythtv/external/FFmpeg/libavcodec/Makefile
    index edab72c..7e050ff 100644
    a b OBJS-$(CONFIG_PNG_PARSER) += png_parser.o 
    742742OBJS-$(CONFIG_MPEGAUDIO_PARSER)        += mpegaudio_parser.o \
    743743                                          mpegaudiodecheader.o mpegaudiodata.o
    744744OBJS-$(CONFIG_MPEGVIDEO_PARSER)        += mpegvideo_parser.o    \
     745                                          dvd_nav_parser.o \
    745746                                          mpeg12.o mpeg12data.o
    746747OBJS-$(CONFIG_PNM_PARSER)              += pnm_parser.o pnm.o
    747748OBJS-$(CONFIG_RV30_PARSER)             += rv34_parser.o
  • mythtv/external/FFmpeg/libavcodec/allcodecs.c

    diff --git a/mythtv/external/FFmpeg/libavcodec/allcodecs.c b/mythtv/external/FFmpeg/libavcodec/allcodecs.c
    index 584446f..1eaf2d3 100644
    a b void avcodec_register_all(void) 
    515515    REGISTER_PARSER(DNXHD,              dnxhd);
    516516    REGISTER_PARSER(DVBSUB,             dvbsub);
    517517    REGISTER_PARSER(DVDSUB,             dvdsub);
     518    REGISTER_PARSER(DVD_NAV,            dvd_nav);
    518519    REGISTER_PARSER(FLAC,               flac);
    519520    REGISTER_PARSER(GSM,                gsm);
    520521    REGISTER_PARSER(H261,               h261);
  • mythtv/external/FFmpeg/libavcodec/avcodec.h

    diff --git a/mythtv/external/FFmpeg/libavcodec/avcodec.h b/mythtv/external/FFmpeg/libavcodec/avcodec.h
    index f828f88..9889866 100644
    a b enum AVCodecID { 
    481481
    482482    /* DSMCC codec */
    483483    AV_CODEC_ID_DSMCC_B,
     484    AV_CODEC_ID_DVD_NAV = MKBETAG('D','N','A','V'),
    484485
    485486    /* other specific kind of codecs (generally used for attachments) */
    486487    AV_CODEC_ID_FIRST_UNKNOWN = 0x18000,           ///< A dummy ID pointing at the start of various fake codecs.
  • mythtv/external/FFmpeg/libavcodec/codec_desc.c

    diff --git a/mythtv/external/FFmpeg/libavcodec/codec_desc.c b/mythtv/external/FFmpeg/libavcodec/codec_desc.c
    index 673f971..ded09c9 100644
    a b static const AVCodecDescriptor codec_descriptors[] = { 
    25252525        .name      = "klv",
    25262526        .long_name = NULL_IF_CONFIG_SMALL("SMPTE 336M Key-Length-Value (KLV) metadata"),
    25272527    },
     2528    {
     2529        .id        = AV_CODEC_ID_DVD_NAV,
     2530        .type      = AVMEDIA_TYPE_DATA,
     2531        .name      = "dvd_nav_packet",
     2532        .long_name = NULL_IF_CONFIG_SMALL("DVD Nav packet"),
     2533    },
    25282534
    25292535};
    25302536
  • new file mythtv/external/FFmpeg/libavcodec/dvd_nav_parser.c

    diff --git a/mythtv/external/FFmpeg/libavcodec/dvd_nav_parser.c b/mythtv/external/FFmpeg/libavcodec/dvd_nav_parser.c
    new file mode 100644
    index 0000000..4b03e39
    - +  
     1/*
     2 * DVD navigation block parser for FFmpeg
     3 * Copyright (c) 2013 The FFmpeg Project
     4 *
     5 * This file is part of FFmpeg.
     6 *
     7 * FFmpeg is free software; you can redistribute it and/or
     8 * modify it under the terms of the GNU Lesser General Public
     9 * License as published by the Free Software Foundation; either
     10 * version 2.1 of the License, or (at your option) any later version.
     11 *
     12 * FFmpeg is distributed in the hope that it will be useful,
     13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     15 * Lesser General Public License for more details.
     16 *
     17 * You should have received a copy of the GNU Lesser General Public
     18 * License along with FFmpeg; if not, write to the Free Software
     19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     20 */
     21#include "avcodec.h"
     22#include "dsputil.h"
     23#include "get_bits.h"
     24#include "parser.h"
     25
     26#define PCI_SIZE  980
     27#define DSI_SIZE 1018
     28
     29/* parser definition */
     30typedef struct DVDNavParseContext {
     31    uint32_t     lba;
     32    uint8_t      buffer[PCI_SIZE+DSI_SIZE];
     33    int          copied;
     34} DVDNavParseContext;
     35
     36static av_cold int dvd_nav_parse_init(AVCodecParserContext *s)
     37{
     38    DVDNavParseContext *pc = s->priv_data;
     39
     40    pc->lba    = 0xFFFFFFFF;
     41    pc->copied = 0;
     42    return 0;
     43}
     44
     45static int dvd_nav_parse(AVCodecParserContext *s,
     46                         AVCodecContext *avctx,
     47                         const uint8_t **poutbuf, int *poutbuf_size,
     48                         const uint8_t *buf, int buf_size)
     49{
     50    DVDNavParseContext *pc1 = s->priv_data;
     51    int lastPacket          = 0;
     52    int valid               = 0;
     53
     54    s->pict_type = AV_PICTURE_TYPE_NONE;
     55
     56    avctx->time_base.num = 1;
     57    avctx->time_base.den = 90000;
     58
     59    if (buf && buf_size) {
     60        switch(buf[0]) {
     61            case 0x00:
     62                if (buf_size == PCI_SIZE) {
     63                    /* PCI */
     64                    uint32_t lba      = AV_RB32(&buf[0x01]);
     65                    uint32_t startpts = AV_RB32(&buf[0x0D]);
     66                    uint32_t endpts   = AV_RB32(&buf[0x11]);
     67
     68                    if (endpts > startpts) {
     69                        pc1->lba    = lba;
     70                        s->pts      = (int64_t)startpts;
     71                        s->duration = endpts - startpts;
     72
     73                        memcpy(pc1->buffer, buf, PCI_SIZE);
     74                        pc1->copied = PCI_SIZE;
     75                        valid       = 1;
     76                    }
     77                }
     78                break;
     79
     80            case 0x01:
     81                if ((buf_size == DSI_SIZE) && (pc1->copied == PCI_SIZE)) {
     82                    /* DSI */
     83                    uint32_t lba = AV_RB32(&buf[0x05]);
     84
     85                    if (lba == pc1->lba) {
     86                        memcpy(pc1->buffer + pc1->copied, buf, DSI_SIZE);
     87                        lastPacket  = 1;
     88                        valid       = 1;
     89                    }
     90                }
     91                break;
     92        }
     93    }
     94
     95    if (!valid || lastPacket) {
     96        pc1->copied = 0;
     97        pc1->lba    = 0xFFFFFFFF;
     98    }
     99
     100    if (lastPacket) {
     101        *poutbuf      = pc1->buffer;
     102        *poutbuf_size = sizeof(pc1->buffer);
     103    } else {
     104        *poutbuf      = NULL;
     105        *poutbuf_size = 0;
     106    }
     107
     108    return buf_size;
     109}
     110
     111AVCodecParser ff_dvd_nav_parser = {
     112    .codec_ids      = { AV_CODEC_ID_DVD_NAV },
     113    .priv_data_size = sizeof(DVDNavParseContext),
     114    .parser_init    = dvd_nav_parse_init,
     115    .parser_parse   = dvd_nav_parse,
     116};
  • mythtv/external/FFmpeg/libavcodec/utils-mythtv.c

    diff --git a/mythtv/external/FFmpeg/libavcodec/utils-mythtv.c b/mythtv/external/FFmpeg/libavcodec/utils-mythtv.c
    index b578c6d..694d713 100644
    a b const char *ff_codec_id_string(enum CodecID codec_id) 
    212212
    213213        case AV_CODEC_ID_DSMCC_B:          return "DSMCC_B";
    214214
     215        case AV_CODEC_ID_DVD_NAV:          return "DVD NAV";
     216
    215217        case AV_CODEC_ID_MPEG2TS:          return "MPEG2TS";
    216218
    217219            /* Attachment codecs */
  • mythtv/external/FFmpeg/libavformat/mpeg.c

    diff --git a/mythtv/external/FFmpeg/libavformat/mpeg.c b/mythtv/external/FFmpeg/libavformat/mpeg.c
    index 782dcca..d70ab83 100644
    a b  
    3030
    3131#undef NDEBUG
    3232#include <assert.h>
     33#include "libavutil/avassert.h"
    3334
    3435/*********************************************/
    3536/* demux code */
    typedef struct MpegDemuxContext { 
    112113    AVFormatContext *sub_ctx;
    113114    FFDemuxSubtitlesQueue q;
    114115#endif
     116    int dvd;
    115117} MpegDemuxContext;
    116118
    117119static int mpegps_read_header(AVFormatContext *s)
    static int mpegps_read_pes_header(AVFormatContext *s, 
    247249        goto redo;
    248250    }
    249251    if (startcode == PRIVATE_STREAM_2) {
    250         len = avio_rb16(s->pb);
    251252        if (!m->sofdec) {
    252             while (len-- >= 6) {
    253                 if (avio_r8(s->pb) == 'S') {
    254                     uint8_t buf[5];
    255                     avio_read(s->pb, buf, sizeof(buf));
    256                     m->sofdec = !memcmp(buf, "ofdec", 5);
    257                     len -= sizeof(buf);
    258                     break;
     253            /* Need to detect whether this from a DVD or a 'Sofdec' stream */
     254            int len = avio_rb16(s->pb);
     255            int bytesread = 0;
     256            uint8_t *ps2buf = av_malloc(len);
     257
     258            if (ps2buf) {
     259                bytesread = avio_read(s->pb, ps2buf, len);
     260
     261                if (bytesread != len) {
     262                    avio_skip(s->pb, len - bytesread);
     263                } else {
     264                    uint8_t *p = 0;
     265                    if (len >= 6)
     266                        p = memchr(ps2buf, 'S', len - 5);
     267
     268                    if (p)
     269                        m->sofdec = !memcmp(p+1, "ofdec", 5);
     270
     271                    m->sofdec -= !m->sofdec;
     272
     273                    if (m->sofdec < 0) {
     274                        if (len == 980  && ps2buf[0] == 0) {
     275                            /* PCI structure? */
     276                            uint32_t startpts = AV_RB32(ps2buf + 0x0d);
     277                            uint32_t endpts = AV_RB32(ps2buf + 0x11);
     278                            uint8_t hours = ((ps2buf[0x19] >> 4) * 10) + (ps2buf[0x19] & 0x0f);
     279                            uint8_t mins  = ((ps2buf[0x1a] >> 4) * 10) + (ps2buf[0x1a] & 0x0f);
     280                            uint8_t secs  = ((ps2buf[0x1b] >> 4) * 10) + (ps2buf[0x1b] & 0x0f);
     281
     282                            m->dvd = (hours <= 23 &&
     283                                      mins  <= 59 &&
     284                                      secs  <= 59 &&
     285                                      (ps2buf[0x19] & 0x0f) < 10 &&
     286                                      (ps2buf[0x1a] & 0x0f) < 10 &&
     287                                      (ps2buf[0x1b] & 0x0f) < 10 &&
     288                                      endpts >= startpts);
     289                        } else if (len == 1018 && ps2buf[0] == 1) {
     290                            /* DSI structure? */
     291                            uint8_t hours = ((ps2buf[0x1d] >> 4) * 10) + (ps2buf[0x1d] & 0x0f);
     292                            uint8_t mins  = ((ps2buf[0x1e] >> 4) * 10) + (ps2buf[0x1e] & 0x0f);
     293                            uint8_t secs  = ((ps2buf[0x1f] >> 4) * 10) + (ps2buf[0x1f] & 0x0f);
     294
     295                            m->dvd = (hours <= 23 &&
     296                                      mins  <= 59 &&
     297                                      secs  <= 59 &&
     298                                      (ps2buf[0x1d] & 0x0f) < 10 &&
     299                                      (ps2buf[0x1e] & 0x0f) < 10 &&
     300                                      (ps2buf[0x1f] & 0x0f) < 10);
     301                        }
     302                    }
    259303                }
     304
     305                av_free(ps2buf);
     306
     307                /* If this isn't a DVD packet or no memory
     308                 * could be allocated, just ignore it.
     309                 * If we did, move back to the start of the
     310                 * packet (plus 'length' field) */
     311                if (!m->dvd || avio_skip(s->pb, -(len + 2)) < 0) {
     312                    /* Skip back failed.
     313                     * This packet will be lost but that can't be helped
     314                     * if we can't skip back
     315                     */
     316                    goto redo;
     317                }
     318            } else {
     319                /* No memory */
     320                avio_skip(s->pb, len);
     321                goto redo;
    260322            }
    261             m->sofdec -= !m->sofdec;
     323        } else if (!m->dvd) {
     324            int len = avio_rb16(s->pb);
     325            avio_skip(s->pb, len);
     326            goto redo;
    262327        }
    263         avio_skip(s->pb, len);
    264         goto redo;
    265328    }
    266329    if (startcode == PROGRAM_STREAM_MAP) {
    267330        mpegps_psm_parse(m, s->pb);
    static int mpegps_read_pes_header(AVFormatContext *s, 
    271334    /* find matching stream */
    272335    if (!((startcode >= 0x1c0 && startcode <= 0x1df) ||
    273336          (startcode >= 0x1e0 && startcode <= 0x1ef) ||
    274           (startcode == 0x1bd) || (startcode == 0x1fd)))
     337          (startcode == 0x1bd) ||
     338          (startcode == PRIVATE_STREAM_2) ||
     339          (startcode == 0x1fd)))
    275340        goto redo;
    276341    if (ppos) {
    277342        *ppos = avio_tell(s->pb) - 4;
    static int mpegps_read_pes_header(AVFormatContext *s, 
    279344    len = avio_rb16(s->pb);
    280345    pts =
    281346    dts = AV_NOPTS_VALUE;
    282     /* stuffing */
    283     for(;;) {
    284         if (len < 1)
    285             goto error_redo;
    286         c = avio_r8(s->pb);
    287         len--;
    288         /* XXX: for mpeg1, should test only bit 7 */
    289         if (c != 0xff)
    290             break;
    291     }
    292     if ((c & 0xc0) == 0x40) {
    293         /* buffer scale & size */
    294         avio_r8(s->pb);
    295         c = avio_r8(s->pb);
    296         len -= 2;
    297     }
    298     if ((c & 0xe0) == 0x20) {
    299         dts = pts = get_pts(s->pb, c);
    300         len -= 4;
    301         if (c & 0x10){
    302             dts = get_pts(s->pb, -1);
    303             len -= 5;
     347    if (startcode != PRIVATE_STREAM_2)
     348    {
     349        /* stuffing */
     350        for(;;) {
     351            if (len < 1)
     352                goto error_redo;
     353            c = avio_r8(s->pb);
     354            len--;
     355            /* XXX: for mpeg1, should test only bit 7 */
     356            if (c != 0xff)
     357                break;
    304358        }
    305     } else if ((c & 0xc0) == 0x80) {
    306         /* mpeg 2 PES */
    307         flags = avio_r8(s->pb);
    308         header_len = avio_r8(s->pb);
    309         len -= 2;
    310         if (header_len > len)
    311             goto error_redo;
    312         len -= header_len;
    313         if (flags & 0x80) {
    314             dts = pts = get_pts(s->pb, -1);
    315             header_len -= 5;
    316             if (flags & 0x40) {
     359        if ((c & 0xc0) == 0x40) {
     360            /* buffer scale & size */
     361            avio_r8(s->pb);
     362            c = avio_r8(s->pb);
     363            len -= 2;
     364        }
     365        if ((c & 0xe0) == 0x20) {
     366            dts = pts = get_pts(s->pb, c);
     367            len -= 4;
     368            if (c & 0x10){
    317369                dts = get_pts(s->pb, -1);
     370                len -= 5;
     371            }
     372        } else if ((c & 0xc0) == 0x80) {
     373            /* mpeg 2 PES */
     374            flags = avio_r8(s->pb);
     375            header_len = avio_r8(s->pb);
     376            len -= 2;
     377            if (header_len > len)
     378                goto error_redo;
     379            len -= header_len;
     380            if (flags & 0x80) {
     381                dts = pts = get_pts(s->pb, -1);
    318382                header_len -= 5;
     383                if (flags & 0x40) {
     384                    dts = get_pts(s->pb, -1);
     385                    header_len -= 5;
     386                }
    319387            }
    320         }
    321         if (flags & 0x3f && header_len == 0){
    322             flags &= 0xC0;
    323             av_log(s, AV_LOG_WARNING, "Further flags set but no bytes left\n");
    324         }
    325         if (flags & 0x01) { /* PES extension */
    326             pes_ext = avio_r8(s->pb);
    327             header_len--;
    328             /* Skip PES private data, program packet sequence counter and P-STD buffer */
    329             skip = (pes_ext >> 4) & 0xb;
    330             skip += skip & 0x9;
    331             if (pes_ext & 0x40 || skip > header_len){
    332                 av_log(s, AV_LOG_WARNING, "pes_ext %X is invalid\n", pes_ext);
    333                 pes_ext=skip=0;
     388            if (flags & 0x3f && header_len == 0){
     389                flags &= 0xC0;
     390                av_log(s, AV_LOG_WARNING, "Further flags set but no bytes left\n");
    334391            }
    335             avio_skip(s->pb, skip);
    336             header_len -= skip;
    337 
    338             if (pes_ext & 0x01) { /* PES extension 2 */
    339                 ext2_len = avio_r8(s->pb);
     392            if (flags & 0x01) { /* PES extension */
     393                pes_ext = avio_r8(s->pb);
    340394                header_len--;
    341                 if ((ext2_len & 0x7f) > 0) {
    342                     id_ext = avio_r8(s->pb);
    343                     if ((id_ext & 0x80) == 0)
    344                         startcode = ((startcode & 0xff) << 8) | id_ext;
     395                /* Skip PES private data, program packet sequence counter and P-STD buffer */
     396                skip = (pes_ext >> 4) & 0xb;
     397                skip += skip & 0x9;
     398                if (pes_ext & 0x40 || skip > header_len){
     399                    av_log(s, AV_LOG_WARNING, "pes_ext %X is invalid\n", pes_ext);
     400                    pes_ext=skip=0;
     401                }
     402                avio_skip(s->pb, skip);
     403                header_len -= skip;
     404
     405                if (pes_ext & 0x01) { /* PES extension 2 */
     406                    ext2_len = avio_r8(s->pb);
    345407                    header_len--;
     408                    if ((ext2_len & 0x7f) > 0) {
     409                        id_ext = avio_r8(s->pb);
     410                        if ((id_ext & 0x80) == 0)
     411                            startcode = ((startcode & 0xff) << 8) | id_ext;
     412                        header_len--;
     413                    }
    346414                }
    347415            }
     416            if(header_len < 0)
     417                goto error_redo;
     418            avio_skip(s->pb, header_len);
    348419        }
    349         if(header_len < 0)
    350             goto error_redo;
    351         avio_skip(s->pb, header_len);
     420        else if( c!= 0xf )
     421            goto redo;
    352422    }
    353     else if( c!= 0xf )
    354         goto redo;
    355423
    356424    if (startcode == PRIVATE_STREAM_1) {
    357425        startcode = avio_r8(s->pb);
    static int mpegps_read_packet(AVFormatContext *s, 
    451519        else
    452520            request_probe= 1;
    453521        type = AVMEDIA_TYPE_VIDEO;
     522    } else if (startcode == PRIVATE_STREAM_2) {
     523        type = AVMEDIA_TYPE_DATA;
     524        codec_id = AV_CODEC_ID_DVD_NAV;
    454525    } else if (startcode >= 0x1c0 && startcode <= 0x1df) {
    455526        type = AVMEDIA_TYPE_AUDIO;
    456527        codec_id = m->sofdec > 0 ? AV_CODEC_ID_ADPCM_ADX : AV_CODEC_ID_MP2;