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 #include "riff.h"
00025
00026 static int lvf_probe(AVProbeData *p)
00027 {
00028 if (AV_RL32(p->buf) == MKTAG('L', 'V', 'F', 'F'))
00029 return AVPROBE_SCORE_MAX / 2;
00030 return 0;
00031 }
00032
00033 static int lvf_read_header(AVFormatContext *s)
00034 {
00035 AVStream *st;
00036 int64_t next_offset;
00037 unsigned size, nb_streams, id;
00038
00039 avio_skip(s->pb, 16);
00040 nb_streams = avio_rl32(s->pb);
00041 if (!nb_streams)
00042 return AVERROR_INVALIDDATA;
00043 if (nb_streams > 2) {
00044 av_log_ask_for_sample(s, "too many streams\n");
00045 return AVERROR_PATCHWELCOME;
00046 }
00047
00048 avio_skip(s->pb, 1012);
00049
00050 while (!url_feof(s->pb)) {
00051 id = avio_rl32(s->pb);
00052 size = avio_rl32(s->pb);
00053 next_offset = avio_tell(s->pb) + size;
00054
00055 switch (id) {
00056 case MKTAG('0', '0', 'f', 'm'):
00057 st = avformat_new_stream(s, 0);
00058 if (!st)
00059 return AVERROR(ENOMEM);
00060
00061 st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
00062 avio_skip(s->pb, 4);
00063 st->codec->width = avio_rl32(s->pb);
00064 st->codec->height = avio_rl32(s->pb);
00065 avio_skip(s->pb, 4);
00066 st->codec->codec_tag = avio_rl32(s->pb);
00067 st->codec->codec_id = ff_codec_get_id(ff_codec_bmp_tags,
00068 st->codec->codec_tag);
00069 avpriv_set_pts_info(st, 32, 1, 1000);
00070 break;
00071 case MKTAG('0', '1', 'f', 'm'):
00072 st = avformat_new_stream(s, 0);
00073 if (!st)
00074 return AVERROR(ENOMEM);
00075
00076 st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
00077 st->codec->codec_tag = avio_rl16(s->pb);
00078 st->codec->channels = avio_rl16(s->pb);
00079 st->codec->sample_rate = avio_rl16(s->pb);
00080 avio_skip(s->pb, 8);
00081 st->codec->bits_per_coded_sample = avio_r8(s->pb);
00082 st->codec->codec_id = ff_codec_get_id(ff_codec_wav_tags,
00083 st->codec->codec_tag);
00084 avpriv_set_pts_info(st, 32, 1, 1000);
00085 break;
00086 case 0:
00087 avio_seek(s->pb, 2048 + 8, SEEK_SET);
00088 return 0;
00089 default:
00090 av_log_ask_for_sample(s, "unknown id\n");
00091 return AVERROR_PATCHWELCOME;
00092 }
00093
00094 avio_seek(s->pb, next_offset, SEEK_SET);
00095 }
00096
00097 return AVERROR_EOF;
00098 }
00099
00100 static int lvf_read_packet(AVFormatContext *s, AVPacket *pkt)
00101 {
00102 unsigned size, flags, timestamp, id;
00103 int64_t pos;
00104 int ret, is_video = 0;
00105
00106 pos = avio_tell(s->pb);
00107 while (!url_feof(s->pb)) {
00108 id = avio_rl32(s->pb);
00109 size = avio_rl32(s->pb);
00110
00111 if (size == 0xFFFFFFFFu)
00112 return AVERROR_EOF;
00113
00114 switch (id) {
00115 case MKTAG('0', '0', 'd', 'c'):
00116 is_video = 1;
00117 case MKTAG('0', '1', 'w', 'b'):
00118 if (size < 8)
00119 return AVERROR_INVALIDDATA;
00120 timestamp = avio_rl32(s->pb);
00121 flags = avio_rl32(s->pb);
00122 ret = av_get_packet(s->pb, pkt, size - 8);
00123 if (flags & (1 << 12))
00124 pkt->flags |= AV_PKT_FLAG_KEY;
00125 pkt->stream_index = is_video ? 0 : 1;
00126 pkt->pts = timestamp;
00127 pkt->pos = pos;
00128 return ret;
00129 default:
00130 ret = avio_skip(s->pb, size);
00131 }
00132
00133 if (ret < 0)
00134 return ret;
00135 }
00136
00137 return AVERROR_EOF;
00138 }
00139
00140 AVInputFormat ff_lvf_demuxer = {
00141 .name = "lvf",
00142 .long_name = NULL_IF_CONFIG_SMALL("LVF"),
00143 .read_probe = lvf_probe,
00144 .read_header = lvf_read_header,
00145 .read_packet = lvf_read_packet,
00146 .extensions = "lvf",
00147 .flags = AVFMT_GENERIC_INDEX,
00148 };