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 "oggdec.h"
00032
00033 struct speex_params {
00034 int final_packet_duration;
00035 int seq;
00036 };
00037
00038 static int speex_header(AVFormatContext *s, int idx) {
00039 struct ogg *ogg = s->priv_data;
00040 struct ogg_stream *os = ogg->streams + idx;
00041 struct speex_params *spxp = os->private;
00042 AVStream *st = s->streams[idx];
00043 uint8_t *p = os->buf + os->pstart;
00044
00045 if (!spxp) {
00046 spxp = av_mallocz(sizeof(*spxp));
00047 os->private = spxp;
00048 }
00049
00050 if (spxp->seq > 1)
00051 return 0;
00052
00053 if (spxp->seq == 0) {
00054 int frames_per_packet;
00055 st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
00056 st->codec->codec_id = CODEC_ID_SPEEX;
00057
00058 st->codec->sample_rate = AV_RL32(p + 36);
00059 st->codec->channels = AV_RL32(p + 48);
00060
00061
00062
00063
00064
00065 st->codec->frame_size = AV_RL32(p + 56);
00066 frames_per_packet = AV_RL32(p + 64);
00067 if (frames_per_packet)
00068 st->codec->frame_size *= frames_per_packet;
00069
00070 st->codec->extradata_size = os->psize;
00071 st->codec->extradata = av_malloc(st->codec->extradata_size
00072 + FF_INPUT_BUFFER_PADDING_SIZE);
00073 memcpy(st->codec->extradata, p, st->codec->extradata_size);
00074
00075 st->time_base.num = 1;
00076 st->time_base.den = st->codec->sample_rate;
00077 } else
00078 ff_vorbis_comment(s, &st->metadata, p, os->psize);
00079
00080 spxp->seq++;
00081 return 1;
00082 }
00083
00084 static int ogg_page_packets(struct ogg_stream *os)
00085 {
00086 int i;
00087 int packets = 0;
00088 for (i = 0; i < os->nsegs; i++)
00089 if (os->segments[i] < 255)
00090 packets++;
00091 return packets;
00092 }
00093
00094 static int speex_packet(AVFormatContext *s, int idx)
00095 {
00096 struct ogg *ogg = s->priv_data;
00097 struct ogg_stream *os = ogg->streams + idx;
00098 struct speex_params *spxp = os->private;
00099 int packet_size = s->streams[idx]->codec->frame_size;
00100
00101 if (os->flags & OGG_FLAG_EOS && os->lastpts != AV_NOPTS_VALUE &&
00102 os->granule > 0) {
00103
00104
00105
00106 spxp->final_packet_duration = os->granule - os->lastpts -
00107 packet_size * (ogg_page_packets(os) - 1);
00108 }
00109
00110 if (!os->lastpts && os->granule > 0)
00111
00112 os->pduration = os->granule - packet_size * (ogg_page_packets(os) - 1);
00113 else if (os->flags & OGG_FLAG_EOS && os->segp == os->nsegs &&
00114 spxp->final_packet_duration)
00115
00116 os->pduration = spxp->final_packet_duration;
00117 else
00118 os->pduration = packet_size;
00119
00120 return 0;
00121 }
00122
00123 const struct ogg_codec ff_speex_codec = {
00124 .magic = "Speex ",
00125 .magicsize = 8,
00126 .header = speex_header,
00127 .packet = speex_packet
00128 };