libavformat/oggparseogm.c
Go to the documentation of this file.
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);    /* useless size field */
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);    /* default_len */
00084         bytestream2_skip(&p, 8);    /* buffersize + bits_per_sample */
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); /* block_align */
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 };