Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/FFmpeg/FFmpeg.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Niedermayer <michaelni@gmx.at>2012-10-07 13:23:29 +0400
committerMichael Niedermayer <michaelni@gmx.at>2012-10-07 13:28:38 +0400
commit79d30321a29dc648d5a475ce5086b2760d5d8c12 (patch)
treec712b09b56a0937ca08a1c89365addd8e4e33d4b
parent537ef8bebf8a35aab448db6ec876e275a10f0f15 (diff)
parent31b2262dca9cc77709d20c45610ec8030e7f9257 (diff)
Merge remote-tracking branch 'qatar/master'
* qatar/master: wmaenc: use float planar sample format (e)ac3enc: use planar sample format aacenc: use planar sample format adpcmenc: use planar sample format for adpcm_ima_wav and adpcm_ima_qt adpcmenc: move 'ch' variable to higher scope adpcmenc: fix 3 instances of variable shadowing adpcm_ima_wav: simplify encoding libvorbis: use planar sample format libmp3lame: use planar sample formats vorbisenc: use float planar sample format ffm: do not write or read the audio sample format parseutils: fix parsing of invalid alpha values doc/RELEASE_NOTES: update for the 9 release. smoothstreamingenc: Add a more verbose error message smoothstreamingenc: Ignore the return value from mkdir smoothstreamingenc: Try writing a manifest when opening the muxer smoothstreamingenc: Move the output_chunk_list and write_manifest functions up smoothstreamingenc: Properly return errors from ism_flush to the caller smoothstreamingenc: Check the output UrlContext before accessing it Conflicts: doc/RELEASE_NOTES libavcodec/aacenc.c libavcodec/ac3enc_template.c libavcodec/wmaenc.c tests/ref/lavf/ffm Merged-by: Michael Niedermayer <michaelni@gmx.at>
-rw-r--r--libavcodec/aacenc.c33
-rw-r--r--libavcodec/ac3enc_fixed.c2
-rw-r--r--libavcodec/ac3enc_float.c2
-rw-r--r--libavcodec/ac3enc_template.c34
-rw-r--r--libavcodec/adpcmenc.c153
-rw-r--r--libavcodec/eac3enc.c2
-rw-r--r--libavcodec/libmp3lame.c104
-rw-r--r--libavcodec/libvorbisenc.c8
-rw-r--r--libavcodec/vorbisenc.c20
-rw-r--r--libavcodec/wma.c1
-rw-r--r--libavcodec/wma.h2
-rw-r--r--libavcodec/wmaenc.c32
-rw-r--r--libavformat/ffmdec.c1
-rw-r--r--libavformat/ffmenc.c1
-rw-r--r--libavformat/smoothstreamingenc.c206
-rw-r--r--libavutil/parseutils.c4
-rw-r--r--tests/ref/lavf/ffm2
17 files changed, 279 insertions, 328 deletions
diff --git a/libavcodec/aacenc.c b/libavcodec/aacenc.c
index 383cb5a7c1..9178babda6 100644
--- a/libavcodec/aacenc.c
+++ b/libavcodec/aacenc.c
@@ -479,31 +479,28 @@ static void put_bitstream_info(AVCodecContext *avctx, AACEncContext *s,
}
/*
- * Deinterleave input samples.
+ * Copy input samples.
* Channels are reordered from libavcodec's default order to AAC order.
*/
-static void deinterleave_input_samples(AACEncContext *s, const AVFrame *frame)
+static void copy_input_samples(AACEncContext *s, const AVFrame *frame)
{
- int ch, i;
- const int sinc = s->channels;
- const uint8_t *channel_map = aac_chan_maps[sinc - 1];
+ int ch;
+ int end = 2048 + (frame ? frame->nb_samples : 0);
+ const uint8_t *channel_map = aac_chan_maps[s->channels - 1];
- /* deinterleave and remap input samples */
- for (ch = 0; ch < sinc; ch++) {
+ /* copy and remap input samples */
+ for (ch = 0; ch < s->channels; ch++) {
/* copy last 1024 samples of previous frame to the start of the current frame */
memcpy(&s->planar_samples[ch][1024], &s->planar_samples[ch][2048], 1024 * sizeof(s->planar_samples[0][0]));
- /* deinterleave */
- i = 2048;
+ /* copy new samples and zero any remaining samples */
if (frame) {
- const float *sptr = ((const float *)frame->data[0]) + channel_map[ch];
- for (; i < 2048 + frame->nb_samples; i++) {
- s->planar_samples[ch][i] = *sptr;
- sptr += sinc;
- }
+ memcpy(&s->planar_samples[ch][2048],
+ frame->extended_data[channel_map[ch]],
+ frame->nb_samples * sizeof(s->planar_samples[0][0]));
}
- memset(&s->planar_samples[ch][i], 0,
- (3072 - i) * sizeof(s->planar_samples[0][0]));
+ memset(&s->planar_samples[ch][end], 0,
+ (3072 - end) * sizeof(s->planar_samples[0][0]));
}
}
@@ -526,7 +523,7 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
return ret;
}
- deinterleave_input_samples(s, frame);
+ copy_input_samples(s, frame);
if (s->psypp)
ff_psy_preprocess(s->psypp, s->planar_samples, s->channels);
@@ -827,7 +824,7 @@ AVCodec ff_aac_encoder = {
.supported_samplerates = avpriv_mpeg4audio_sample_rates,
.capabilities = CODEC_CAP_SMALL_LAST_FRAME | CODEC_CAP_DELAY |
CODEC_CAP_EXPERIMENTAL,
- .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLT,
+ .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLTP,
AV_SAMPLE_FMT_NONE },
.long_name = NULL_IF_CONFIG_SMALL("AAC (Advanced Audio Coding)"),
.priv_class = &aacenc_class,
diff --git a/libavcodec/ac3enc_fixed.c b/libavcodec/ac3enc_fixed.c
index fa109f9791..5d8dd5c3f1 100644
--- a/libavcodec/ac3enc_fixed.c
+++ b/libavcodec/ac3enc_fixed.c
@@ -160,7 +160,7 @@ AVCodec ff_ac3_fixed_encoder = {
.init = ac3_fixed_encode_init,
.encode2 = ff_ac3_fixed_encode_frame,
.close = ff_ac3_encode_close,
- .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16,
+ .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16P,
AV_SAMPLE_FMT_NONE },
.long_name = NULL_IF_CONFIG_SMALL("ATSC A/52A (AC-3)"),
.priv_class = &ac3enc_class,
diff --git a/libavcodec/ac3enc_float.c b/libavcodec/ac3enc_float.c
index 5afe0fe2ab..7864f41019 100644
--- a/libavcodec/ac3enc_float.c
+++ b/libavcodec/ac3enc_float.c
@@ -158,7 +158,7 @@ AVCodec ff_ac3_encoder = {
.init = ff_ac3_encode_init,
.encode2 = ff_ac3_float_encode_frame,
.close = ff_ac3_encode_close,
- .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLT,
+ .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLTP,
AV_SAMPLE_FMT_NONE },
.long_name = NULL_IF_CONFIG_SMALL("ATSC A/52A (AC-3)"),
.priv_class = &ac3enc_class,
diff --git a/libavcodec/ac3enc_template.c b/libavcodec/ac3enc_template.c
index e81bfce5a8..904e0bb9ef 100644
--- a/libavcodec/ac3enc_template.c
+++ b/libavcodec/ac3enc_template.c
@@ -4,20 +4,20 @@
* Copyright (c) 2006-2011 Justin Ruggles <justin.ruggles@gmail.com>
* Copyright (c) 2006-2010 Prakash Punnoor <prakash@punnoor.de>
*
- * This file is part of Libav.
+ * This file is part of FFmpeg.
*
- * Libav is free software; you can redistribute it and/or
+ * FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
- * Libav is distributed in the hope that it will be useful,
+ * FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with Libav; if not, write to the Free Software
+ * License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@@ -68,30 +68,23 @@ alloc_fail:
/*
- * Deinterleave input samples.
+ * Copy input samples.
* Channels are reordered from FFmpeg's default order to AC-3 order.
*/
-static void deinterleave_input_samples(AC3EncodeContext *s,
- const SampleType *samples)
+static void copy_input_samples(AC3EncodeContext *s, SampleType **samples)
{
- int ch, i;
+ int ch;
- /* deinterleave and remap input samples */
+ /* copy and remap input samples */
for (ch = 0; ch < s->channels; ch++) {
- const SampleType *sptr;
- int sinc;
-
/* copy last 256 samples of previous frame to the start of the current frame */
memcpy(&s->planar_samples[ch][0], &s->planar_samples[ch][AC3_BLOCK_SIZE * s->num_blocks],
AC3_BLOCK_SIZE * sizeof(s->planar_samples[0][0]));
- /* deinterleave */
- sinc = s->channels;
- sptr = samples + s->channel_map[ch];
- for (i = AC3_BLOCK_SIZE; i < AC3_BLOCK_SIZE * (s->num_blocks + 1); i++) {
- s->planar_samples[ch][i] = *sptr;
- sptr += sinc;
- }
+ /* copy new samples for current frame */
+ memcpy(&s->planar_samples[ch][AC3_BLOCK_SIZE],
+ samples[s->channel_map[ch]],
+ AC3_BLOCK_SIZE * s->num_blocks * sizeof(s->planar_samples[0][0]));
}
}
@@ -395,7 +388,6 @@ int AC3_NAME(encode_frame)(AVCodecContext *avctx, AVPacket *avpkt,
const AVFrame *frame, int *got_packet_ptr)
{
AC3EncodeContext *s = avctx->priv_data;
- const SampleType *samples = (const SampleType *)frame->data[0];
int ret;
if (s->options.allow_per_frame_metadata) {
@@ -407,7 +399,7 @@ int AC3_NAME(encode_frame)(AVCodecContext *avctx, AVPacket *avpkt,
if (s->bit_alloc.sr_code == 1 || s->eac3)
ff_ac3_adjust_frame_size(s);
- deinterleave_input_samples(s, samples);
+ copy_input_samples(s, (SampleType **)frame->extended_data);
apply_mdct(s);
diff --git a/libavcodec/adpcmenc.c b/libavcodec/adpcmenc.c
index a3194abb3c..f016ebd910 100644
--- a/libavcodec/adpcmenc.c
+++ b/libavcodec/adpcmenc.c
@@ -274,12 +274,11 @@ static inline uint8_t adpcm_yamaha_compress_sample(ADPCMChannelStatus *c,
static void adpcm_compress_trellis(AVCodecContext *avctx,
const int16_t *samples, uint8_t *dst,
- ADPCMChannelStatus *c, int n)
+ ADPCMChannelStatus *c, int n, int stride)
{
//FIXME 6% faster if frontier is a compile-time constant
ADPCMEncodeContext *s = avctx->priv_data;
const int frontier = 1 << avctx->trellis;
- const int stride = avctx->channels;
const int version = avctx->codec->id;
TrellisPath *paths = s->paths, *p;
TrellisNode *node_buf = s->node_buf;
@@ -481,13 +480,15 @@ static void adpcm_compress_trellis(AVCodecContext *avctx,
static int adpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
const AVFrame *frame, int *got_packet_ptr)
{
- int n, i, st, pkt_size, ret;
+ int n, i, ch, st, pkt_size, ret;
const int16_t *samples;
+ int16_t **samples_p;
uint8_t *dst;
ADPCMEncodeContext *c = avctx->priv_data;
uint8_t *buf;
samples = (const int16_t *)frame->data[0];
+ samples_p = (int16_t **)frame->extended_data;
st = avctx->channels == 2;
if (avctx->codec_id == AV_CODEC_ID_ADPCM_SWF)
@@ -500,91 +501,71 @@ static int adpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
switch(avctx->codec->id) {
case AV_CODEC_ID_ADPCM_IMA_WAV:
- n = frame->nb_samples / 8;
- c->status[0].prev_sample = samples[0];
- /* c->status[0].step_index = 0;
- XXX: not sure how to init the state machine */
- bytestream_put_le16(&dst, c->status[0].prev_sample);
- *dst++ = c->status[0].step_index;
- *dst++ = 0; /* unknown */
- samples++;
- if (avctx->channels == 2) {
- c->status[1].prev_sample = samples[0];
- /* c->status[1].step_index = 0; */
- bytestream_put_le16(&dst, c->status[1].prev_sample);
- *dst++ = c->status[1].step_index;
- *dst++ = 0;
- samples++;
+ {
+ int blocks, j;
+
+ blocks = (frame->nb_samples - 1) / 8;
+
+ for (ch = 0; ch < avctx->channels; ch++) {
+ ADPCMChannelStatus *status = &c->status[ch];
+ status->prev_sample = samples_p[ch][0];
+ /* status->step_index = 0;
+ XXX: not sure how to init the state machine */
+ bytestream_put_le16(&dst, status->prev_sample);
+ *dst++ = status->step_index;
+ *dst++ = 0; /* unknown */
}
- /* stereo: 4 bytes (8 samples) for left,
- 4 bytes for right, 4 bytes left, ... */
+ /* stereo: 4 bytes (8 samples) for left, 4 bytes for right */
if (avctx->trellis > 0) {
- FF_ALLOC_OR_GOTO(avctx, buf, 2 * n * 8, error);
- adpcm_compress_trellis(avctx, samples, buf, &c->status[0], n * 8);
- if (avctx->channels == 2)
- adpcm_compress_trellis(avctx, samples + 1, buf + n * 8,
- &c->status[1], n * 8);
- for (i = 0; i < n; i++) {
- *dst++ = buf[8 * i + 0] | (buf[8 * i + 1] << 4);
- *dst++ = buf[8 * i + 2] | (buf[8 * i + 3] << 4);
- *dst++ = buf[8 * i + 4] | (buf[8 * i + 5] << 4);
- *dst++ = buf[8 * i + 6] | (buf[8 * i + 7] << 4);
- if (avctx->channels == 2) {
- uint8_t *buf1 = buf + n * 8;
- *dst++ = buf1[8 * i + 0] | (buf1[8 * i + 1] << 4);
- *dst++ = buf1[8 * i + 2] | (buf1[8 * i + 3] << 4);
- *dst++ = buf1[8 * i + 4] | (buf1[8 * i + 5] << 4);
- *dst++ = buf1[8 * i + 6] | (buf1[8 * i + 7] << 4);
+ FF_ALLOC_OR_GOTO(avctx, buf, avctx->channels * blocks * 8, error);
+ for (ch = 0; ch < avctx->channels; ch++) {
+ adpcm_compress_trellis(avctx, &samples_p[ch][1],
+ buf + ch * blocks * 8, &c->status[ch],
+ blocks * 8, 1);
+ }
+ for (i = 0; i < blocks; i++) {
+ for (ch = 0; ch < avctx->channels; ch++) {
+ uint8_t *buf1 = buf + ch * blocks * 8 + i * 8;
+ for (j = 0; j < 8; j += 2)
+ *dst++ = buf1[j] | (buf1[j + 1] << 4);
}
}
av_free(buf);
} else {
- for (; n > 0; n--) {
- *dst = adpcm_ima_compress_sample(&c->status[0], samples[0]);
- *dst++ |= adpcm_ima_compress_sample(&c->status[0], samples[avctx->channels ]) << 4;
- *dst = adpcm_ima_compress_sample(&c->status[0], samples[avctx->channels * 2]);
- *dst++ |= adpcm_ima_compress_sample(&c->status[0], samples[avctx->channels * 3]) << 4;
- *dst = adpcm_ima_compress_sample(&c->status[0], samples[avctx->channels * 4]);
- *dst++ |= adpcm_ima_compress_sample(&c->status[0], samples[avctx->channels * 5]) << 4;
- *dst = adpcm_ima_compress_sample(&c->status[0], samples[avctx->channels * 6]);
- *dst++ |= adpcm_ima_compress_sample(&c->status[0], samples[avctx->channels * 7]) << 4;
- /* right channel */
- if (avctx->channels == 2) {
- *dst = adpcm_ima_compress_sample(&c->status[1], samples[1 ]);
- *dst++ |= adpcm_ima_compress_sample(&c->status[1], samples[3 ]) << 4;
- *dst = adpcm_ima_compress_sample(&c->status[1], samples[5 ]);
- *dst++ |= adpcm_ima_compress_sample(&c->status[1], samples[7 ]) << 4;
- *dst = adpcm_ima_compress_sample(&c->status[1], samples[9 ]);
- *dst++ |= adpcm_ima_compress_sample(&c->status[1], samples[11]) << 4;
- *dst = adpcm_ima_compress_sample(&c->status[1], samples[13]);
- *dst++ |= adpcm_ima_compress_sample(&c->status[1], samples[15]) << 4;
+ for (i = 0; i < blocks; i++) {
+ for (ch = 0; ch < avctx->channels; ch++) {
+ ADPCMChannelStatus *status = &c->status[ch];
+ const int16_t *smp = &samples_p[ch][1 + i * 8];
+ for (j = 0; j < 8; j += 2) {
+ *dst++ = adpcm_ima_compress_sample(status, smp[j ]) |
+ (adpcm_ima_compress_sample(status, smp[j + 1]) << 4);
+ }
}
- samples += 8 * avctx->channels;
}
}
break;
+ }
case AV_CODEC_ID_ADPCM_IMA_QT:
{
- int ch, i;
PutBitContext pb;
init_put_bits(&pb, dst, pkt_size * 8);
for (ch = 0; ch < avctx->channels; ch++) {
- put_bits(&pb, 9, (c->status[ch].prev_sample & 0xFFFF) >> 7);
- put_bits(&pb, 7, c->status[ch].step_index);
+ ADPCMChannelStatus *status = &c->status[ch];
+ put_bits(&pb, 9, (status->prev_sample & 0xFFFF) >> 7);
+ put_bits(&pb, 7, status->step_index);
if (avctx->trellis > 0) {
uint8_t buf[64];
- adpcm_compress_trellis(avctx, samples+ch, buf, &c->status[ch], 64);
+ adpcm_compress_trellis(avctx, &samples_p[ch][1], buf, status,
+ 64, 1);
for (i = 0; i < 64; i++)
put_bits(&pb, 4, buf[i ^ 1]);
} else {
for (i = 0; i < 64; i += 2) {
int t1, t2;
- t1 = adpcm_ima_qt_compress_sample(&c->status[ch],
- samples[avctx->channels * (i + 0) + ch]);
- t2 = adpcm_ima_qt_compress_sample(&c->status[ch],
- samples[avctx->channels * (i + 1) + ch]);
+ t1 = adpcm_ima_qt_compress_sample(status, samples_p[ch][i ]);
+ t2 = adpcm_ima_qt_compress_sample(status, samples_p[ch][i + 1]);
put_bits(&pb, 4, t2);
put_bits(&pb, 4, t1);
}
@@ -596,7 +577,6 @@ static int adpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
}
case AV_CODEC_ID_ADPCM_SWF:
{
- int i;
PutBitContext pb;
init_put_bits(&pb, dst, pkt_size * 8);
@@ -617,10 +597,11 @@ static int adpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
if (avctx->trellis > 0) {
FF_ALLOC_OR_GOTO(avctx, buf, 2 * n, error);
adpcm_compress_trellis(avctx, samples + avctx->channels, buf,
- &c->status[0], n);
+ &c->status[0], n, avctx->channels);
if (avctx->channels == 2)
adpcm_compress_trellis(avctx, samples + avctx->channels + 1,
- buf + n, &c->status[1], n);
+ buf + n, &c->status[1], n,
+ avctx->channels);
for (i = 0; i < n; i++) {
put_bits(&pb, 4, buf[i]);
if (avctx->channels == 2)
@@ -661,15 +642,18 @@ static int adpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
bytestream_put_le16(&dst, c->status[i].sample2);
if (avctx->trellis > 0) {
- int n = avctx->block_align - 7 * avctx->channels;
+ n = avctx->block_align - 7 * avctx->channels;
FF_ALLOC_OR_GOTO(avctx, buf, 2 * n, error);
if (avctx->channels == 1) {
- adpcm_compress_trellis(avctx, samples, buf, &c->status[0], n);
+ adpcm_compress_trellis(avctx, samples, buf, &c->status[0], n,
+ avctx->channels);
for (i = 0; i < n; i += 2)
*dst++ = (buf[i] << 4) | buf[i + 1];
} else {
- adpcm_compress_trellis(avctx, samples, buf, &c->status[0], n);
- adpcm_compress_trellis(avctx, samples + 1, buf + n, &c->status[1], n);
+ adpcm_compress_trellis(avctx, samples, buf,
+ &c->status[0], n, avctx->channels);
+ adpcm_compress_trellis(avctx, samples + 1, buf + n,
+ &c->status[1], n, avctx->channels);
for (i = 0; i < n; i++)
*dst++ = (buf[i] << 4) | buf[n + i];
}
@@ -689,12 +673,15 @@ static int adpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
FF_ALLOC_OR_GOTO(avctx, buf, 2 * n * 2, error);
n *= 2;
if (avctx->channels == 1) {
- adpcm_compress_trellis(avctx, samples, buf, &c->status[0], n);
+ adpcm_compress_trellis(avctx, samples, buf, &c->status[0], n,
+ avctx->channels);
for (i = 0; i < n; i += 2)
*dst++ = buf[i] | (buf[i + 1] << 4);
} else {
- adpcm_compress_trellis(avctx, samples, buf, &c->status[0], n);
- adpcm_compress_trellis(avctx, samples + 1, buf + n, &c->status[1], n);
+ adpcm_compress_trellis(avctx, samples, buf,
+ &c->status[0], n, avctx->channels);
+ adpcm_compress_trellis(avctx, samples + 1, buf + n,
+ &c->status[1], n, avctx->channels);
for (i = 0; i < n; i++)
*dst++ = buf[i] | (buf[n + i] << 4);
}
@@ -722,7 +709,11 @@ static const enum AVSampleFormat sample_fmts[] = {
AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE
};
-#define ADPCM_ENCODER(id_, name_, long_name_) \
+static const enum AVSampleFormat sample_fmts_p[] = {
+ AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_NONE
+};
+
+#define ADPCM_ENCODER(id_, name_, sample_fmts_, long_name_) \
AVCodec ff_ ## name_ ## _encoder = { \
.name = #name_, \
.type = AVMEDIA_TYPE_AUDIO, \
@@ -731,12 +722,12 @@ AVCodec ff_ ## name_ ## _encoder = { \
.init = adpcm_encode_init, \
.encode2 = adpcm_encode_frame, \
.close = adpcm_encode_close, \
- .sample_fmts = sample_fmts, \
+ .sample_fmts = sample_fmts_, \
.long_name = NULL_IF_CONFIG_SMALL(long_name_), \
}
-ADPCM_ENCODER(AV_CODEC_ID_ADPCM_IMA_QT, adpcm_ima_qt, "ADPCM IMA QuickTime");
-ADPCM_ENCODER(AV_CODEC_ID_ADPCM_IMA_WAV, adpcm_ima_wav, "ADPCM IMA WAV");
-ADPCM_ENCODER(AV_CODEC_ID_ADPCM_MS, adpcm_ms, "ADPCM Microsoft");
-ADPCM_ENCODER(AV_CODEC_ID_ADPCM_SWF, adpcm_swf, "ADPCM Shockwave Flash");
-ADPCM_ENCODER(AV_CODEC_ID_ADPCM_YAMAHA, adpcm_yamaha, "ADPCM Yamaha");
+ADPCM_ENCODER(AV_CODEC_ID_ADPCM_IMA_QT, adpcm_ima_qt, sample_fmts_p, "ADPCM IMA QuickTime");
+ADPCM_ENCODER(AV_CODEC_ID_ADPCM_IMA_WAV, adpcm_ima_wav, sample_fmts_p, "ADPCM IMA WAV");
+ADPCM_ENCODER(AV_CODEC_ID_ADPCM_MS, adpcm_ms, sample_fmts, "ADPCM Microsoft");
+ADPCM_ENCODER(AV_CODEC_ID_ADPCM_SWF, adpcm_swf, sample_fmts, "ADPCM Shockwave Flash");
+ADPCM_ENCODER(AV_CODEC_ID_ADPCM_YAMAHA, adpcm_yamaha, sample_fmts, "ADPCM Yamaha");
diff --git a/libavcodec/eac3enc.c b/libavcodec/eac3enc.c
index c5ac6d1516..bb9ef4fd3e 100644
--- a/libavcodec/eac3enc.c
+++ b/libavcodec/eac3enc.c
@@ -258,7 +258,7 @@ AVCodec ff_eac3_encoder = {
.init = ff_ac3_encode_init,
.encode2 = ff_ac3_float_encode_frame,
.close = ff_ac3_encode_close,
- .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLT,
+ .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLTP,
AV_SAMPLE_FMT_NONE },
.long_name = NULL_IF_CONFIG_SMALL("ATSC A/52 E-AC-3"),
.priv_class = &eac3enc_class,
diff --git a/libavcodec/libmp3lame.c b/libavcodec/libmp3lame.c
index 427cacdf8e..ce17e06ef8 100644
--- a/libavcodec/libmp3lame.c
+++ b/libavcodec/libmp3lame.c
@@ -33,6 +33,7 @@
#include "libavutil/opt.h"
#include "avcodec.h"
#include "audio_frame_queue.h"
+#include "dsputil.h"
#include "internal.h"
#include "mpegaudio.h"
#include "mpegaudiodecheader.h"
@@ -46,8 +47,9 @@ typedef struct LAMEContext {
uint8_t buffer[BUFFER_SIZE];
int buffer_index;
int reservoir;
- void *planar_samples[2];
+ float *samples_flt[2];
AudioFrameQueue afq;
+ DSPContext dsp;
} LAMEContext;
@@ -58,8 +60,8 @@ static av_cold int mp3lame_encode_close(AVCodecContext *avctx)
#if FF_API_OLD_ENCODE_AUDIO
av_freep(&avctx->coded_frame);
#endif
- av_freep(&s->planar_samples[0]);
- av_freep(&s->planar_samples[1]);
+ av_freep(&s->samples_flt[0]);
+ av_freep(&s->samples_flt[1]);
ff_af_queue_close(&s->afq);
@@ -127,93 +129,63 @@ static av_cold int mp3lame_encode_init(AVCodecContext *avctx)
}
#endif
- /* sample format */
- if (avctx->sample_fmt == AV_SAMPLE_FMT_S32 ||
- avctx->sample_fmt == AV_SAMPLE_FMT_FLT) {
+ /* allocate float sample buffers */
+ if (avctx->sample_fmt == AV_SAMPLE_FMT_FLTP) {
int ch;
for (ch = 0; ch < avctx->channels; ch++) {
- s->planar_samples[ch] = av_malloc(avctx->frame_size *
- av_get_bytes_per_sample(avctx->sample_fmt));
- if (!s->planar_samples[ch]) {
+ s->samples_flt[ch] = av_malloc(avctx->frame_size *
+ sizeof(*s->samples_flt[ch]));
+ if (!s->samples_flt[ch]) {
ret = AVERROR(ENOMEM);
goto error;
}
}
}
+ ff_dsputil_init(&s->dsp, avctx);
+
return 0;
error:
mp3lame_encode_close(avctx);
return ret;
}
-#define DEINTERLEAVE(type, scale) do { \
- int ch, i; \
- for (ch = 0; ch < s->avctx->channels; ch++) { \
- const type *input = samples; \
- type *output = s->planar_samples[ch]; \
- input += ch; \
- for (i = 0; i < nb_samples; i++) { \
- output[i] = *input * scale; \
- input += s->avctx->channels; \
- } \
- } \
+#define ENCODE_BUFFER(func, buf_type, buf_name) do { \
+ lame_result = func(s->gfp, \
+ (const buf_type *)buf_name[0], \
+ (const buf_type *)buf_name[1], frame->nb_samples, \
+ s->buffer + s->buffer_index, \
+ BUFFER_SIZE - s->buffer_index); \
} while (0)
-static int encode_frame_int16(LAMEContext *s, void *samples, int nb_samples)
-{
- if (s->avctx->channels > 1) {
- return lame_encode_buffer_interleaved(s->gfp, samples,
- nb_samples,
- s->buffer + s->buffer_index,
- BUFFER_SIZE - s->buffer_index);
- } else {
- return lame_encode_buffer(s->gfp, samples, NULL, nb_samples,
- s->buffer + s->buffer_index,
- BUFFER_SIZE - s->buffer_index);
- }
-}
-
-static int encode_frame_int32(LAMEContext *s, void *samples, int nb_samples)
-{
- DEINTERLEAVE(int32_t, 1);
-
- return lame_encode_buffer_int(s->gfp,
- s->planar_samples[0], s->planar_samples[1],
- nb_samples,
- s->buffer + s->buffer_index,
- BUFFER_SIZE - s->buffer_index);
-}
-
-static int encode_frame_float(LAMEContext *s, void *samples, int nb_samples)
-{
- DEINTERLEAVE(float, 32768.0f);
-
- return lame_encode_buffer_float(s->gfp,
- s->planar_samples[0], s->planar_samples[1],
- nb_samples,
- s->buffer + s->buffer_index,
- BUFFER_SIZE - s->buffer_index);
-}
-
static int mp3lame_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
const AVFrame *frame, int *got_packet_ptr)
{
LAMEContext *s = avctx->priv_data;
MPADecodeHeader hdr;
- int len, ret;
+ int len, ret, ch;
int lame_result;
if (frame) {
switch (avctx->sample_fmt) {
- case AV_SAMPLE_FMT_S16:
- lame_result = encode_frame_int16(s, frame->data[0], frame->nb_samples);
+ case AV_SAMPLE_FMT_S16P:
+ ENCODE_BUFFER(lame_encode_buffer, int16_t, frame->data);
break;
- case AV_SAMPLE_FMT_S32:
- lame_result = encode_frame_int32(s, frame->data[0], frame->nb_samples);
+ case AV_SAMPLE_FMT_S32P:
+ ENCODE_BUFFER(lame_encode_buffer_int, int32_t, frame->data);
break;
- case AV_SAMPLE_FMT_FLT:
- lame_result = encode_frame_float(s, frame->data[0], frame->nb_samples);
+ case AV_SAMPLE_FMT_FLTP:
+ if (frame->linesize[0] < 4 * FFALIGN(frame->nb_samples, 8)) {
+ av_log(avctx, AV_LOG_ERROR, "inadequate AVFrame plane padding\n");
+ return AVERROR(EINVAL);
+ }
+ for (ch = 0; ch < avctx->channels; ch++) {
+ s->dsp.vector_fmul_scalar(s->samples_flt[ch],
+ (const float *)frame->data[ch],
+ 32768.0f,
+ FFALIGN(frame->nb_samples, 8));
+ }
+ ENCODE_BUFFER(lame_encode_buffer_float, float, s->samples_flt);
break;
default:
return AVERROR_BUG;
@@ -299,9 +271,9 @@ AVCodec ff_libmp3lame_encoder = {
.encode2 = mp3lame_encode_frame,
.close = mp3lame_encode_close,
.capabilities = CODEC_CAP_DELAY | CODEC_CAP_SMALL_LAST_FRAME,
- .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S32,
- AV_SAMPLE_FMT_FLT,
- AV_SAMPLE_FMT_S16,
+ .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S32P,
+ AV_SAMPLE_FMT_FLTP,
+ AV_SAMPLE_FMT_S16P,
AV_SAMPLE_FMT_NONE },
.supported_samplerates = libmp3lame_sample_rates,
.channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_MONO,
diff --git a/libavcodec/libvorbisenc.c b/libavcodec/libvorbisenc.c
index b042e0cb4f..6064dd5649 100644
--- a/libavcodec/libvorbisenc.c
+++ b/libavcodec/libvorbisenc.c
@@ -290,18 +290,16 @@ static int oggvorbis_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
/* send samples to libvorbis */
if (frame) {
- const float *audio = (const float *)frame->data[0];
const int samples = frame->nb_samples;
float **buffer;
int c, channels = s->vi.channels;
buffer = vorbis_analysis_buffer(&s->vd, samples);
for (c = 0; c < channels; c++) {
- int i;
int co = (channels > 8) ? c :
ff_vorbis_encoding_channel_layout_offsets[channels - 1][c];
- for (i = 0; i < samples; i++)
- buffer[c][i] = audio[i * channels + co];
+ memcpy(buffer[c], frame->extended_data[co],
+ samples * sizeof(*buffer[c]));
}
if ((ret = vorbis_analysis_wrote(&s->vd, samples)) < 0) {
av_log(avctx, AV_LOG_ERROR, "error in vorbis_analysis_wrote()\n");
@@ -383,7 +381,7 @@ AVCodec ff_libvorbis_encoder = {
.encode2 = oggvorbis_encode_frame,
.close = oggvorbis_encode_close,
.capabilities = CODEC_CAP_DELAY,
- .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLT,
+ .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP,
AV_SAMPLE_FMT_NONE },
.long_name = NULL_IF_CONFIG_SMALL("libvorbis"),
.priv_class = &class,
diff --git a/libavcodec/vorbisenc.c b/libavcodec/vorbisenc.c
index b88791f274..74d6331ee3 100644
--- a/libavcodec/vorbisenc.c
+++ b/libavcodec/vorbisenc.c
@@ -963,10 +963,10 @@ static int residue_encode(vorbis_enc_context *venc, vorbis_enc_residue *rc,
return 0;
}
-static int apply_window_and_mdct(vorbis_enc_context *venc, const signed short *audio,
- int samples)
+static int apply_window_and_mdct(vorbis_enc_context *venc,
+ float **audio, int samples)
{
- int i, j, channel;
+ int i, channel;
const float * win = venc->win[0];
int window_len = 1 << (venc->log2_blocksize[0] - 1);
float n = (float)(1 << venc->log2_blocksize[0]) / 4.;
@@ -988,9 +988,8 @@ static int apply_window_and_mdct(vorbis_enc_context *venc, const signed short *a
if (samples) {
for (channel = 0; channel < venc->channels; channel++) {
float * offset = venc->samples + channel*window_len*2 + window_len;
- j = channel;
- for (i = 0; i < samples; i++, j += venc->channels)
- offset[i] = audio[j] / 32768. / n * win[window_len - i - 1];
+ for (i = 0; i < samples; i++)
+ offset[i] = audio[channel][i] / n * win[window_len - i - 1];
}
} else {
for (channel = 0; channel < venc->channels; channel++)
@@ -1005,9 +1004,8 @@ static int apply_window_and_mdct(vorbis_enc_context *venc, const signed short *a
if (samples) {
for (channel = 0; channel < venc->channels; channel++) {
float *offset = venc->saved + channel * window_len;
- j = channel;
- for (i = 0; i < samples; i++, j += venc->channels)
- offset[i] = audio[j] / 32768. / n * win[i];
+ for (i = 0; i < samples; i++)
+ offset[i] = audio[channel][i] / n * win[i];
}
venc->have_saved = 1;
} else {
@@ -1020,7 +1018,7 @@ static int vorbis_encode_frame(AVCodecContext *avccontext, AVPacket *avpkt,
const AVFrame *frame, int *got_packet_ptr)
{
vorbis_enc_context *venc = avccontext->priv_data;
- const int16_t *audio = frame ? (const int16_t *)frame->data[0] : NULL;
+ float **audio = frame ? (float **)frame->extended_data : NULL;
int samples = frame ? frame->nb_samples : 0;
vorbis_enc_mode *mode;
vorbis_enc_mapping *mapping;
@@ -1213,7 +1211,7 @@ AVCodec ff_vorbis_encoder = {
.encode2 = vorbis_encode_frame,
.close = vorbis_encode_close,
.capabilities = CODEC_CAP_DELAY | CODEC_CAP_EXPERIMENTAL,
- .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16,
+ .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLTP,
AV_SAMPLE_FMT_NONE },
.long_name = NULL_IF_CONFIG_SMALL("Vorbis"),
};
diff --git a/libavcodec/wma.c b/libavcodec/wma.c
index d5e66e25b3..c65281711a 100644
--- a/libavcodec/wma.c
+++ b/libavcodec/wma.c
@@ -89,6 +89,7 @@ int ff_wma_init(AVCodecContext *avctx, int flags2)
ff_dsputil_init(&s->dsp, avctx);
ff_fmt_convert_init(&s->fmt_conv, avctx);
+ avpriv_float_dsp_init(&s->fdsp, avctx->flags & CODEC_FLAG_BITEXACT);
if (avctx->codec->id == AV_CODEC_ID_WMAV1) {
s->version = 1;
diff --git a/libavcodec/wma.h b/libavcodec/wma.h
index 73734ebc7c..1e7f0e5aba 100644
--- a/libavcodec/wma.h
+++ b/libavcodec/wma.h
@@ -22,6 +22,7 @@
#ifndef AVCODEC_WMA_H
#define AVCODEC_WMA_H
+#include "libavutil/float_dsp.h"
#include "get_bits.h"
#include "put_bits.h"
#include "dsputil.h"
@@ -137,6 +138,7 @@ typedef struct WMACodecContext {
float lsp_pow_m_table2[(1 << LSP_POW_BITS)];
DSPContext dsp;
FmtConvertContext fmt_conv;
+ AVFloatDSPContext fdsp;
#ifdef TRACE
int frame_count;
diff --git a/libavcodec/wmaenc.c b/libavcodec/wmaenc.c
index 835bc39ce8..63f815c78a 100644
--- a/libavcodec/wmaenc.c
+++ b/libavcodec/wmaenc.c
@@ -93,23 +93,24 @@ static int encode_init(AVCodecContext * avctx){
}
-static void apply_window_and_mdct(AVCodecContext * avctx, const signed short * audio, int len) {
+static void apply_window_and_mdct(AVCodecContext * avctx, const AVFrame *frame)
+{
WMACodecContext *s = avctx->priv_data;
+ float **audio = (float **)frame->extended_data;
+ int len = frame->nb_samples;
int window_index= s->frame_len_bits - s->block_len_bits;
FFTContext *mdct = &s->mdct_ctx[window_index];
- int i, j, channel;
+ int ch;
const float * win = s->windows[window_index];
int window_len = 1 << s->block_len_bits;
- float n = window_len/2;
-
- for (channel = 0; channel < avctx->channels; channel++) {
- memcpy(s->output, s->frame_out[channel], sizeof(float)*window_len);
- j = channel;
- for (i = 0; i < len; i++, j += avctx->channels){
- s->output[i+window_len] = audio[j] / n * win[window_len - i - 1];
- s->frame_out[channel][i] = audio[j] / n * win[i];
- }
- mdct->mdct_calc(mdct, s->coefs[channel], s->output);
+ float n = 2.0 * 32768.0 / window_len;
+
+ for (ch = 0; ch < avctx->channels; ch++) {
+ memcpy(s->output, s->frame_out[ch], window_len * sizeof(*s->output));
+ s->dsp.vector_fmul_scalar(s->frame_out[ch], audio[ch], n, len);
+ s->dsp.vector_fmul_reverse(&s->output[window_len], s->frame_out[ch], win, len);
+ s->fdsp.vector_fmul(s->frame_out[ch], s->frame_out[ch], win, len);
+ mdct->mdct_calc(mdct, s->coefs[ch], s->output);
}
}
@@ -345,13 +346,12 @@ static int encode_superframe(AVCodecContext *avctx, AVPacket *avpkt,
const AVFrame *frame, int *got_packet_ptr)
{
WMACodecContext *s = avctx->priv_data;
- const int16_t *samples = (const int16_t *)frame->data[0];
int i, total_gain, ret, error;
s->block_len_bits= s->frame_len_bits; //required by non variable block len
s->block_len = 1 << s->block_len_bits;
- apply_window_and_mdct(avctx, samples, frame->nb_samples);
+ apply_window_and_mdct(avctx, frame);
if (s->ms_stereo) {
float a, b;
@@ -404,7 +404,7 @@ AVCodec ff_wmav1_encoder = {
.init = encode_init,
.encode2 = encode_superframe,
.close = ff_wma_end,
- .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16,
+ .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLTP,
AV_SAMPLE_FMT_NONE },
.long_name = NULL_IF_CONFIG_SMALL("Windows Media Audio 1"),
};
@@ -418,7 +418,7 @@ AVCodec ff_wmav2_encoder = {
.init = encode_init,
.encode2 = encode_superframe,
.close = ff_wma_end,
- .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16,
+ .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLTP,
AV_SAMPLE_FMT_NONE },
.long_name = NULL_IF_CONFIG_SMALL("Windows Media Audio 2"),
};
diff --git a/libavformat/ffmdec.c b/libavformat/ffmdec.c
index c6d9fab9cf..f151f9c1f4 100644
--- a/libavformat/ffmdec.c
+++ b/libavformat/ffmdec.c
@@ -360,7 +360,6 @@ static int ffm_read_header(AVFormatContext *s)
codec->sample_rate = avio_rb32(pb);
codec->channels = avio_rl16(pb);
codec->frame_size = avio_rl16(pb);
- codec->sample_fmt = (int16_t) avio_rl16(pb);
break;
default:
goto fail;
diff --git a/libavformat/ffmenc.c b/libavformat/ffmenc.c
index 1aa4775a03..fb397aff37 100644
--- a/libavformat/ffmenc.c
+++ b/libavformat/ffmenc.c
@@ -169,7 +169,6 @@ static int ffm_write_header(AVFormatContext *s)
avio_wb32(pb, codec->sample_rate);
avio_wl16(pb, codec->channels);
avio_wl16(pb, codec->frame_size);
- avio_wl16(pb, codec->sample_fmt);
break;
default:
return -1;
diff --git a/libavformat/smoothstreamingenc.c b/libavformat/smoothstreamingenc.c
index 2dfc26f8d8..df7522ee1d 100644
--- a/libavformat/smoothstreamingenc.c
+++ b/libavformat/smoothstreamingenc.c
@@ -108,7 +108,8 @@ static int64_t ism_seek(void *opaque, int64_t offset, int whence)
os->tail_out = NULL;
}
if (offset >= os->cur_start_pos) {
- ffurl_seek(os->out, offset - os->cur_start_pos, SEEK_SET);
+ if (os->out)
+ ffurl_seek(os->out, offset - os->cur_start_pos, SEEK_SET);
os->cur_pos = offset;
return offset;
}
@@ -185,18 +186,108 @@ static void ism_free(AVFormatContext *s)
av_freep(&c->streams);
}
+static void output_chunk_list(OutputStream *os, AVIOContext *out, int final, int skip, int window_size)
+{
+ int removed = 0, i, start = 0;
+ if (os->nb_fragments <= 0)
+ return;
+ if (os->fragments[0]->n > 0)
+ removed = 1;
+ if (final)
+ skip = 0;
+ if (window_size)
+ start = FFMAX(os->nb_fragments - skip - window_size, 0);
+ for (i = start; i < os->nb_fragments - skip; i++) {
+ Fragment *frag = os->fragments[i];
+ if (!final || removed)
+ avio_printf(out, "<c t=\"%"PRIu64"\" d=\"%"PRIu64"\" />\n", frag->start_time, frag->duration);
+ else
+ avio_printf(out, "<c n=\"%d\" d=\"%"PRIu64"\" />\n", frag->n, frag->duration);
+ }
+}
+
+static int write_manifest(AVFormatContext *s, int final)
+{
+ SmoothStreamingContext *c = s->priv_data;
+ AVIOContext *out;
+ char filename[1024];
+ int ret, i, video_chunks = 0, audio_chunks = 0, video_streams = 0, audio_streams = 0;
+ int64_t duration = 0;
+
+ snprintf(filename, sizeof(filename), "%s/Manifest", s->filename);
+ ret = avio_open2(&out, filename, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL);
+ if (ret < 0) {
+ av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", filename);
+ return ret;
+ }
+ avio_printf(out, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
+ for (i = 0; i < s->nb_streams; i++) {
+ OutputStream *os = &c->streams[i];
+ if (os->nb_fragments > 0) {
+ Fragment *last = os->fragments[os->nb_fragments - 1];
+ duration = last->start_time + last->duration;
+ }
+ if (s->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
+ video_chunks = os->nb_fragments;
+ video_streams++;
+ } else {
+ audio_chunks = os->nb_fragments;
+ audio_streams++;
+ }
+ }
+ if (!final) {
+ duration = 0;
+ video_chunks = audio_chunks = 0;
+ }
+ if (c->window_size) {
+ video_chunks = FFMIN(video_chunks, c->window_size);
+ audio_chunks = FFMIN(audio_chunks, c->window_size);
+ }
+ avio_printf(out, "<SmoothStreamingMedia MajorVersion=\"2\" MinorVersion=\"0\" Duration=\"%"PRIu64"\"", duration);
+ if (!final)
+ avio_printf(out, " IsLive=\"true\" LookAheadFragmentCount=\"%d\" DVRWindowLength=\"0\"", c->lookahead_count);
+ avio_printf(out, ">\n");
+ if (c->has_video) {
+ int last = -1, index = 0;
+ avio_printf(out, "<StreamIndex Type=\"video\" QualityLevels=\"%d\" Chunks=\"%d\" Url=\"QualityLevels({bitrate})/Fragments(video={start time})\">\n", video_streams, video_chunks);
+ for (i = 0; i < s->nb_streams; i++) {
+ OutputStream *os = &c->streams[i];
+ if (s->streams[i]->codec->codec_type != AVMEDIA_TYPE_VIDEO)
+ continue;
+ last = i;
+ avio_printf(out, "<QualityLevel Index=\"%d\" Bitrate=\"%d\" FourCC=\"%s\" MaxWidth=\"%d\" MaxHeight=\"%d\" CodecPrivateData=\"%s\" />\n", index, s->streams[i]->codec->bit_rate, os->fourcc, s->streams[i]->codec->width, s->streams[i]->codec->height, os->private_str);
+ index++;
+ }
+ output_chunk_list(&c->streams[last], out, final, c->lookahead_count, c->window_size);
+ avio_printf(out, "</StreamIndex>\n");
+ }
+ if (c->has_audio) {
+ int last = -1, index = 0;
+ avio_printf(out, "<StreamIndex Type=\"audio\" QualityLevels=\"%d\" Chunks=\"%d\" Url=\"QualityLevels({bitrate})/Fragments(audio={start time})\">\n", audio_streams, audio_chunks);
+ for (i = 0; i < s->nb_streams; i++) {
+ OutputStream *os = &c->streams[i];
+ if (s->streams[i]->codec->codec_type != AVMEDIA_TYPE_AUDIO)
+ continue;
+ last = i;
+ avio_printf(out, "<QualityLevel Index=\"%d\" Bitrate=\"%d\" FourCC=\"%s\" SamplingRate=\"%d\" Channels=\"%d\" BitsPerSample=\"16\" PacketSize=\"%d\" AudioTag=\"%d\" CodecPrivateData=\"%s\" />\n", index, s->streams[i]->codec->bit_rate, os->fourcc, s->streams[i]->codec->sample_rate, s->streams[i]->codec->channels, os->packet_size, os->audio_tag, os->private_str);
+ index++;
+ }
+ output_chunk_list(&c->streams[last], out, final, c->lookahead_count, c->window_size);
+ avio_printf(out, "</StreamIndex>\n");
+ }
+ avio_printf(out, "</SmoothStreamingMedia>\n");
+ avio_flush(out);
+ avio_close(out);
+ return 0;
+}
+
static int ism_write_header(AVFormatContext *s)
{
SmoothStreamingContext *c = s->priv_data;
int ret = 0, i;
AVOutputFormat *oformat;
- ret = mkdir(s->filename, 0777);
- if (ret) {
- av_log(s, AV_LOG_ERROR, "mkdir(%s): %s\n", s->filename, strerror(errno));
- return AVERROR(errno);
- }
- ret = 0;
+ mkdir(s->filename, 0777);
oformat = av_guess_format("ismv", NULL, NULL);
if (!oformat) {
@@ -292,6 +383,7 @@ static int ism_write_header(AVFormatContext *s)
av_log(s, AV_LOG_WARNING, "no video stream and no min frag duration set\n");
ret = AVERROR(EINVAL);
}
+ ret = write_manifest(s, 0);
fail:
if (ret)
@@ -400,99 +492,6 @@ static int copy_moof(AVFormatContext *s, const char* infile, const char *outfile
return ret;
}
-static void output_chunk_list(OutputStream *os, AVIOContext *out, int final, int skip, int window_size)
-{
- int removed = 0, i, start = 0;
- if (os->nb_fragments <= 0)
- return;
- if (os->fragments[0]->n > 0)
- removed = 1;
- if (final)
- skip = 0;
- if (window_size)
- start = FFMAX(os->nb_fragments - skip - window_size, 0);
- for (i = start; i < os->nb_fragments - skip; i++) {
- Fragment *frag = os->fragments[i];
- if (!final || removed)
- avio_printf(out, "<c t=\"%"PRIu64"\" d=\"%"PRIu64"\" />\n", frag->start_time, frag->duration);
- else
- avio_printf(out, "<c n=\"%d\" d=\"%"PRIu64"\" />\n", frag->n, frag->duration);
- }
-}
-
-static int write_manifest(AVFormatContext *s, int final)
-{
- SmoothStreamingContext *c = s->priv_data;
- AVIOContext *out;
- char filename[1024];
- int ret, i, video_chunks = 0, audio_chunks = 0, video_streams = 0, audio_streams = 0;
- int64_t duration = 0;
-
- snprintf(filename, sizeof(filename), "%s/Manifest", s->filename);
- ret = avio_open2(&out, filename, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL);
- if (ret < 0)
- return ret;
- avio_printf(out, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
- for (i = 0; i < s->nb_streams; i++) {
- OutputStream *os = &c->streams[i];
- if (os->nb_fragments > 0) {
- Fragment *last = os->fragments[os->nb_fragments - 1];
- duration = last->start_time + last->duration;
- }
- if (s->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
- video_chunks = os->nb_fragments;
- video_streams++;
- } else {
- audio_chunks = os->nb_fragments;
- audio_streams++;
- }
- }
- if (!final) {
- duration = 0;
- video_chunks = audio_chunks = 0;
- }
- if (c->window_size) {
- video_chunks = FFMIN(video_chunks, c->window_size);
- audio_chunks = FFMIN(audio_chunks, c->window_size);
- }
- avio_printf(out, "<SmoothStreamingMedia MajorVersion=\"2\" MinorVersion=\"0\" Duration=\"%"PRIu64"\"", duration);
- if (!final)
- avio_printf(out, " IsLive=\"true\" LookAheadFragmentCount=\"%d\" DVRWindowLength=\"0\"", c->lookahead_count);
- avio_printf(out, ">\n");
- if (c->has_video) {
- int last = -1, index = 0;
- avio_printf(out, "<StreamIndex Type=\"video\" QualityLevels=\"%d\" Chunks=\"%d\" Url=\"QualityLevels({bitrate})/Fragments(video={start time})\">\n", video_streams, video_chunks);
- for (i = 0; i < s->nb_streams; i++) {
- OutputStream *os = &c->streams[i];
- if (s->streams[i]->codec->codec_type != AVMEDIA_TYPE_VIDEO)
- continue;
- last = i;
- avio_printf(out, "<QualityLevel Index=\"%d\" Bitrate=\"%d\" FourCC=\"%s\" MaxWidth=\"%d\" MaxHeight=\"%d\" CodecPrivateData=\"%s\" />\n", index, s->streams[i]->codec->bit_rate, os->fourcc, s->streams[i]->codec->width, s->streams[i]->codec->height, os->private_str);
- index++;
- }
- output_chunk_list(&c->streams[last], out, final, c->lookahead_count, c->window_size);
- avio_printf(out, "</StreamIndex>\n");
- }
- if (c->has_audio) {
- int last = -1, index = 0;
- avio_printf(out, "<StreamIndex Type=\"audio\" QualityLevels=\"%d\" Chunks=\"%d\" Url=\"QualityLevels({bitrate})/Fragments(audio={start time})\">\n", audio_streams, audio_chunks);
- for (i = 0; i < s->nb_streams; i++) {
- OutputStream *os = &c->streams[i];
- if (s->streams[i]->codec->codec_type != AVMEDIA_TYPE_AUDIO)
- continue;
- last = i;
- avio_printf(out, "<QualityLevel Index=\"%d\" Bitrate=\"%d\" FourCC=\"%s\" SamplingRate=\"%d\" Channels=\"%d\" BitsPerSample=\"16\" PacketSize=\"%d\" AudioTag=\"%d\" CodecPrivateData=\"%s\" />\n", index, s->streams[i]->codec->bit_rate, os->fourcc, s->streams[i]->codec->sample_rate, s->streams[i]->codec->channels, os->packet_size, os->audio_tag, os->private_str);
- index++;
- }
- output_chunk_list(&c->streams[last], out, final, c->lookahead_count, c->window_size);
- avio_printf(out, "</StreamIndex>\n");
- }
- avio_printf(out, "</SmoothStreamingMedia>\n");
- avio_flush(out);
- avio_close(out);
- return 0;
-}
-
static int ism_flush(AVFormatContext *s, int final)
{
SmoothStreamingContext *c = s->priv_data;
@@ -550,7 +549,8 @@ static int ism_flush(AVFormatContext *s, int final)
}
}
- write_manifest(s, final);
+ if (ret >= 0)
+ ret = write_manifest(s, final);
return ret;
}
@@ -560,13 +560,15 @@ static int ism_write_packet(AVFormatContext *s, AVPacket *pkt)
AVStream *st = s->streams[pkt->stream_index];
OutputStream *os = &c->streams[pkt->stream_index];
int64_t end_pts = (c->nb_fragments + 1) * c->min_frag_duration;
+ int ret;
if ((!c->has_video || st->codec->codec_type == AVMEDIA_TYPE_VIDEO) &&
av_compare_ts(pkt->pts, st->time_base,
end_pts, AV_TIME_BASE_Q) >= 0 &&
pkt->flags & AV_PKT_FLAG_KEY && os->packets_written) {
- ism_flush(s, 0);
+ if ((ret = ism_flush(s, 0)) < 0)
+ return ret;
c->nb_fragments++;
}
diff --git a/libavutil/parseutils.c b/libavutil/parseutils.c
index 6e50d70657..da7180fcfb 100644
--- a/libavutil/parseutils.c
+++ b/libavutil/parseutils.c
@@ -389,7 +389,7 @@ int av_parse_color(uint8_t *rgba_color, const char *color_string, int slen,
}
if (tail) {
- unsigned long int alpha;
+ double alpha;
const char *alpha_string = tail;
if (!strncmp(alpha_string, "0x", 2)) {
alpha = strtoul(alpha_string, &tail, 16);
@@ -401,7 +401,7 @@ int av_parse_color(uint8_t *rgba_color, const char *color_string, int slen,
alpha = 255 * norm_alpha;
}
- if (tail == alpha_string || *tail || alpha > 255) {
+ if (tail == alpha_string || *tail || alpha > 255 || alpha < 0) {
av_log(log_ctx, AV_LOG_ERROR, "Invalid alpha value specifier '%s' in '%s'\n",
alpha_string, color_string);
return AVERROR(EINVAL);
diff --git a/tests/ref/lavf/ffm b/tests/ref/lavf/ffm
index ce0dcddd36..0494c0ea4a 100644
--- a/tests/ref/lavf/ffm
+++ b/tests/ref/lavf/ffm
@@ -1,3 +1,3 @@
-e6d8254af2b1ad1f58d60da4d80c6e96 *./tests/data/lavf/lavf.ffm
+c76e8f9a9bcd04379dfa3239e272d049 *./tests/data/lavf/lavf.ffm
376832 ./tests/data/lavf/lavf.ffm
./tests/data/lavf/lavf.ffm CRC=0x5b136bb1