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