00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 #include <stdlib.h>
00026 #include "libavutil/bswap.h"
00027 #include "libavutil/avstring.h"
00028 #include "libavcodec/get_bits.h"
00029 #include "libavcodec/bytestream.h"
00030 #include "avformat.h"
00031 #include "internal.h"
00032 #include "oggdec.h"
00033 
00034 struct speex_params {
00035     int packet_size;
00036     int final_packet_duration;
00037     int seq;
00038 };
00039 
00040 static int speex_header(AVFormatContext *s, int idx) {
00041     struct ogg *ogg = s->priv_data;
00042     struct ogg_stream *os = ogg->streams + idx;
00043     struct speex_params *spxp = os->private;
00044     AVStream *st = s->streams[idx];
00045     uint8_t *p = os->buf + os->pstart;
00046 
00047     if (!spxp) {
00048         spxp = av_mallocz(sizeof(*spxp));
00049         os->private = spxp;
00050     }
00051 
00052     if (spxp->seq > 1)
00053         return 0;
00054 
00055     if (spxp->seq == 0) {
00056         int frames_per_packet;
00057         st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
00058         st->codec->codec_id = AV_CODEC_ID_SPEEX;
00059 
00060         st->codec->sample_rate = AV_RL32(p + 36);
00061         st->codec->channels = AV_RL32(p + 48);
00062 
00063         spxp->packet_size  = AV_RL32(p + 56);
00064         frames_per_packet  = AV_RL32(p + 64);
00065         if (frames_per_packet)
00066             spxp->packet_size *= frames_per_packet;
00067 
00068         st->codec->extradata_size = os->psize;
00069         st->codec->extradata = av_malloc(st->codec->extradata_size
00070                                          + FF_INPUT_BUFFER_PADDING_SIZE);
00071         memcpy(st->codec->extradata, p, st->codec->extradata_size);
00072 
00073         avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
00074     } else
00075         ff_vorbis_comment(s, &st->metadata, p, os->psize);
00076 
00077     spxp->seq++;
00078     return 1;
00079 }
00080 
00081 static int ogg_page_packets(struct ogg_stream *os)
00082 {
00083     int i;
00084     int packets = 0;
00085     for (i = 0; i < os->nsegs; i++)
00086         if (os->segments[i] < 255)
00087             packets++;
00088     return packets;
00089 }
00090 
00091 static int speex_packet(AVFormatContext *s, int idx)
00092 {
00093     struct ogg *ogg = s->priv_data;
00094     struct ogg_stream *os = ogg->streams + idx;
00095     struct speex_params *spxp = os->private;
00096     int packet_size = spxp->packet_size;
00097 
00098     if (os->flags & OGG_FLAG_EOS && os->lastpts != AV_NOPTS_VALUE &&
00099         os->granule > 0) {
00100         
00101 
00102 
00103         spxp->final_packet_duration = os->granule - os->lastpts -
00104                                       packet_size * (ogg_page_packets(os) - 1);
00105     }
00106 
00107     if (!os->lastpts && os->granule > 0)
00108         
00109         os->lastpts = os->lastdts = os->granule - packet_size *
00110                                     ogg_page_packets(os);
00111     if (os->flags & OGG_FLAG_EOS && os->segp == os->nsegs &&
00112         spxp->final_packet_duration)
00113         
00114         os->pduration = spxp->final_packet_duration;
00115     else
00116         os->pduration = packet_size;
00117 
00118     return 0;
00119 }
00120 
00121 const struct ogg_codec ff_speex_codec = {
00122     .magic = "Speex   ",
00123     .magicsize = 8,
00124     .header = speex_header,
00125     .packet = speex_packet,
00126     .nb_header = 2,
00127 };