1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * This file is part of FFmpeg. 3cabdff1aSopenharmony_ci * 4cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 5cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 6cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 7cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 8cabdff1aSopenharmony_ci * 9cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 10cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 11cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12cabdff1aSopenharmony_ci * Lesser General Public License for more details. 13cabdff1aSopenharmony_ci * 14cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 15cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 16cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17cabdff1aSopenharmony_ci */ 18cabdff1aSopenharmony_ci 19cabdff1aSopenharmony_ci#include "avformat.h" 20cabdff1aSopenharmony_ci#include "internal.h" 21cabdff1aSopenharmony_ci#include "libavutil/intreadwrite.h" 22cabdff1aSopenharmony_ci 23cabdff1aSopenharmony_ci#define SUP_PGS_MAGIC 0x5047 /* "PG", big endian */ 24cabdff1aSopenharmony_ci 25cabdff1aSopenharmony_cistatic int sup_read_header(AVFormatContext *s) 26cabdff1aSopenharmony_ci{ 27cabdff1aSopenharmony_ci AVStream *st = avformat_new_stream(s, NULL); 28cabdff1aSopenharmony_ci if (!st) 29cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 30cabdff1aSopenharmony_ci st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE; 31cabdff1aSopenharmony_ci st->codecpar->codec_id = AV_CODEC_ID_HDMV_PGS_SUBTITLE; 32cabdff1aSopenharmony_ci avpriv_set_pts_info(st, 32, 1, 90000); 33cabdff1aSopenharmony_ci 34cabdff1aSopenharmony_ci return 0; 35cabdff1aSopenharmony_ci} 36cabdff1aSopenharmony_ci 37cabdff1aSopenharmony_cistatic int sup_read_packet(AVFormatContext *s, AVPacket *pkt) 38cabdff1aSopenharmony_ci{ 39cabdff1aSopenharmony_ci int64_t pts, dts, pos; 40cabdff1aSopenharmony_ci int ret; 41cabdff1aSopenharmony_ci 42cabdff1aSopenharmony_ci pos = avio_tell(s->pb); 43cabdff1aSopenharmony_ci 44cabdff1aSopenharmony_ci if (avio_rb16(s->pb) != SUP_PGS_MAGIC) 45cabdff1aSopenharmony_ci return avio_feof(s->pb) ? AVERROR_EOF : AVERROR_INVALIDDATA; 46cabdff1aSopenharmony_ci 47cabdff1aSopenharmony_ci pts = avio_rb32(s->pb); 48cabdff1aSopenharmony_ci dts = avio_rb32(s->pb); 49cabdff1aSopenharmony_ci 50cabdff1aSopenharmony_ci if ((ret = av_get_packet(s->pb, pkt, 3)) < 0) 51cabdff1aSopenharmony_ci return ret; 52cabdff1aSopenharmony_ci 53cabdff1aSopenharmony_ci pkt->stream_index = 0; 54cabdff1aSopenharmony_ci pkt->flags |= AV_PKT_FLAG_KEY; 55cabdff1aSopenharmony_ci pkt->pos = pos; 56cabdff1aSopenharmony_ci pkt->pts = pts; 57cabdff1aSopenharmony_ci // Many files have DTS set to 0 for all packets, so assume 0 means unset. 58cabdff1aSopenharmony_ci pkt->dts = dts ? dts : AV_NOPTS_VALUE; 59cabdff1aSopenharmony_ci 60cabdff1aSopenharmony_ci if (pkt->size >= 3) { 61cabdff1aSopenharmony_ci // The full packet size is stored as part of the packet. 62cabdff1aSopenharmony_ci size_t len = AV_RB16(pkt->data + 1); 63cabdff1aSopenharmony_ci 64cabdff1aSopenharmony_ci if ((ret = av_append_packet(s->pb, pkt, len)) < 0) 65cabdff1aSopenharmony_ci return ret; 66cabdff1aSopenharmony_ci } 67cabdff1aSopenharmony_ci 68cabdff1aSopenharmony_ci return 0; 69cabdff1aSopenharmony_ci} 70cabdff1aSopenharmony_ci 71cabdff1aSopenharmony_cistatic int sup_probe(const AVProbeData *p) 72cabdff1aSopenharmony_ci{ 73cabdff1aSopenharmony_ci unsigned char *buf = p->buf; 74cabdff1aSopenharmony_ci size_t buf_size = p->buf_size; 75cabdff1aSopenharmony_ci int nb_packets; 76cabdff1aSopenharmony_ci 77cabdff1aSopenharmony_ci for (nb_packets = 0; nb_packets < 10; nb_packets++) { 78cabdff1aSopenharmony_ci size_t full_packet_size; 79cabdff1aSopenharmony_ci if (buf_size < 10 + 3) 80cabdff1aSopenharmony_ci break; 81cabdff1aSopenharmony_ci if (AV_RB16(buf) != SUP_PGS_MAGIC) 82cabdff1aSopenharmony_ci return 0; 83cabdff1aSopenharmony_ci full_packet_size = AV_RB16(buf + 10 + 1) + 10 + 3; 84cabdff1aSopenharmony_ci if (buf_size < full_packet_size) 85cabdff1aSopenharmony_ci break; 86cabdff1aSopenharmony_ci buf += full_packet_size; 87cabdff1aSopenharmony_ci buf_size -= full_packet_size; 88cabdff1aSopenharmony_ci } 89cabdff1aSopenharmony_ci if (!nb_packets) 90cabdff1aSopenharmony_ci return 0; 91cabdff1aSopenharmony_ci if (nb_packets < 2) 92cabdff1aSopenharmony_ci return AVPROBE_SCORE_RETRY / 2; 93cabdff1aSopenharmony_ci if (nb_packets < 4) 94cabdff1aSopenharmony_ci return AVPROBE_SCORE_RETRY; 95cabdff1aSopenharmony_ci if (nb_packets < 10) 96cabdff1aSopenharmony_ci return AVPROBE_SCORE_EXTENSION; 97cabdff1aSopenharmony_ci return AVPROBE_SCORE_MAX; 98cabdff1aSopenharmony_ci} 99cabdff1aSopenharmony_ci 100cabdff1aSopenharmony_ciconst AVInputFormat ff_sup_demuxer = { 101cabdff1aSopenharmony_ci .name = "sup", 102cabdff1aSopenharmony_ci .long_name = NULL_IF_CONFIG_SMALL("raw HDMV Presentation Graphic Stream subtitles"), 103cabdff1aSopenharmony_ci .extensions = "sup", 104cabdff1aSopenharmony_ci .mime_type = "application/x-pgs", 105cabdff1aSopenharmony_ci .read_probe = sup_probe, 106cabdff1aSopenharmony_ci .read_header = sup_read_header, 107cabdff1aSopenharmony_ci .read_packet = sup_read_packet, 108cabdff1aSopenharmony_ci .flags = AVFMT_GENERIC_INDEX, 109cabdff1aSopenharmony_ci}; 110