1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * DVB subtitle parser for FFmpeg 3cabdff1aSopenharmony_ci * Copyright (c) 2005 Ian Caulfield 4cabdff1aSopenharmony_ci * 5cabdff1aSopenharmony_ci * This file is part of FFmpeg. 6cabdff1aSopenharmony_ci * 7cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 8cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 9cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 10cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 11cabdff1aSopenharmony_ci * 12cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 13cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 14cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15cabdff1aSopenharmony_ci * Lesser General Public License for more details. 16cabdff1aSopenharmony_ci * 17cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 18cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 19cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20cabdff1aSopenharmony_ci */ 21cabdff1aSopenharmony_ci 22cabdff1aSopenharmony_ci#include <inttypes.h> 23cabdff1aSopenharmony_ci#include <string.h> 24cabdff1aSopenharmony_ci 25cabdff1aSopenharmony_ci#include "libavutil/intreadwrite.h" 26cabdff1aSopenharmony_ci 27cabdff1aSopenharmony_ci#include "avcodec.h" 28cabdff1aSopenharmony_ci 29cabdff1aSopenharmony_ci/* Parser (mostly) copied from dvdsub.c */ 30cabdff1aSopenharmony_ci 31cabdff1aSopenharmony_ci#define PARSE_BUF_SIZE (65536) 32cabdff1aSopenharmony_ci 33cabdff1aSopenharmony_ci 34cabdff1aSopenharmony_ci/* parser definition */ 35cabdff1aSopenharmony_citypedef struct DVBSubParseContext { 36cabdff1aSopenharmony_ci int packet_start; 37cabdff1aSopenharmony_ci int packet_index; 38cabdff1aSopenharmony_ci int in_packet; 39cabdff1aSopenharmony_ci uint8_t packet_buf[PARSE_BUF_SIZE]; 40cabdff1aSopenharmony_ci} DVBSubParseContext; 41cabdff1aSopenharmony_ci 42cabdff1aSopenharmony_cistatic int dvbsub_parse(AVCodecParserContext *s, 43cabdff1aSopenharmony_ci AVCodecContext *avctx, 44cabdff1aSopenharmony_ci const uint8_t **poutbuf, int *poutbuf_size, 45cabdff1aSopenharmony_ci const uint8_t *buf, int buf_size) 46cabdff1aSopenharmony_ci{ 47cabdff1aSopenharmony_ci DVBSubParseContext *pc = s->priv_data; 48cabdff1aSopenharmony_ci uint8_t *p, *p_end; 49cabdff1aSopenharmony_ci int i, len, buf_pos = 0; 50cabdff1aSopenharmony_ci int out_size = 0; 51cabdff1aSopenharmony_ci 52cabdff1aSopenharmony_ci ff_dlog(avctx, "DVB parse packet pts=%"PRIx64", lpts=%"PRIx64", cpts=%"PRIx64":\n", 53cabdff1aSopenharmony_ci s->pts, s->last_pts, s->cur_frame_pts[s->cur_frame_start_index]); 54cabdff1aSopenharmony_ci 55cabdff1aSopenharmony_ci for (i=0; i < buf_size; i++) 56cabdff1aSopenharmony_ci { 57cabdff1aSopenharmony_ci ff_dlog(avctx, "%02x ", buf[i]); 58cabdff1aSopenharmony_ci if (i % 16 == 15) 59cabdff1aSopenharmony_ci ff_dlog(avctx, "\n"); 60cabdff1aSopenharmony_ci } 61cabdff1aSopenharmony_ci 62cabdff1aSopenharmony_ci if (i % 16 != 0) 63cabdff1aSopenharmony_ci ff_dlog(avctx, "\n"); 64cabdff1aSopenharmony_ci 65cabdff1aSopenharmony_ci *poutbuf = buf; 66cabdff1aSopenharmony_ci *poutbuf_size = buf_size; 67cabdff1aSopenharmony_ci 68cabdff1aSopenharmony_ci s->fetch_timestamp = 1; 69cabdff1aSopenharmony_ci 70cabdff1aSopenharmony_ci if (s->last_pts != s->pts && s->pts != AV_NOPTS_VALUE) /* Start of a new packet */ 71cabdff1aSopenharmony_ci { 72cabdff1aSopenharmony_ci if (pc->packet_index != pc->packet_start) 73cabdff1aSopenharmony_ci { 74cabdff1aSopenharmony_ci ff_dlog(avctx, "Discarding %d bytes\n", 75cabdff1aSopenharmony_ci pc->packet_index - pc->packet_start); 76cabdff1aSopenharmony_ci } 77cabdff1aSopenharmony_ci 78cabdff1aSopenharmony_ci pc->packet_start = 0; 79cabdff1aSopenharmony_ci pc->packet_index = 0; 80cabdff1aSopenharmony_ci 81cabdff1aSopenharmony_ci if (buf_size < 2 || buf[0] != 0x20 || buf[1] != 0x00) { 82cabdff1aSopenharmony_ci ff_dlog(avctx, "Bad packet header\n"); 83cabdff1aSopenharmony_ci return buf_size; 84cabdff1aSopenharmony_ci } 85cabdff1aSopenharmony_ci 86cabdff1aSopenharmony_ci buf_pos = 2; 87cabdff1aSopenharmony_ci 88cabdff1aSopenharmony_ci pc->in_packet = 1; 89cabdff1aSopenharmony_ci } else { 90cabdff1aSopenharmony_ci if (pc->packet_start != 0) 91cabdff1aSopenharmony_ci { 92cabdff1aSopenharmony_ci if (pc->packet_index != pc->packet_start) 93cabdff1aSopenharmony_ci { 94cabdff1aSopenharmony_ci memmove(pc->packet_buf, pc->packet_buf + pc->packet_start, 95cabdff1aSopenharmony_ci pc->packet_index - pc->packet_start); 96cabdff1aSopenharmony_ci 97cabdff1aSopenharmony_ci pc->packet_index -= pc->packet_start; 98cabdff1aSopenharmony_ci pc->packet_start = 0; 99cabdff1aSopenharmony_ci } else { 100cabdff1aSopenharmony_ci pc->packet_start = 0; 101cabdff1aSopenharmony_ci pc->packet_index = 0; 102cabdff1aSopenharmony_ci } 103cabdff1aSopenharmony_ci } 104cabdff1aSopenharmony_ci } 105cabdff1aSopenharmony_ci 106cabdff1aSopenharmony_ci if (buf_size - buf_pos + pc->packet_index > PARSE_BUF_SIZE) 107cabdff1aSopenharmony_ci return buf_size; 108cabdff1aSopenharmony_ci 109cabdff1aSopenharmony_ci/* if not currently in a packet, pass data */ 110cabdff1aSopenharmony_ci if (pc->in_packet == 0) 111cabdff1aSopenharmony_ci return buf_size; 112cabdff1aSopenharmony_ci 113cabdff1aSopenharmony_ci memcpy(pc->packet_buf + pc->packet_index, buf + buf_pos, buf_size - buf_pos); 114cabdff1aSopenharmony_ci pc->packet_index += buf_size - buf_pos; 115cabdff1aSopenharmony_ci 116cabdff1aSopenharmony_ci p = pc->packet_buf; 117cabdff1aSopenharmony_ci p_end = pc->packet_buf + pc->packet_index; 118cabdff1aSopenharmony_ci 119cabdff1aSopenharmony_ci while (p < p_end) 120cabdff1aSopenharmony_ci { 121cabdff1aSopenharmony_ci if (*p == 0x0f) 122cabdff1aSopenharmony_ci { 123cabdff1aSopenharmony_ci if (6 <= p_end - p) 124cabdff1aSopenharmony_ci { 125cabdff1aSopenharmony_ci len = AV_RB16(p + 4); 126cabdff1aSopenharmony_ci 127cabdff1aSopenharmony_ci if (len + 6 <= p_end - p) 128cabdff1aSopenharmony_ci { 129cabdff1aSopenharmony_ci out_size += len + 6; 130cabdff1aSopenharmony_ci 131cabdff1aSopenharmony_ci p += len + 6; 132cabdff1aSopenharmony_ci } else 133cabdff1aSopenharmony_ci break; 134cabdff1aSopenharmony_ci } else 135cabdff1aSopenharmony_ci break; 136cabdff1aSopenharmony_ci } else if (*p == 0xff) { 137cabdff1aSopenharmony_ci if (1 < p_end - p) 138cabdff1aSopenharmony_ci { 139cabdff1aSopenharmony_ci ff_dlog(avctx, "Junk at end of packet\n"); 140cabdff1aSopenharmony_ci } 141cabdff1aSopenharmony_ci pc->packet_index = p - pc->packet_buf; 142cabdff1aSopenharmony_ci pc->in_packet = 0; 143cabdff1aSopenharmony_ci break; 144cabdff1aSopenharmony_ci } else { 145cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Junk in packet\n"); 146cabdff1aSopenharmony_ci 147cabdff1aSopenharmony_ci pc->packet_index = p - pc->packet_buf; 148cabdff1aSopenharmony_ci pc->in_packet = 0; 149cabdff1aSopenharmony_ci break; 150cabdff1aSopenharmony_ci } 151cabdff1aSopenharmony_ci } 152cabdff1aSopenharmony_ci 153cabdff1aSopenharmony_ci if (out_size > 0) 154cabdff1aSopenharmony_ci { 155cabdff1aSopenharmony_ci *poutbuf = pc->packet_buf; 156cabdff1aSopenharmony_ci *poutbuf_size = out_size; 157cabdff1aSopenharmony_ci pc->packet_start = *poutbuf_size; 158cabdff1aSopenharmony_ci } 159cabdff1aSopenharmony_ci 160cabdff1aSopenharmony_ci if (s->pts == AV_NOPTS_VALUE) 161cabdff1aSopenharmony_ci s->pts = s->last_pts; 162cabdff1aSopenharmony_ci 163cabdff1aSopenharmony_ci return buf_size; 164cabdff1aSopenharmony_ci} 165cabdff1aSopenharmony_ci 166cabdff1aSopenharmony_ciconst AVCodecParser ff_dvbsub_parser = { 167cabdff1aSopenharmony_ci .codec_ids = { AV_CODEC_ID_DVB_SUBTITLE }, 168cabdff1aSopenharmony_ci .priv_data_size = sizeof(DVBSubParseContext), 169cabdff1aSopenharmony_ci .parser_parse = dvbsub_parse, 170cabdff1aSopenharmony_ci}; 171