00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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);
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);
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 };