aboutsummaryrefslogtreecommitdiffstats
path: root/libavformat
diff options
context:
space:
mode:
authorMichael Niedermayer <michaelni@gmx.at>2011-10-22 01:03:27 +0200
committerMichael Niedermayer <michaelni@gmx.at>2011-10-22 01:16:41 +0200
commitaedc908601de7396751a9a4504e064782d9f6a0b (patch)
tree8f04b899142439893bac426ac83d05c4068b099c /libavformat
parent1a7090bfafe986d4470ba8059c815939171ddb74 (diff)
parentf4b51d061f0f34e36be876b562b8abe47f4b9c1c (diff)
downloadffmpeg-aedc908601de7396751a9a4504e064782d9f6a0b.tar.gz
Merge remote-tracking branch 'qatar/master'
* qatar/master: (35 commits) flvdec: Do not call parse_keyframes_index with a NULL stream libspeexdec: include system headers before local headers libspeexdec: return meaningful error codes libspeexdec: cosmetics: reindent libspeexdec: decode one frame at a time. swscale: fix signed shift overflows in ff_yuv2rgb_c_init_tables() Move timefilter code from lavf to lavd. mov: add support for hdvd and pgapmetadata atoms mov: rename function _stik, some indentation cosmetics mov: rename function _int8 to remove ambiguity, some indentation cosmetics mov: parse the gnre atom mp3on4: check for allocation failures in decode_init_mp3on4() mp3on4: create a separate flush function for MP3onMP4. mp3on4: ensure that the frame channel count does not exceed the codec channel count. mp3on4: set channel layout mp3on4: fix the output channel order mp3on4: allocate temp buffer with av_malloc() instead of on the stack. mp3on4: copy MPADSPContext from first context to all contexts. fmtconvert: port float_to_int16_interleave() 2-channel x86 inline asm to yasm fmtconvert: port int32_to_float_fmul_scalar() x86 inline asm to yasm ... Conflicts: libavcodec/arm/h264dsp_init_arm.c libavcodec/h264.c libavcodec/h264.h libavcodec/h264_cabac.c libavcodec/h264_cavlc.c libavcodec/h264_ps.c libavcodec/h264dsp_template.c libavcodec/h264idct_template.c libavcodec/h264pred.c libavcodec/h264pred_template.c libavcodec/x86/h264dsp_mmx.c libavdevice/Makefile libavdevice/jack_audio.c libavformat/Makefile libavformat/flvdec.c libavformat/flvenc.c libavutil/pixfmt.h libswscale/utils.c Merged-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavformat')
-rw-r--r--libavformat/Makefile5
-rw-r--r--libavformat/flvdec.c5
-rw-r--r--libavformat/flvenc.c34
-rw-r--r--libavformat/mov.c60
-rw-r--r--libavformat/timefilter.c151
-rw-r--r--libavformat/timefilter.h97
6 files changed, 68 insertions, 284 deletions
diff --git a/libavformat/Makefile b/libavformat/Makefile
index ddd1ab7833..15ccb291ed 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -354,11 +354,8 @@ OBJS-$(CONFIG_RTP_PROTOCOL) += rtpproto.o
OBJS-$(CONFIG_TCP_PROTOCOL) += tcp.o
OBJS-$(CONFIG_UDP_PROTOCOL) += udp.o
-# libavdevice dependencies
-OBJS-$(CONFIG_ALSA_INDEV) += timefilter.o
-OBJS-$(CONFIG_JACK_INDEV) += timefilter.o
-TESTPROGS = seek timefilter
+TESTPROGS = seek
TOOLS = pktdumper probetest
include $(SRC_PATH)/subdir.mak
diff --git a/libavformat/flvdec.c b/libavformat/flvdec.c
index 7025ddd014..d48d367500 100644
--- a/libavformat/flvdec.c
+++ b/libavformat/flvdec.c
@@ -228,8 +228,9 @@ static int amf_parse_object(AVFormatContext *s, AVStream *astream, AVStream *vst
case AMF_DATA_TYPE_OBJECT: {
unsigned int keylen;
- if (vstream && ioc->seekable && key && !strcmp(KEYFRAMES_TAG, key) && depth == 1)
- if (parse_keyframes_index(s, ioc, vstream, max_pos) < 0)
+ if ((vstream || astream) && ioc->seekable && key && !strcmp(KEYFRAMES_TAG, key) && depth == 1)
+ if (parse_keyframes_index(s, ioc, vstream ? vstream : astream,
+ max_pos) < 0)
av_log(s, AV_LOG_ERROR, "Keyframe index parsing failed\n");
while(avio_tell(ioc) < max_pos - 2 && (keylen = avio_rb16(ioc))) {
diff --git a/libavformat/flvenc.c b/libavformat/flvenc.c
index 98c4170311..627bb6d3ab 100644
--- a/libavformat/flvenc.c
+++ b/libavformat/flvenc.c
@@ -60,10 +60,13 @@ typedef struct FLVContext {
int64_t duration_offset;
int64_t filesize_offset;
int64_t duration;
- int delay; ///< first dts delay for AVC
- int64_t last_ts;
} FLVContext;
+typedef struct FLVStreamContext {
+ int delay; ///< first dts delay for each stream (needed for AVC & Speex)
+ int64_t last_ts; ///< last timestamp for each stream
+} FLVStreamContext;
+
static int get_audio_flags(AVCodecContext *enc){
int flags = (enc->bits_per_coded_sample == 16) ? FLV_SAMPLESSIZE_16BIT : FLV_SAMPLESSIZE_8BIT;
@@ -182,6 +185,7 @@ static int flv_write_header(AVFormatContext *s)
for(i=0; i<s->nb_streams; i++){
AVCodecContext *enc = s->streams[i]->codec;
+ FLVStreamContext *sc;
if (enc->codec_type == AVMEDIA_TYPE_VIDEO) {
if (s->streams[i]->r_frame_rate.den && s->streams[i]->r_frame_rate.num) {
framerate = av_q2d(s->streams[i]->r_frame_rate);
@@ -199,6 +203,12 @@ static int flv_write_header(AVFormatContext *s)
return -1;
}
av_set_pts_info(s->streams[i], 32, 1, 1000); /* 32 bit pts in ms */
+
+ sc = av_mallocz(sizeof(FLVStreamContext));
+ if (!sc)
+ return AVERROR(ENOMEM);
+ s->streams[i]->priv_data = sc;
+ sc->last_ts = -1;
}
avio_write(pb, "FLV", 3);
avio_w8(pb,1);
@@ -218,8 +228,6 @@ static int flv_write_header(AVFormatContext *s)
}
}
- flv->last_ts = -1;
-
/* write meta_tag */
avio_w8(pb, 18); // tag type META
metadata_size_pos= avio_tell(pb);
@@ -361,9 +369,10 @@ static int flv_write_trailer(AVFormatContext *s)
/* Add EOS tag */
for (i = 0; i < s->nb_streams; i++) {
AVCodecContext *enc = s->streams[i]->codec;
+ FLVStreamContext *sc = s->streams[i]->priv_data;
if (enc->codec_type == AVMEDIA_TYPE_VIDEO &&
(enc->codec_id == CODEC_ID_H264 || enc->codec_id == CODEC_ID_MPEG4)) {
- put_avc_eos_tag(pb, flv->last_ts);
+ put_avc_eos_tag(pb, sc->last_ts);
}
}
@@ -384,6 +393,7 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt)
AVIOContext *pb = s->pb;
AVCodecContext *enc = s->streams[pkt->stream_index]->codec;
FLVContext *flv = s->priv_data;
+ FLVStreamContext *sc = s->streams[pkt->stream_index]->priv_data;
unsigned ts;
int size= pkt->size;
uint8_t *data= NULL;
@@ -434,20 +444,20 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt)
av_log(s, AV_LOG_ERROR, "malformated aac bitstream, use -absf aac_adtstoasc\n");
return -1;
}
- if (!flv->delay && pkt->dts < 0)
- flv->delay = -pkt->dts;
+ if (!sc->delay && pkt->dts < 0)
+ sc->delay = -pkt->dts;
- ts = pkt->dts + flv->delay; // add delay to force positive dts
+ ts = pkt->dts + sc->delay; // add delay to force positive dts
/* check Speex packet duration */
- if (enc->codec_id == CODEC_ID_SPEEX && ts - flv->last_ts > 160) {
+ if (enc->codec_id == CODEC_ID_SPEEX && ts - sc->last_ts > 160) {
av_log(s, AV_LOG_WARNING, "Warning: Speex stream has more than "
"8 frames per packet. Adobe Flash "
"Player cannot handle this!\n");
}
- if (flv->last_ts < ts)
- flv->last_ts = ts;
+ if (sc->last_ts < ts)
+ sc->last_ts = ts;
avio_wb24(pb,size + flags_size);
avio_wb24(pb,ts);
@@ -471,7 +481,7 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt)
avio_write(pb, data ? data : pkt->data, size);
avio_wb32(pb,size+flags_size+11); // previous tag size
- flv->duration = FFMAX(flv->duration, pkt->pts + flv->delay + pkt->duration);
+ flv->duration = FFMAX(flv->duration, pkt->pts + sc->delay + pkt->duration);
avio_flush(pb);
diff --git a/libavformat/mov.c b/libavformat/mov.c
index 3c8bbc9ca1..198f3cd938 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -35,6 +35,7 @@
#include "riff.h"
#include "isom.h"
#include "libavcodec/get_bits.h"
+#include "id3v1.h"
#if CONFIG_ZLIB
#include <zlib.h>
@@ -99,31 +100,48 @@ static int mov_metadata_track_or_disc_number(MOVContext *c, AVIOContext *pb,
return 0;
}
-static int mov_metadata_int8(MOVContext *c, AVIOContext *pb,
- unsigned len, const char *key)
+static int mov_metadata_int8_bypass_padding(MOVContext *c, AVIOContext *pb,
+ unsigned len, const char *key)
{
- char buf[16];
+ char buf[16];
+
+ /* bypass padding bytes */
+ avio_r8(pb);
+ avio_r8(pb);
+ avio_r8(pb);
+
+ snprintf(buf, sizeof(buf), "%hu", avio_r8(pb));
+ av_dict_set(&c->fc->metadata, key, buf, 0);
+
+ return 0;
+}
- /* bypass padding bytes */
- avio_r8(pb);
- avio_r8(pb);
- avio_r8(pb);
+static int mov_metadata_int8_no_padding(MOVContext *c, AVIOContext *pb,
+ unsigned len, const char *key)
+{
+ char buf[16];
- snprintf(buf, sizeof(buf), "%hu", avio_r8(pb));
- av_dict_set(&c->fc->metadata, key, buf, 0);
+ snprintf(buf, sizeof(buf), "%hu", avio_r8(pb));
+ av_dict_set(&c->fc->metadata, key, buf, 0);
- return 0;
+ return 0;
}
-static int mov_metadata_stik(MOVContext *c, AVIOContext *pb,
+static int mov_metadata_gnre(MOVContext *c, AVIOContext *pb,
unsigned len, const char *key)
{
- char buf[16];
+ short genre;
+ char buf[20];
- snprintf(buf, sizeof(buf), "%hu", avio_r8(pb));
- av_dict_set(&c->fc->metadata, key, buf, 0);
+ avio_r8(pb); // unknown
- return 0;
+ genre = avio_r8(pb);
+ if (genre < 1 || genre > ID3v1_GENRE_MAX)
+ return 0;
+ snprintf(buf, sizeof(buf), "%s", ff_id3v1_genre_str[genre-1]);
+ av_dict_set(&c->fc->metadata, key, buf, 0);
+
+ return 0;
}
static const uint32_t mac_to_unicode[128] = {
@@ -189,6 +207,8 @@ static int mov_read_udta_string(MOVContext *c, AVIOContext *pb, MOVAtom atom)
case MKTAG(0xa9,'a','l','b'): key = "album"; break;
case MKTAG(0xa9,'d','a','y'): key = "date"; break;
case MKTAG(0xa9,'g','e','n'): key = "genre"; break;
+ case MKTAG( 'g','n','r','e'): key = "genre";
+ parse = mov_metadata_gnre; break;
case MKTAG(0xa9,'t','o','o'):
case MKTAG(0xa9,'s','w','r'): key = "encoder"; break;
case MKTAG(0xa9,'e','n','c'): key = "encoder"; break;
@@ -202,11 +222,15 @@ static int mov_read_udta_string(MOVContext *c, AVIOContext *pb, MOVAtom atom)
case MKTAG( 'd','i','s','k'): key = "disc";
parse = mov_metadata_track_or_disc_number; break;
case MKTAG( 't','v','e','s'): key = "episode_sort";
- parse = mov_metadata_int8; break;
+ parse = mov_metadata_int8_bypass_padding; break;
case MKTAG( 't','v','s','n'): key = "season_number";
- parse = mov_metadata_int8; break;
+ parse = mov_metadata_int8_bypass_padding; break;
case MKTAG( 's','t','i','k'): key = "media_type";
- parse = mov_metadata_stik; break;
+ parse = mov_metadata_int8_no_padding; break;
+ case MKTAG( 'h','d','v','d'): key = "hd_video";
+ parse = mov_metadata_int8_no_padding; break;
+ case MKTAG( 'p','g','a','p'): key = "gapless_playback";
+ parse = mov_metadata_int8_no_padding; break;
}
if (c->itunes_metadata && atom.size > 8) {
diff --git a/libavformat/timefilter.c b/libavformat/timefilter.c
deleted file mode 100644
index 5c780c8d90..0000000000
--- a/libavformat/timefilter.c
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Delay Locked Loop based time filter
- * Copyright (c) 2009 Samalyse
- * Copyright (c) 2009 Michael Niedermayer
- * Author: Olivier Guilyardi <olivier samalyse com>
- * Michael Niedermayer <michaelni gmx at>
- *
- * This file is part of FFmpeg.
- *
- * 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.
- *
- * 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 FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-
-#include "config.h"
-#include "avformat.h"
-#include "timefilter.h"
-
-struct TimeFilter {
- /// Delay Locked Loop data. These variables refer to mathematical
- /// concepts described in: http://www.kokkinizita.net/papers/usingdll.pdf
- double cycle_time;
- double feedback2_factor;
- double feedback3_factor;
- double clock_period;
- int count;
-};
-
-TimeFilter * ff_timefilter_new(double clock_period, double feedback2_factor, double feedback3_factor)
-{
- TimeFilter *self = av_mallocz(sizeof(TimeFilter));
- self->clock_period = clock_period;
- self->feedback2_factor = feedback2_factor;
- self->feedback3_factor = feedback3_factor;
- return self;
-}
-
-void ff_timefilter_destroy(TimeFilter *self)
-{
- av_freep(&self);
-}
-
-void ff_timefilter_reset(TimeFilter *self)
-{
- self->count = 0;
-}
-
-double ff_timefilter_update(TimeFilter *self, double system_time, double period)
-{
- self->count++;
- if (self->count==1) {
- /// init loop
- self->cycle_time = system_time;
- } else {
- double loop_error;
- self->cycle_time += self->clock_period * period;
- /// calculate loop error
- loop_error = system_time - self->cycle_time;
-
- /// update loop
- self->cycle_time += FFMAX(self->feedback2_factor, 1.0/(self->count)) * loop_error;
- self->clock_period += self->feedback3_factor * loop_error / period;
- }
- return self->cycle_time;
-}
-
-#ifdef TEST
-#include "libavutil/lfg.h"
-#define LFG_MAX ((1LL << 32) - 1)
-
-#undef printf
-
-int main(void)
-{
- AVLFG prng;
- double n0,n1;
-#define SAMPLES 1000
- double ideal[SAMPLES];
- double samples[SAMPLES];
-#if 1
- for(n0= 0; n0<40; n0=2*n0+1){
- for(n1= 0; n1<10; n1=2*n1+1){
-#else
- {{
- n0=7;
- n1=1;
-#endif
- double best_error= 1000000000;
- double bestpar0=1;
- double bestpar1=0.001;
- int better, i;
-
- av_lfg_init(&prng, 123);
- for(i=0; i<SAMPLES; i++){
- ideal[i] = 10 + i + n1*i/(1000);
- samples[i] = ideal[i] + n0 * (av_lfg_get(&prng) - LFG_MAX / 2)
- / (LFG_MAX * 10LL);
- }
-
- do{
- double par0, par1;
- better=0;
- for(par0= bestpar0*0.8; par0<=bestpar0*1.21; par0+=bestpar0*0.05){
- for(par1= bestpar1*0.8; par1<=bestpar1*1.21; par1+=bestpar1*0.05){
- double error=0;
- TimeFilter *tf= ff_timefilter_new(1, par0, par1);
- for(i=0; i<SAMPLES; i++){
- double filtered;
- filtered= ff_timefilter_update(tf, samples[i], 1);
- error += (filtered - ideal[i]) * (filtered - ideal[i]);
- }
- ff_timefilter_destroy(tf);
- if(error < best_error){
- best_error= error;
- bestpar0= par0;
- bestpar1= par1;
- better=1;
- }
- }
- }
- }while(better);
-#if 0
- double lastfil=9;
- TimeFilter *tf= ff_timefilter_new(1, bestpar0, bestpar1);
- for(i=0; i<SAMPLES; i++){
- double filtered;
- filtered= ff_timefilter_update(tf, samples[i], 1);
- printf("%f %f %f %f\n", i - samples[i] + 10, filtered - samples[i], samples[FFMAX(i, 1)] - samples[FFMAX(i-1, 0)], filtered - lastfil);
- lastfil= filtered;
- }
- ff_timefilter_destroy(tf);
-#else
- printf(" [%f %f %9f]", bestpar0, bestpar1, best_error);
-#endif
- }
- printf("\n");
- }
- return 0;
-}
-#endif
diff --git a/libavformat/timefilter.h b/libavformat/timefilter.h
deleted file mode 100644
index ded8ec7bed..0000000000
--- a/libavformat/timefilter.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Delay Locked Loop based time filter prototypes and declarations
- * Copyright (c) 2009 Samalyse
- * Copyright (c) 2009 Michael Niedermayer
- * Author: Olivier Guilyardi <olivier samalyse com>
- * Michael Niedermayer <michaelni gmx at>
- *
- * This file is part of FFmpeg.
- *
- * 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.
- *
- * 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 FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef AVFORMAT_TIMEFILTER_H
-#define AVFORMAT_TIMEFILTER_H
-
-/**
- * Opaque type representing a time filter state
- *
- * The purpose of this filter is to provide a way to compute accurate time
- * stamps that can be compared to wall clock time, especially when dealing
- * with two clocks: the system clock and a hardware device clock, such as
- * a soundcard.
- */
-typedef struct TimeFilter TimeFilter;
-
-
-/**
- * Create a new Delay Locked Loop time filter
- *
- * feedback2_factor and feedback3_factor are the factors used for the
- * multiplications that are respectively performed in the second and third
- * feedback paths of the loop.
- *
- * Unless you know what you are doing, you should set these as follow:
- *
- * o = 2 * M_PI * bandwidth * period
- * feedback2_factor = sqrt(2 * o)
- * feedback3_factor = o * o
- *
- * Where bandwidth is up to you to choose. Smaller values will filter out more
- * of the jitter, but also take a longer time for the loop to settle. A good
- * starting point is something between 0.3 and 3 Hz.
- *
- * @param clock_period period of the hardware clock in seconds
- * (for example 1.0/44100)
- *
- * For more details about these parameters and background concepts please see:
- * http://www.kokkinizita.net/papers/usingdll.pdf
- */
-TimeFilter * ff_timefilter_new(double clock_period, double feedback2_factor, double feedback3_factor);
-
-/**
- * Update the filter
- *
- * This function must be called in real time, at each process cycle.
- *
- * @param period the device cycle duration in clock_periods. For example, at
- * 44.1kHz and a buffer size of 512 frames, period = 512 when clock_period
- * was 1.0/44100, or 512/44100 if clock_period was 1.
- *
- * system_time, in seconds, should be the value of the system clock time,
- * at (or as close as possible to) the moment the device hardware interrupt
- * occured (or any other event the device clock raises at the beginning of a
- * cycle).
- *
- * @return the filtered time, in seconds
- */
-double ff_timefilter_update(TimeFilter *self, double system_time, double period);
-
-/**
- * Reset the filter
- *
- * This function should mainly be called in case of XRUN.
- *
- * Warning: after calling this, the filter is in an undetermined state until
- * the next call to ff_timefilter_update()
- */
-void ff_timefilter_reset(TimeFilter *);
-
-/**
- * Free all resources associated with the filter
- */
-void ff_timefilter_destroy(TimeFilter *);
-
-#endif /* AVFORMAT_TIMEFILTER_H */