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 "get_bits.h" 23#include "parser.h" 24 25#define PCI_SIZE 980 26#define DSI_SIZE 1018 27 28/* parser definition */ 29typedef struct DVDNavParseContext { 30 uint32_t lba; 31 uint8_t buffer[PCI_SIZE+DSI_SIZE]; 32 int copied; 33} DVDNavParseContext; 34 35static av_cold int dvd_nav_parse_init(AVCodecParserContext *s) 36{ 37 DVDNavParseContext *pc = s->priv_data; 38 39 pc->lba = 0xFFFFFFFF; 40 pc->copied = 0; 41 return 0; 42} 43 44static int dvd_nav_parse(AVCodecParserContext *s, 45 AVCodecContext *avctx, 46 const uint8_t **poutbuf, int *poutbuf_size, 47 const uint8_t *buf, int buf_size) 48{ 49 DVDNavParseContext *pc1 = s->priv_data; 50 int lastPacket = 0; 51 int valid = 0; 52 53 s->pict_type = AV_PICTURE_TYPE_NONE; 54 55 avctx->time_base.num = 1; 56 avctx->time_base.den = 90000; 57 58 if (buf && buf_size) { 59 switch(buf[0]) { 60 case 0x00: 61 if (buf_size == PCI_SIZE) { 62 /* PCI */ 63 uint32_t lba = AV_RB32(&buf[0x01]); 64 uint32_t startpts = AV_RB32(&buf[0x0D]); 65 uint32_t endpts = AV_RB32(&buf[0x11]); 66 67 if (endpts > startpts) { 68 pc1->lba = lba; 69 s->pts = (int64_t)startpts; 70 s->duration = endpts - startpts; 71 72 memcpy(pc1->buffer, buf, PCI_SIZE); 73 pc1->copied = PCI_SIZE; 74 valid = 1; 75 } 76 } 77 break; 78 79 case 0x01: 80 if ((buf_size == DSI_SIZE) && (pc1->copied == PCI_SIZE)) { 81 /* DSI */ 82 uint32_t lba = AV_RB32(&buf[0x05]); 83 84 if (lba == pc1->lba) { 85 memcpy(pc1->buffer + pc1->copied, buf, DSI_SIZE); 86 lastPacket = 1; 87 valid = 1; 88 } 89 } 90 break; 91 } 92 } 93 94 if (!valid || lastPacket) { 95 pc1->copied = 0; 96 pc1->lba = 0xFFFFFFFF; 97 } 98 99 if (lastPacket) { 100 *poutbuf = pc1->buffer; 101 *poutbuf_size = sizeof(pc1->buffer); 102 } else { 103 *poutbuf = NULL; 104 *poutbuf_size = 0; 105 } 106 107 return buf_size; 108} 109 110const AVCodecParser ff_dvd_nav_parser = { 111 .codec_ids = { AV_CODEC_ID_DVD_NAV }, 112 .priv_data_size = sizeof(DVDNavParseContext), 113 .parser_init = dvd_nav_parse_init, 114 .parser_parse = dvd_nav_parse, 115}; 116