00001
00025 #include <stdlib.h>
00026 #include "libavutil/intreadwrite.h"
00027 #include "libavcodec/get_bits.h"
00028 #include "libavcodec/bytestream.h"
00029 #include "avformat.h"
00030 #include "oggdec.h"
00031 #include "riff.h"
00032
00033 static int
00034 ogm_header(AVFormatContext *s, int idx)
00035 {
00036 struct ogg *ogg = s->priv_data;
00037 struct ogg_stream *os = ogg->streams + idx;
00038 AVStream *st = s->streams[idx];
00039 const uint8_t *p = os->buf + os->pstart;
00040 uint64_t time_unit;
00041 uint64_t spu;
00042
00043 if(!(*p & 1))
00044 return 0;
00045
00046 if(*p == 1) {
00047 p++;
00048
00049 if(*p == 'v'){
00050 int tag;
00051 st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
00052 p += 8;
00053 tag = bytestream_get_le32(&p);
00054 st->codec->codec_id = ff_codec_get_id(ff_codec_bmp_tags, tag);
00055 st->codec->codec_tag = tag;
00056 } else if (*p == 't') {
00057 st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE;
00058 st->codec->codec_id = CODEC_ID_TEXT;
00059 p += 12;
00060 } else {
00061 uint8_t acid[5];
00062 int cid;
00063 st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
00064 p += 8;
00065 bytestream_get_buffer(&p, acid, 4);
00066 acid[4] = 0;
00067 cid = strtol(acid, NULL, 16);
00068 st->codec->codec_id = ff_codec_get_id(ff_codec_wav_tags, cid);
00069 st->need_parsing = AVSTREAM_PARSE_FULL;
00070 }
00071
00072 p += 4;
00073
00074 time_unit = bytestream_get_le64(&p);
00075 spu = bytestream_get_le64(&p);
00076 p += 4;
00077 p += 8;
00078
00079 if(st->codec->codec_type == AVMEDIA_TYPE_VIDEO){
00080 st->codec->width = bytestream_get_le32(&p);
00081 st->codec->height = bytestream_get_le32(&p);
00082 st->codec->time_base.den = spu * 10000000;
00083 st->codec->time_base.num = time_unit;
00084 av_set_pts_info(st, 64, st->codec->time_base.num, st->codec->time_base.den);
00085 } else {
00086 st->codec->channels = bytestream_get_le16(&p);
00087 p += 2;
00088 st->codec->bit_rate = bytestream_get_le32(&p) * 8;
00089 st->codec->sample_rate = spu * 10000000 / time_unit;
00090 av_set_pts_info(st, 64, 1, st->codec->sample_rate);
00091 }
00092 } else if (*p == 3) {
00093 if (os->psize > 8)
00094 ff_vorbis_comment(s, &st->metadata, p+7, os->psize-8);
00095 }
00096
00097 return 1;
00098 }
00099
00100 static int
00101 ogm_dshow_header(AVFormatContext *s, int idx)
00102 {
00103 struct ogg *ogg = s->priv_data;
00104 struct ogg_stream *os = ogg->streams + idx;
00105 AVStream *st = s->streams[idx];
00106 uint8_t *p = os->buf + os->pstart;
00107 uint32_t t;
00108
00109 if(!(*p & 1))
00110 return 0;
00111 if(*p != 1)
00112 return 1;
00113
00114 t = AV_RL32(p + 96);
00115
00116 if(t == 0x05589f80){
00117 st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
00118 st->codec->codec_id = ff_codec_get_id(ff_codec_bmp_tags, AV_RL32(p + 68));
00119 st->codec->time_base.den = 10000000;
00120 st->codec->time_base.num = AV_RL64(p + 164);
00121 st->codec->width = AV_RL32(p + 176);
00122 st->codec->height = AV_RL32(p + 180);
00123 } else if(t == 0x05589f81){
00124 st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
00125 st->codec->codec_id = ff_codec_get_id(ff_codec_wav_tags, AV_RL16(p + 124));
00126 st->codec->channels = AV_RL16(p + 126);
00127 st->codec->sample_rate = AV_RL32(p + 128);
00128 st->codec->bit_rate = AV_RL32(p + 132) * 8;
00129 }
00130
00131 return 1;
00132 }
00133
00134 static int
00135 ogm_packet(AVFormatContext *s, int idx)
00136 {
00137 struct ogg *ogg = s->priv_data;
00138 struct ogg_stream *os = ogg->streams + idx;
00139 uint8_t *p = os->buf + os->pstart;
00140 int lb;
00141
00142 if(*p & 8)
00143 os->pflags |= AV_PKT_FLAG_KEY;
00144
00145 lb = ((*p & 2) << 1) | ((*p >> 6) & 3);
00146 os->pstart += lb + 1;
00147 os->psize -= lb + 1;
00148
00149 while (lb--)
00150 os->pduration += p[lb+1] << (lb*8);
00151
00152 return 0;
00153 }
00154
00155 const struct ogg_codec ff_ogm_video_codec = {
00156 .magic = "\001video",
00157 .magicsize = 6,
00158 .header = ogm_header,
00159 .packet = ogm_packet,
00160 .granule_is_start = 1,
00161 };
00162
00163 const struct ogg_codec ff_ogm_audio_codec = {
00164 .magic = "\001audio",
00165 .magicsize = 6,
00166 .header = ogm_header,
00167 .packet = ogm_packet,
00168 .granule_is_start = 1,
00169 };
00170
00171 const struct ogg_codec ff_ogm_text_codec = {
00172 .magic = "\001text",
00173 .magicsize = 5,
00174 .header = ogm_header,
00175 .packet = ogm_packet,
00176 .granule_is_start = 1,
00177 };
00178
00179 const struct ogg_codec ff_ogm_old_codec = {
00180 .magic = "\001Direct Show Samples embedded in Ogg",
00181 .magicsize = 35,
00182 .header = ogm_dshow_header,
00183 .packet = ogm_packet,
00184 .granule_is_start = 1,
00185 };