Libav 0.7.1
|
00001 /* 00002 Copyright (C) 2008 Reimar Döffinger 00003 00004 Permission is hereby granted, free of charge, to any person 00005 obtaining a copy of this software and associated documentation 00006 files (the "Software"), to deal in the Software without 00007 restriction, including without limitation the rights to use, copy, 00008 modify, merge, publish, distribute, sublicense, and/or sell copies 00009 of the Software, and to permit persons to whom the Software is 00010 furnished to do so, subject to the following conditions: 00011 00012 The above copyright notice and this permission notice shall be 00013 included in all copies or substantial portions of the Software. 00014 00015 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 00016 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 00017 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 00018 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 00019 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 00020 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00021 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 00022 DEALINGS IN THE SOFTWARE. 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 /* We treat the whole Speex packet as a single frame everywhere Speex 00062 is handled in Libav. This avoids the complexities of splitting 00063 and joining individual Speex frames, which are not always 00064 byte-aligned. */ 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 av_set_pts_info(st, 64, 1, st->codec->sample_rate); 00076 } else 00077 ff_vorbis_comment(s, &st->metadata, p, os->psize); 00078 00079 spxp->seq++; 00080 return 1; 00081 } 00082 00083 static int ogg_page_packets(struct ogg_stream *os) 00084 { 00085 int i; 00086 int packets = 0; 00087 for (i = 0; i < os->nsegs; i++) 00088 if (os->segments[i] < 255) 00089 packets++; 00090 return packets; 00091 } 00092 00093 static int speex_packet(AVFormatContext *s, int idx) 00094 { 00095 struct ogg *ogg = s->priv_data; 00096 struct ogg_stream *os = ogg->streams + idx; 00097 struct speex_params *spxp = os->private; 00098 int packet_size = s->streams[idx]->codec->frame_size; 00099 00100 if (os->flags & OGG_FLAG_EOS && os->lastpts != AV_NOPTS_VALUE && 00101 os->granule > 0) { 00102 /* first packet of final page. we have to calculate the final packet 00103 duration here because it is the only place we know the next-to-last 00104 granule position. */ 00105 spxp->final_packet_duration = os->granule - os->lastpts - 00106 packet_size * (ogg_page_packets(os) - 1); 00107 } 00108 00109 if (!os->lastpts && os->granule > 0) 00110 /* first packet */ 00111 os->pduration = os->granule - packet_size * (ogg_page_packets(os) - 1); 00112 else if (os->flags & OGG_FLAG_EOS && os->segp == os->nsegs && 00113 spxp->final_packet_duration) 00114 /* final packet */ 00115 os->pduration = spxp->final_packet_duration; 00116 else 00117 os->pduration = packet_size; 00118 00119 return 0; 00120 } 00121 00122 const struct ogg_codec ff_speex_codec = { 00123 .magic = "Speex ", 00124 .magicsize = 8, 00125 .header = speex_header, 00126 .packet = speex_packet 00127 };