Libav 0.7.1
|
00001 /* 00002 * Chronomaster DFA Format Demuxer 00003 * Copyright (c) 2011 Konstantin Shishkov 00004 * 00005 * This file is part of Libav. 00006 * 00007 * Libav is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * Libav is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with Libav; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00020 */ 00021 00022 #include "libavutil/intreadwrite.h" 00023 #include "avformat.h" 00024 00025 static int dfa_probe(AVProbeData *p) 00026 { 00027 if (p->buf_size < 4 || AV_RL32(p->buf) != MKTAG('D', 'F', 'I', 'A')) 00028 return 0; 00029 00030 return AVPROBE_SCORE_MAX; 00031 } 00032 00033 static int dfa_read_header(AVFormatContext *s, 00034 AVFormatParameters *ap) 00035 { 00036 AVIOContext *pb = s->pb; 00037 AVStream *st; 00038 int frames; 00039 uint32_t mspf; 00040 00041 if (avio_rl32(pb) != MKTAG('D', 'F', 'I', 'A')) { 00042 av_log(s, AV_LOG_ERROR, "Invalid magic for DFA\n"); 00043 return AVERROR_INVALIDDATA; 00044 } 00045 avio_skip(pb, 2); // unused 00046 frames = avio_rl16(pb); 00047 00048 st = av_new_stream(s, 0); 00049 if (!st) 00050 return AVERROR(ENOMEM); 00051 00052 st->codec->codec_type = AVMEDIA_TYPE_VIDEO; 00053 st->codec->codec_id = CODEC_ID_DFA; 00054 st->codec->width = avio_rl16(pb); 00055 st->codec->height = avio_rl16(pb); 00056 mspf = avio_rl32(pb); 00057 if (!mspf) { 00058 av_log(s, AV_LOG_WARNING, "Zero FPS reported, defaulting to 10\n"); 00059 mspf = 100; 00060 } 00061 av_set_pts_info(st, 24, mspf, 1000); 00062 avio_skip(pb, 128 - 16); // padding 00063 st->duration = frames; 00064 00065 return 0; 00066 } 00067 00068 static int dfa_read_packet(AVFormatContext *s, AVPacket *pkt) 00069 { 00070 AVIOContext *pb = s->pb; 00071 uint32_t frame_size; 00072 int ret, first = 1; 00073 00074 if (pb->eof_reached) 00075 return AVERROR_EOF; 00076 00077 if (av_get_packet(pb, pkt, 12) != 12) 00078 return AVERROR(EIO); 00079 while (!pb->eof_reached) { 00080 if (!first) { 00081 ret = av_append_packet(pb, pkt, 12); 00082 if (ret < 0) { 00083 av_free_packet(pkt); 00084 return ret; 00085 } 00086 } else 00087 first = 0; 00088 frame_size = AV_RL32(pkt->data + pkt->size - 8); 00089 if (frame_size > INT_MAX - 4) { 00090 av_log(s, AV_LOG_ERROR, "Too large chunk size: %d\n", frame_size); 00091 return AVERROR(EIO); 00092 } 00093 if (AV_RL32(pkt->data + pkt->size - 12) == MKTAG('E', 'O', 'F', 'R')) { 00094 if (frame_size) { 00095 av_log(s, AV_LOG_WARNING, "skipping %d bytes of end-of-frame marker chunk\n", 00096 frame_size); 00097 avio_skip(pb, frame_size); 00098 } 00099 return 0; 00100 } 00101 ret = av_append_packet(pb, pkt, frame_size); 00102 if (ret < 0) { 00103 av_free_packet(pkt); 00104 return ret; 00105 } 00106 } 00107 00108 return 0; 00109 } 00110 00111 AVInputFormat ff_dfa_demuxer = { 00112 "dfa", 00113 NULL_IF_CONFIG_SMALL("Chronomaster DFA"), 00114 0, 00115 dfa_probe, 00116 dfa_read_header, 00117 dfa_read_packet, 00118 .flags = AVFMT_GENERIC_INDEX, 00119 };