Libav 0.7.1
libavformat/dfa.c
Go to the documentation of this file.
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 };