1/* 2 * Adobe Filmstrip demuxer 3 * Copyright (c) 2010 Peter Ross 4 * 5 * This file is part of Libav. 6 * 7 * Libav 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 * Libav 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 Libav; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 */ 21 22/** 23 * @file 24 * Adobe Filmstrip demuxer 25 */ 26 27#include "libavutil/intreadwrite.h" 28#include "avformat.h" 29#include "internal.h" 30 31#define RAND_TAG MKBETAG('R','a','n','d') 32 33typedef struct { 34 int leading; 35} FilmstripDemuxContext; 36 37static int read_header(AVFormatContext *s, 38 AVFormatParameters *ap) 39{ 40 FilmstripDemuxContext *film = s->priv_data; 41 AVIOContext *pb = s->pb; 42 AVStream *st; 43 44 if (!s->pb->seekable) 45 return AVERROR(EIO); 46 47 avio_seek(pb, avio_size(pb) - 36, SEEK_SET); 48 if (avio_rb32(pb) != RAND_TAG) { 49 av_log(s, AV_LOG_ERROR, "magic number not found"); 50 return AVERROR_INVALIDDATA; 51 } 52 53 st = avformat_new_stream(s, NULL); 54 if (!st) 55 return AVERROR(ENOMEM); 56 57 st->nb_frames = avio_rb32(pb); 58 if (avio_rb16(pb) != 0) { 59 av_log_ask_for_sample(s, "unsupported packing method\n"); 60 return AVERROR_INVALIDDATA; 61 } 62 63 avio_skip(pb, 2); 64 st->codec->codec_type = AVMEDIA_TYPE_VIDEO; 65 st->codec->codec_id = CODEC_ID_RAWVIDEO; 66 st->codec->pix_fmt = PIX_FMT_RGBA; 67 st->codec->codec_tag = 0; /* no fourcc */ 68 st->codec->width = avio_rb16(pb); 69 st->codec->height = avio_rb16(pb); 70 film->leading = avio_rb16(pb); 71 avpriv_set_pts_info(st, 64, 1, avio_rb16(pb)); 72 73 avio_seek(pb, 0, SEEK_SET); 74 75 return 0; 76} 77 78static int read_packet(AVFormatContext *s, 79 AVPacket *pkt) 80{ 81 FilmstripDemuxContext *film = s->priv_data; 82 AVStream *st = s->streams[0]; 83 84 if (s->pb->eof_reached) 85 return AVERROR(EIO); 86 pkt->dts = avio_tell(s->pb) / (st->codec->width * (st->codec->height + film->leading) * 4); 87 pkt->size = av_get_packet(s->pb, pkt, st->codec->width * st->codec->height * 4); 88 avio_skip(s->pb, st->codec->width * film->leading * 4); 89 if (pkt->size < 0) 90 return pkt->size; 91 pkt->flags |= AV_PKT_FLAG_KEY; 92 return 0; 93} 94 95static int read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) 96{ 97 AVStream *st = s->streams[stream_index]; 98 avio_seek(s->pb, FFMAX(timestamp, 0) * st->codec->width * st->codec->height * 4, SEEK_SET); 99 return 0; 100} 101 102AVInputFormat ff_filmstrip_demuxer = { 103 .name = "filmstrip", 104 .long_name = NULL_IF_CONFIG_SMALL("Adobe Filmstrip"), 105 .priv_data_size = sizeof(FilmstripDemuxContext), 106 .read_header = read_header, 107 .read_packet = read_packet, 108 .read_seek = read_seek, 109 .extensions = "flm", 110}; 111