* qatar/master: (23 commits) build: cosmetics: Reorder some lists in a more logical fashion x86: pngdsp: Fix assembly for OS/2 fate: add test for RTjpeg in nuv with frameheader rtmp: send check_bw as notification g723_1: clip argument for 15-bit version of normalize_bits() g723_1: use all LPC vectors in formant postfilter id3v2: Support v2.2 PIC avplay: fix build with lavfi disabled. avconv: split configuring filter configuration to a separate file. avconv: split option parsing into a separate file. mpc8: do not leave padding after last frame in buffer for the next decode call mpegaudioenc: list supported channel layouts. mpegaudiodec: don't print an error on > 1 frame in a packet. api-example: update to new audio encoding API. configure: add --enable/disable-random option doc: cygwin: Update list of FATE package requirements build: Remove all installed headers and header directories on uninstall build: change checkheaders to use regular build rules rtmp: Add a new option 'rtmp_subscribe' rtmp: Add support for subscribing live streams ... Conflicts: Makefile common.mak configure doc/examples/decoding_encoding.c ffmpeg.c libavcodec/g723_1.c libavcodec/mpegaudiodec.c libavcodec/x86/pngdsp.asm libavformat/version.h library.mak tests/fate/video.mak Merged-by: Michael Niedermayer <michaelni@gmx.at>tags/n1.0
| @@ -4,7 +4,7 @@ | |||
| *.def | |||
| *.dll | |||
| *.exe | |||
| *.ho | |||
| *.h.c | |||
| *.lib | |||
| *.pc | |||
| *.so | |||
| @@ -18,6 +18,7 @@ PROGS-$(CONFIG_FFSERVER) += ffserver | |||
| PROGS := $(PROGS-yes:%=%$(EXESUF)) | |||
| INSTPROGS = $(PROGS-yes:%=%$(PROGSSUF)$(EXESUF)) | |||
| OBJS = cmdutils.o | |||
| OBJS-ffmpeg = ffmpeg_opt.o ffmpeg_filter.o | |||
| TESTTOOLS = audiogen videogen rotozoom tiny_psnr base64 | |||
| HOSTPROGS := $(TESTTOOLS:%=tests/%) doc/print_options | |||
| TOOLS = qt-faststart trasher | |||
| @@ -68,8 +69,9 @@ config.h: .config | |||
| SUBDIR_VARS := CLEANFILES EXAMPLES FFLIBS HOSTPROGS TESTPROGS TOOLS \ | |||
| ARCH_HEADERS BUILT_HEADERS SKIPHEADERS \ | |||
| ALTIVEC-OBJS ARMV5TE-OBJS ARMV6-OBJS ARMVFP-OBJS MMI-OBJS \ | |||
| MMX-OBJS NEON-OBJS VIS-OBJS YASM-OBJS \ | |||
| ARMV5TE-OBJS ARMV6-OBJS ARMVFP-OBJS NEON-OBJS \ | |||
| MMI-OBJS ALTIVEC-OBJS VIS-OBJS \ | |||
| MMX-OBJS YASM-OBJS \ | |||
| MIPSFPU-OBJS MIPSDSPR2-OBJS MIPSDSPR1-OBJS MIPS32R2-OBJS \ | |||
| OBJS TESTOBJS | |||
| @@ -10,8 +10,9 @@ ifndef SUBDIR | |||
| ifndef V | |||
| Q = @ | |||
| ECHO = printf "$(1)\t%s\n" $(2) | |||
| BRIEF = CC CXX AS YASM AR LD HOSTCC STRIP CP | |||
| SILENT = DEPCC DEPAS DEPHOSTCC DEPYASM RM RANLIB | |||
| BRIEF = CC CXX HOSTCC AS YASM AR LD STRIP CP | |||
| SILENT = DEPCC DEPHOSTCC DEPAS DEPYASM RANLIB RM | |||
| MSG = $@ | |||
| M = @$(call ECHO,$(TAG),$@); | |||
| $(foreach VAR,$(BRIEF), \ | |||
| @@ -98,8 +99,9 @@ DEP_LIBS := $(foreach NAME,$(FFLIBS),lib$(NAME)/$($(CONFIG_SHARED:yes=S)LIBNAME) | |||
| ALLHEADERS := $(subst $(SRC_DIR)/,$(SUBDIR),$(wildcard $(SRC_DIR)/*.h $(SRC_DIR)/$(ARCH)/*.h)) | |||
| SKIPHEADERS += $(ARCH_HEADERS:%=$(ARCH)/%) $(SKIPHEADERS-) | |||
| SKIPHEADERS := $(SKIPHEADERS:%=$(SUBDIR)%) | |||
| HEADEROBJS := $(filter-out $(SKIPHEADERS:.h=.ho),$(ALLHEADERS:.h=.ho)) | |||
| checkheaders: $(HEADEROBJS) | |||
| HOBJS = $(filter-out $(SKIPHEADERS:.h=.h.o),$(ALLHEADERS:.h=.h.o)) | |||
| checkheaders: $(HOBJS) | |||
| .SECONDARY: $(HOBJS:.o=.c) | |||
| alltools: $(TOOLS) | |||
| @@ -117,8 +119,8 @@ $(TOOLOBJS): | tools | |||
| OBJDIRS := $(OBJDIRS) $(dir $(OBJS) $(HOSTOBJS) $(TESTOBJS) $(HEADEROBJS)) | |||
| CLEANSUFFIXES = *.d *.o *~ *.ho *.map *.ver *.gcno *.gcda | |||
| CLEANSUFFIXES = *.d *.o *~ *.h.c *.map *.ver *.ho *.gcno *.gcda | |||
| DISTCLEANSUFFIXES = *.pc | |||
| LIBSUFFIXES = *.a *.lib *.so *.so.* *.dylib *.dll *.def *.dll.a | |||
| -include $(wildcard $(OBJS:.o=.d) $(HOSTOBJS:.o=.d) $(TESTOBJS:.o=.d)) | |||
| -include $(wildcard $(OBJS:.o=.d) $(HOSTOBJS:.o=.d) $(TESTOBJS:.o=.d) $(HOBJS:.o=.d)) | |||
| @@ -1211,6 +1211,7 @@ HAVE_LIST=" | |||
| alsa_asoundlib_h | |||
| altivec_h | |||
| arpa_inet_h | |||
| asm_mod_q | |||
| asm_mod_y | |||
| asm_types_h | |||
| attribute_may_alias | |||
| @@ -3119,6 +3120,7 @@ EOF | |||
| enabled neon && check_asm neon '"vadd.i16 q0, q0, q0"' | |||
| enabled vfpv3 && check_asm vfpv3 '"vmov.f32 s0, #1.0"' | |||
| check_asm asm_mod_q '"add r0, %Q0, %R0" :: "r"((long long)0)' | |||
| check_asm asm_mod_y '"vmul.i32 d0, d0, %y0" :: "x"(0)' | |||
| enabled_all armv6t2 shared !pic && enable_pic | |||
| @@ -34,6 +34,7 @@ | |||
| #include <libavutil/imgutils.h> | |||
| #include <libavutil/opt.h> | |||
| #include <libavcodec/avcodec.h> | |||
| #include <libavutil/audioconvert.h> | |||
| #include <libavutil/mathematics.h> | |||
| #include <libavutil/samplefmt.h> | |||
| @@ -41,6 +42,59 @@ | |||
| #define AUDIO_INBUF_SIZE 20480 | |||
| #define AUDIO_REFILL_THRESH 4096 | |||
| /* check that a given sample format is supported by the encoder */ | |||
| static int check_sample_fmt(AVCodec *codec, enum AVSampleFormat sample_fmt) | |||
| { | |||
| const enum AVSampleFormat *p = codec->sample_fmts; | |||
| while (*p != AV_SAMPLE_FMT_NONE) { | |||
| if (*p == sample_fmt) | |||
| return 1; | |||
| p++; | |||
| } | |||
| return 0; | |||
| } | |||
| /* just pick the highest supported samplerate */ | |||
| static int select_sample_rate(AVCodec *codec) | |||
| { | |||
| const int *p; | |||
| int best_samplerate = 0; | |||
| if (!codec->supported_samplerates) | |||
| return 44100; | |||
| p = codec->supported_samplerates; | |||
| while (*p) { | |||
| best_samplerate = FFMAX(*p, best_samplerate); | |||
| p++; | |||
| } | |||
| return best_samplerate; | |||
| } | |||
| /* select layout with the highest channel count */ | |||
| static int select_channel_layout(AVCodec *codec) | |||
| { | |||
| const uint64_t *p; | |||
| uint64_t best_ch_layout = 0; | |||
| int best_nb_channells = 0; | |||
| if (!codec->channel_layouts) | |||
| return AV_CH_LAYOUT_STEREO; | |||
| p = codec->channel_layouts; | |||
| while (*p) { | |||
| int nb_channels = av_get_channel_layout_nb_channels(*p); | |||
| if (nb_channels > best_nb_channells) { | |||
| best_ch_layout = *p; | |||
| best_nb_channells = nb_channels; | |||
| } | |||
| p++; | |||
| } | |||
| return best_ch_layout; | |||
| } | |||
| /* | |||
| * Audio encoding example | |||
| */ | |||
| @@ -48,11 +102,13 @@ static void audio_encode_example(const char *filename) | |||
| { | |||
| AVCodec *codec; | |||
| AVCodecContext *c= NULL; | |||
| int frame_size, i, j, out_size, outbuf_size; | |||
| AVFrame *frame; | |||
| AVPacket pkt; | |||
| int i, j, k, ret, got_output; | |||
| int buffer_size; | |||
| FILE *f; | |||
| short *samples; | |||
| uint16_t *samples; | |||
| float t, tincr; | |||
| uint8_t *outbuf; | |||
| printf("Encode audio file %s\n", filename); | |||
| @@ -67,9 +123,19 @@ static void audio_encode_example(const char *filename) | |||
| /* put sample parameters */ | |||
| c->bit_rate = 64000; | |||
| c->sample_rate = 44100; | |||
| c->channels = 2; | |||
| /* check that the encoder supports s16 pcm input */ | |||
| c->sample_fmt = AV_SAMPLE_FMT_S16; | |||
| if (!check_sample_fmt(codec, c->sample_fmt)) { | |||
| fprintf(stderr, "encoder does not support %s", | |||
| av_get_sample_fmt_name(c->sample_fmt)); | |||
| exit(1); | |||
| } | |||
| /* select other audio parameters supported by the encoder */ | |||
| c->sample_rate = select_sample_rate(codec); | |||
| c->channel_layout = select_channel_layout(codec); | |||
| c->channels = av_get_channel_layout_nb_channels(c->channel_layout); | |||
| /* open it */ | |||
| if (avcodec_open2(c, codec, NULL) < 0) { | |||
| @@ -77,35 +143,71 @@ static void audio_encode_example(const char *filename) | |||
| exit(1); | |||
| } | |||
| /* the codec gives us the frame size, in samples */ | |||
| frame_size = c->frame_size; | |||
| samples = malloc(frame_size * 2 * c->channels); | |||
| outbuf_size = 10000; | |||
| outbuf = malloc(outbuf_size); | |||
| f = fopen(filename, "wb"); | |||
| if (!f) { | |||
| fprintf(stderr, "could not open %s\n", filename); | |||
| exit(1); | |||
| } | |||
| /* frame containing input raw audio */ | |||
| frame = avcodec_alloc_frame(); | |||
| if (!frame) { | |||
| fprintf(stderr, "could not allocate audio frame\n"); | |||
| exit(1); | |||
| } | |||
| frame->nb_samples = c->frame_size; | |||
| frame->format = c->sample_fmt; | |||
| frame->channel_layout = c->channel_layout; | |||
| /* the codec gives us the frame size, in samples, | |||
| * we calculate the size of the samples buffer in bytes */ | |||
| buffer_size = av_samples_get_buffer_size(NULL, c->channels, c->frame_size, | |||
| c->sample_fmt, 0); | |||
| samples = av_malloc(buffer_size); | |||
| if (!samples) { | |||
| fprintf(stderr, "could not allocate %d bytes for samples buffer\n", | |||
| buffer_size); | |||
| exit(1); | |||
| } | |||
| /* setup the data pointers in the AVFrame */ | |||
| ret = avcodec_fill_audio_frame(frame, c->channels, c->sample_fmt, | |||
| (const uint8_t*)samples, buffer_size, 0); | |||
| if (ret < 0) { | |||
| fprintf(stderr, "could not setup audio frame\n"); | |||
| exit(1); | |||
| } | |||
| /* encode a single tone sound */ | |||
| t = 0; | |||
| tincr = 2 * M_PI * 440.0 / c->sample_rate; | |||
| for(i=0;i<200;i++) { | |||
| for(j=0;j<frame_size;j++) { | |||
| av_init_packet(&pkt); | |||
| pkt.data = NULL; // packet data will be allocated by the encoder | |||
| pkt.size = 0; | |||
| for (j = 0; j < c->frame_size; j++) { | |||
| samples[2*j] = (int)(sin(t) * 10000); | |||
| samples[2*j+1] = samples[2*j]; | |||
| for (k = 1; k < c->channels; k++) | |||
| samples[2*j + k] = samples[2*j]; | |||
| t += tincr; | |||
| } | |||
| /* encode the samples */ | |||
| out_size = avcodec_encode_audio(c, outbuf, outbuf_size, samples); | |||
| fwrite(outbuf, 1, out_size, f); | |||
| ret = avcodec_encode_audio2(c, &pkt, frame, &got_output); | |||
| if (ret < 0) { | |||
| fprintf(stderr, "error encoding audio frame\n"); | |||
| exit(1); | |||
| } | |||
| if (got_output) { | |||
| fwrite(pkt.data, 1, pkt.size, f); | |||
| av_free_packet(&pkt); | |||
| } | |||
| } | |||
| fclose(f); | |||
| free(outbuf); | |||
| free(samples); | |||
| av_freep(&samples); | |||
| av_freep(&frame); | |||
| avcodec_close(c); | |||
| av_free(c); | |||
| } | |||
| @@ -318,9 +318,9 @@ following "Devel" ones: | |||
| binutils, gcc4-core, make, git, mingw-runtime, texi2html | |||
| @end example | |||
| And the following "Utils" one: | |||
| In order to run FATE you will also need the following "Utils" packages: | |||
| @example | |||
| diffutils | |||
| bc, diffutils | |||
| @end example | |||
| Then run | |||
| @@ -267,6 +267,11 @@ value will be sent. | |||
| Stream identifier to play or to publish. This option overrides the | |||
| parameter specified in the URI. | |||
| @item rtmp_subscribe | |||
| Name of live stream to subscribe to. By default no value will be sent. | |||
| It is only sent if the option is specified or if rtmp_live | |||
| is set to live. | |||
| @item rtmp_swfurl | |||
| URL of the SWF player for the media. By default no value will be sent. | |||
| @@ -0,0 +1,391 @@ | |||
| /* | |||
| * 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 FFMPEG_H | |||
| #define FFMPEG_H | |||
| #include "config.h" | |||
| #include <stdint.h> | |||
| #include <stdio.h> | |||
| #include <signal.h> | |||
| #if HAVE_PTHREADS | |||
| #include <pthread.h> | |||
| #endif | |||
| #include "cmdutils.h" | |||
| #include "libavformat/avformat.h" | |||
| #include "libavformat/avio.h" | |||
| #include "libavcodec/avcodec.h" | |||
| #include "libavfilter/avfilter.h" | |||
| #include "libavfilter/avfiltergraph.h" | |||
| #include "libavutil/avutil.h" | |||
| #include "libavutil/dict.h" | |||
| #include "libavutil/fifo.h" | |||
| #include "libavutil/pixfmt.h" | |||
| #include "libavutil/rational.h" | |||
| #include "libswresample/swresample.h" | |||
| #define VSYNC_AUTO -1 | |||
| #define VSYNC_PASSTHROUGH 0 | |||
| #define VSYNC_CFR 1 | |||
| #define VSYNC_VFR 2 | |||
| #define VSYNC_DROP 0xff | |||
| #define MAX_STREAMS 1024 /* arbitrary sanity check value */ | |||
| /* select an input stream for an output stream */ | |||
| typedef struct StreamMap { | |||
| int disabled; /** 1 is this mapping is disabled by a negative map */ | |||
| int file_index; | |||
| int stream_index; | |||
| int sync_file_index; | |||
| int sync_stream_index; | |||
| char *linklabel; /** name of an output link, for mapping lavfi outputs */ | |||
| } StreamMap; | |||
| typedef struct { | |||
| int file_idx, stream_idx, channel_idx; // input | |||
| int ofile_idx, ostream_idx; // output | |||
| } AudioChannelMap; | |||
| typedef struct OptionsContext { | |||
| /* input/output options */ | |||
| int64_t start_time; | |||
| const char *format; | |||
| SpecifierOpt *codec_names; | |||
| int nb_codec_names; | |||
| SpecifierOpt *audio_channels; | |||
| int nb_audio_channels; | |||
| SpecifierOpt *audio_sample_rate; | |||
| int nb_audio_sample_rate; | |||
| SpecifierOpt *frame_rates; | |||
| int nb_frame_rates; | |||
| SpecifierOpt *frame_sizes; | |||
| int nb_frame_sizes; | |||
| SpecifierOpt *frame_pix_fmts; | |||
| int nb_frame_pix_fmts; | |||
| /* input options */ | |||
| int64_t input_ts_offset; | |||
| int rate_emu; | |||
| SpecifierOpt *ts_scale; | |||
| int nb_ts_scale; | |||
| SpecifierOpt *dump_attachment; | |||
| int nb_dump_attachment; | |||
| /* output options */ | |||
| StreamMap *stream_maps; | |||
| int nb_stream_maps; | |||
| AudioChannelMap *audio_channel_maps; /* one info entry per -map_channel */ | |||
| int nb_audio_channel_maps; /* number of (valid) -map_channel settings */ | |||
| int metadata_global_manual; | |||
| int metadata_streams_manual; | |||
| int metadata_chapters_manual; | |||
| const char **attachments; | |||
| int nb_attachments; | |||
| int chapters_input_file; | |||
| int64_t recording_time; | |||
| uint64_t limit_filesize; | |||
| float mux_preload; | |||
| float mux_max_delay; | |||
| int video_disable; | |||
| int audio_disable; | |||
| int subtitle_disable; | |||
| int data_disable; | |||
| /* indexed by output file stream index */ | |||
| int *streamid_map; | |||
| int nb_streamid_map; | |||
| SpecifierOpt *metadata; | |||
| int nb_metadata; | |||
| SpecifierOpt *max_frames; | |||
| int nb_max_frames; | |||
| SpecifierOpt *bitstream_filters; | |||
| int nb_bitstream_filters; | |||
| SpecifierOpt *codec_tags; | |||
| int nb_codec_tags; | |||
| SpecifierOpt *sample_fmts; | |||
| int nb_sample_fmts; | |||
| SpecifierOpt *qscale; | |||
| int nb_qscale; | |||
| SpecifierOpt *forced_key_frames; | |||
| int nb_forced_key_frames; | |||
| SpecifierOpt *force_fps; | |||
| int nb_force_fps; | |||
| SpecifierOpt *frame_aspect_ratios; | |||
| int nb_frame_aspect_ratios; | |||
| SpecifierOpt *rc_overrides; | |||
| int nb_rc_overrides; | |||
| SpecifierOpt *intra_matrices; | |||
| int nb_intra_matrices; | |||
| SpecifierOpt *inter_matrices; | |||
| int nb_inter_matrices; | |||
| SpecifierOpt *top_field_first; | |||
| int nb_top_field_first; | |||
| SpecifierOpt *metadata_map; | |||
| int nb_metadata_map; | |||
| SpecifierOpt *presets; | |||
| int nb_presets; | |||
| SpecifierOpt *copy_initial_nonkeyframes; | |||
| int nb_copy_initial_nonkeyframes; | |||
| SpecifierOpt *filters; | |||
| int nb_filters; | |||
| } OptionsContext; | |||
| typedef struct InputFilter { | |||
| AVFilterContext *filter; | |||
| struct InputStream *ist; | |||
| struct FilterGraph *graph; | |||
| uint8_t *name; | |||
| } InputFilter; | |||
| typedef struct OutputFilter { | |||
| AVFilterContext *filter; | |||
| struct OutputStream *ost; | |||
| struct FilterGraph *graph; | |||
| uint8_t *name; | |||
| /* temporary storage until stream maps are processed */ | |||
| AVFilterInOut *out_tmp; | |||
| } OutputFilter; | |||
| typedef struct FilterGraph { | |||
| int index; | |||
| const char *graph_desc; | |||
| AVFilterGraph *graph; | |||
| InputFilter **inputs; | |||
| int nb_inputs; | |||
| OutputFilter **outputs; | |||
| int nb_outputs; | |||
| } FilterGraph; | |||
| typedef struct InputStream { | |||
| int file_index; | |||
| AVStream *st; | |||
| int discard; /* true if stream data should be discarded */ | |||
| int decoding_needed; /* true if the packets must be decoded in 'raw_fifo' */ | |||
| AVCodec *dec; | |||
| AVFrame *decoded_frame; | |||
| int64_t start; /* time when read started */ | |||
| /* predicted dts of the next packet read for this stream or (when there are | |||
| * several frames in a packet) of the next frame in current packet (in AV_TIME_BASE units) */ | |||
| int64_t next_dts; | |||
| int64_t dts; ///< dts of the last packet read for this stream (in AV_TIME_BASE units) | |||
| int64_t next_pts; ///< synthetic pts for the next decode frame (in AV_TIME_BASE units) | |||
| int64_t pts; ///< current pts of the decoded frame (in AV_TIME_BASE units) | |||
| int wrap_correction_done; | |||
| double ts_scale; | |||
| int is_start; /* is 1 at the start and after a discontinuity */ | |||
| int saw_first_ts; | |||
| int showed_multi_packet_warning; | |||
| AVDictionary *opts; | |||
| AVRational framerate; /* framerate forced with -r */ | |||
| int top_field_first; | |||
| int resample_height; | |||
| int resample_width; | |||
| int resample_pix_fmt; | |||
| int resample_sample_fmt; | |||
| int resample_sample_rate; | |||
| int resample_channels; | |||
| uint64_t resample_channel_layout; | |||
| struct sub2video { | |||
| int64_t last_pts; | |||
| AVFilterBufferRef *ref; | |||
| int w, h; | |||
| } sub2video; | |||
| /* a pool of free buffers for decoded data */ | |||
| FrameBuffer *buffer_pool; | |||
| int dr1; | |||
| /* decoded data from this stream goes into all those filters | |||
| * currently video and audio only */ | |||
| InputFilter **filters; | |||
| int nb_filters; | |||
| } InputStream; | |||
| typedef struct InputFile { | |||
| AVFormatContext *ctx; | |||
| int eof_reached; /* true if eof reached */ | |||
| int unavailable; /* true if the file is unavailable (possibly temporarily) */ | |||
| int ist_index; /* index of first stream in input_streams */ | |||
| int64_t ts_offset; | |||
| int nb_streams; /* number of stream that ffmpeg is aware of; may be different | |||
| from ctx.nb_streams if new streams appear during av_read_frame() */ | |||
| int nb_streams_warn; /* number of streams that the user was warned of */ | |||
| int rate_emu; | |||
| #if HAVE_PTHREADS | |||
| pthread_t thread; /* thread reading from this file */ | |||
| int finished; /* the thread has exited */ | |||
| int joined; /* the thread has been joined */ | |||
| pthread_mutex_t fifo_lock; /* lock for access to fifo */ | |||
| pthread_cond_t fifo_cond; /* the main thread will signal on this cond after reading from fifo */ | |||
| AVFifoBuffer *fifo; /* demuxed packets are stored here; freed by the main thread */ | |||
| #endif | |||
| } InputFile; | |||
| typedef struct OutputStream { | |||
| int file_index; /* file index */ | |||
| int index; /* stream index in the output file */ | |||
| int source_index; /* InputStream index */ | |||
| AVStream *st; /* stream in the output file */ | |||
| int encoding_needed; /* true if encoding needed for this stream */ | |||
| int frame_number; | |||
| /* input pts and corresponding output pts | |||
| for A/V sync */ | |||
| struct InputStream *sync_ist; /* input stream to sync against */ | |||
| int64_t sync_opts; /* output frame counter, could be changed to some true timestamp */ // FIXME look at frame_number | |||
| /* pts of the first frame encoded for this stream, used for limiting | |||
| * recording time */ | |||
| int64_t first_pts; | |||
| AVBitStreamFilterContext *bitstream_filters; | |||
| AVCodec *enc; | |||
| int64_t max_frames; | |||
| AVFrame *filtered_frame; | |||
| /* video only */ | |||
| AVRational frame_rate; | |||
| int force_fps; | |||
| int top_field_first; | |||
| float frame_aspect_ratio; | |||
| float last_quality; | |||
| /* forced key frames */ | |||
| int64_t *forced_kf_pts; | |||
| int forced_kf_count; | |||
| int forced_kf_index; | |||
| char *forced_keyframes; | |||
| /* audio only */ | |||
| int audio_channels_map[SWR_CH_MAX]; /* list of the channels id to pick from the source stream */ | |||
| int audio_channels_mapped; /* number of channels in audio_channels_map */ | |||
| FILE *logfile; | |||
| OutputFilter *filter; | |||
| char *avfilter; | |||
| int64_t sws_flags; | |||
| int64_t swr_dither_method; | |||
| double swr_dither_scale; | |||
| AVDictionary *opts; | |||
| int is_past_recording_time; | |||
| int unavailable; /* true if the steram is unavailable (possibly temporarily) */ | |||
| int stream_copy; | |||
| const char *attachment_filename; | |||
| int copy_initial_nonkeyframes; | |||
| int keep_pix_fmt; | |||
| } OutputStream; | |||
| typedef struct OutputFile { | |||
| AVFormatContext *ctx; | |||
| AVDictionary *opts; | |||
| int ost_index; /* index of the first stream in output_streams */ | |||
| int64_t recording_time; ///< desired length of the resulting file in microseconds == AV_TIME_BASE units | |||
| int64_t start_time; ///< start time in microseconds == AV_TIME_BASE units | |||
| uint64_t limit_filesize; /* filesize limit expressed in bytes */ | |||
| } OutputFile; | |||
| extern InputStream **input_streams; | |||
| extern int nb_input_streams; | |||
| extern InputFile **input_files; | |||
| extern int nb_input_files; | |||
| extern OutputStream **output_streams; | |||
| extern int nb_output_streams; | |||
| extern OutputFile **output_files; | |||
| extern int nb_output_files; | |||
| extern FilterGraph **filtergraphs; | |||
| extern int nb_filtergraphs; | |||
| extern const char *pass_logfilename_prefix; | |||
| extern char *vstats_filename; | |||
| extern float audio_drift_threshold; | |||
| extern float dts_delta_threshold; | |||
| extern float dts_error_threshold; | |||
| extern int audio_volume; | |||
| extern int audio_sync_method; | |||
| extern int video_sync_method; | |||
| extern int do_benchmark; | |||
| extern int do_benchmark_all; | |||
| extern int do_deinterlace; | |||
| extern int do_hex_dump; | |||
| extern int do_pkt_dump; | |||
| extern int copy_ts; | |||
| extern int copy_tb; | |||
| extern int debug_ts; | |||
| extern int opt_shortest; | |||
| extern int exit_on_error; | |||
| extern int print_stats; | |||
| extern int qp_hist; | |||
| extern int same_quant; | |||
| extern int stdin_interaction; | |||
| extern int frame_bits_per_raw_sample; | |||
| extern AVIOContext *progress_avio; | |||
| extern const AVIOInterruptCB int_cb; | |||
| extern const OptionDef options[]; | |||
| void term_init(void); | |||
| void term_exit(void); | |||
| void reset_options(OptionsContext *o, int is_input); | |||
| void show_usage(void); | |||
| void opt_output_file(void *optctx, const char *filename); | |||
| void assert_avoptions(AVDictionary *m); | |||
| int guess_input_channel_layout(InputStream *ist); | |||
| enum PixelFormat choose_pixel_fmt(AVStream *st, AVCodec *codec, enum PixelFormat target); | |||
| void choose_sample_fmt(AVStream *st, AVCodec *codec); | |||
| int configure_filtergraph(FilterGraph *fg); | |||
| int configure_output_filter(FilterGraph *fg, OutputFilter *ofilter, AVFilterInOut *out); | |||
| int ist_in_filtergraph(FilterGraph *fg, InputStream *ist); | |||
| FilterGraph *init_simple_filtergraph(InputStream *ist, OutputStream *ost); | |||
| #endif /* FFMPEG_H */ | |||
| @@ -0,0 +1,789 @@ | |||
| /* | |||
| * ffmpeg filter configuration | |||
| * | |||
| * 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 "ffmpeg.h" | |||
| #include "libavfilter/avfilter.h" | |||
| #include "libavfilter/avfiltergraph.h" | |||
| #include "libavfilter/buffersink.h" | |||
| #include "libavutil/audioconvert.h" | |||
| #include "libavutil/avassert.h" | |||
| #include "libavutil/avstring.h" | |||
| #include "libavutil/bprint.h" | |||
| #include "libavutil/pixdesc.h" | |||
| #include "libavutil/pixfmt.h" | |||
| #include "libavutil/imgutils.h" | |||
| #include "libavutil/samplefmt.h" | |||
| enum PixelFormat choose_pixel_fmt(AVStream *st, AVCodec *codec, enum PixelFormat target) | |||
| { | |||
| if (codec && codec->pix_fmts) { | |||
| const enum PixelFormat *p = codec->pix_fmts; | |||
| int has_alpha= av_pix_fmt_descriptors[target].nb_components % 2 == 0; | |||
| enum PixelFormat best= PIX_FMT_NONE; | |||
| if (st->codec->strict_std_compliance <= FF_COMPLIANCE_UNOFFICIAL) { | |||
| if (st->codec->codec_id == AV_CODEC_ID_MJPEG) { | |||
| p = (const enum PixelFormat[]) { PIX_FMT_YUVJ420P, PIX_FMT_YUVJ422P, PIX_FMT_YUV420P, PIX_FMT_YUV422P, PIX_FMT_NONE }; | |||
| } else if (st->codec->codec_id == AV_CODEC_ID_LJPEG) { | |||
| p = (const enum PixelFormat[]) { PIX_FMT_YUVJ420P, PIX_FMT_YUVJ422P, PIX_FMT_YUVJ444P, PIX_FMT_YUV420P, | |||
| PIX_FMT_YUV422P, PIX_FMT_YUV444P, PIX_FMT_BGRA, PIX_FMT_NONE }; | |||
| } | |||
| } | |||
| for (; *p != PIX_FMT_NONE; p++) { | |||
| best= avcodec_find_best_pix_fmt2(best, *p, target, has_alpha, NULL); | |||
| if (*p == target) | |||
| break; | |||
| } | |||
| if (*p == PIX_FMT_NONE) { | |||
| if (target != PIX_FMT_NONE) | |||
| av_log(NULL, AV_LOG_WARNING, | |||
| "Incompatible pixel format '%s' for codec '%s', auto-selecting format '%s'\n", | |||
| av_pix_fmt_descriptors[target].name, | |||
| codec->name, | |||
| av_pix_fmt_descriptors[best].name); | |||
| return best; | |||
| } | |||
| } | |||
| return target; | |||
| } | |||
| void choose_sample_fmt(AVStream *st, AVCodec *codec) | |||
| { | |||
| if (codec && codec->sample_fmts) { | |||
| const enum AVSampleFormat *p = codec->sample_fmts; | |||
| for (; *p != -1; p++) { | |||
| if (*p == st->codec->sample_fmt) | |||
| break; | |||
| } | |||
| if (*p == -1) { | |||
| if((codec->capabilities & CODEC_CAP_LOSSLESS) && av_get_sample_fmt_name(st->codec->sample_fmt) > av_get_sample_fmt_name(codec->sample_fmts[0])) | |||
| av_log(NULL, AV_LOG_ERROR, "Conversion will not be lossless.\n"); | |||
| if(av_get_sample_fmt_name(st->codec->sample_fmt)) | |||
| av_log(NULL, AV_LOG_WARNING, | |||
| "Incompatible sample format '%s' for codec '%s', auto-selecting format '%s'\n", | |||
| av_get_sample_fmt_name(st->codec->sample_fmt), | |||
| codec->name, | |||
| av_get_sample_fmt_name(codec->sample_fmts[0])); | |||
| st->codec->sample_fmt = codec->sample_fmts[0]; | |||
| } | |||
| } | |||
| } | |||
| static char *choose_pix_fmts(OutputStream *ost) | |||
| { | |||
| if (ost->keep_pix_fmt) { | |||
| if (ost->filter) | |||
| avfilter_graph_set_auto_convert(ost->filter->graph->graph, | |||
| AVFILTER_AUTO_CONVERT_NONE); | |||
| if (ost->st->codec->pix_fmt == PIX_FMT_NONE) | |||
| return NULL; | |||
| return av_strdup(av_get_pix_fmt_name(ost->st->codec->pix_fmt)); | |||
| } | |||
| if (ost->st->codec->pix_fmt != PIX_FMT_NONE) { | |||
| return av_strdup(av_get_pix_fmt_name(choose_pixel_fmt(ost->st, ost->enc, ost->st->codec->pix_fmt))); | |||
| } else if (ost->enc && ost->enc->pix_fmts) { | |||
| const enum PixelFormat *p; | |||
| AVIOContext *s = NULL; | |||
| uint8_t *ret; | |||
| int len; | |||
| if (avio_open_dyn_buf(&s) < 0) | |||
| exit_program(1); | |||
| p = ost->enc->pix_fmts; | |||
| if (ost->st->codec->strict_std_compliance <= FF_COMPLIANCE_UNOFFICIAL) { | |||
| if (ost->st->codec->codec_id == AV_CODEC_ID_MJPEG) { | |||
| p = (const enum PixelFormat[]) { PIX_FMT_YUVJ420P, PIX_FMT_YUVJ422P, PIX_FMT_YUV420P, PIX_FMT_YUV422P, PIX_FMT_NONE }; | |||
| } else if (ost->st->codec->codec_id == AV_CODEC_ID_LJPEG) { | |||
| p = (const enum PixelFormat[]) { PIX_FMT_YUVJ420P, PIX_FMT_YUVJ422P, PIX_FMT_YUVJ444P, PIX_FMT_YUV420P, | |||
| PIX_FMT_YUV422P, PIX_FMT_YUV444P, PIX_FMT_BGRA, PIX_FMT_NONE }; | |||
| } | |||
| } | |||
| for (; *p != PIX_FMT_NONE; p++) { | |||
| const char *name = av_get_pix_fmt_name(*p); | |||
| avio_printf(s, "%s:", name); | |||
| } | |||
| len = avio_close_dyn_buf(s, &ret); | |||
| ret[len - 1] = 0; | |||
| return ret; | |||
| } else | |||
| return NULL; | |||
| } | |||
| /** | |||
| * Define a function for building a string containing a list of | |||
| * allowed formats, | |||
| */ | |||
| #define DEF_CHOOSE_FORMAT(type, var, supported_list, none, get_name, separator)\ | |||
| static char *choose_ ## var ## s(OutputStream *ost) \ | |||
| { \ | |||
| if (ost->st->codec->var != none) { \ | |||
| get_name(ost->st->codec->var); \ | |||
| return av_strdup(name); \ | |||
| } else if (ost->enc->supported_list) { \ | |||
| const type *p; \ | |||
| AVIOContext *s = NULL; \ | |||
| uint8_t *ret; \ | |||
| int len; \ | |||
| \ | |||
| if (avio_open_dyn_buf(&s) < 0) \ | |||
| exit_program(1); \ | |||
| \ | |||
| for (p = ost->enc->supported_list; *p != none; p++) { \ | |||
| get_name(*p); \ | |||
| avio_printf(s, "%s" separator, name); \ | |||
| } \ | |||
| len = avio_close_dyn_buf(s, &ret); \ | |||
| ret[len - 1] = 0; \ | |||
| return ret; \ | |||
| } else \ | |||
| return NULL; \ | |||
| } | |||
| #define GET_PIX_FMT_NAME(pix_fmt)\ | |||
| const char *name = av_get_pix_fmt_name(pix_fmt); | |||
| // DEF_CHOOSE_FORMAT(enum PixelFormat, pix_fmt, pix_fmts, PIX_FMT_NONE, | |||
| // GET_PIX_FMT_NAME, ":") | |||
| #define GET_SAMPLE_FMT_NAME(sample_fmt)\ | |||
| const char *name = av_get_sample_fmt_name(sample_fmt) | |||
| DEF_CHOOSE_FORMAT(enum AVSampleFormat, sample_fmt, sample_fmts, | |||
| AV_SAMPLE_FMT_NONE, GET_SAMPLE_FMT_NAME, ",") | |||
| #define GET_SAMPLE_RATE_NAME(rate)\ | |||
| char name[16];\ | |||
| snprintf(name, sizeof(name), "%d", rate); | |||
| DEF_CHOOSE_FORMAT(int, sample_rate, supported_samplerates, 0, | |||
| GET_SAMPLE_RATE_NAME, ",") | |||
| #define GET_CH_LAYOUT_NAME(ch_layout)\ | |||
| char name[16];\ | |||
| snprintf(name, sizeof(name), "0x%"PRIx64, ch_layout); | |||
| DEF_CHOOSE_FORMAT(uint64_t, channel_layout, channel_layouts, 0, | |||
| GET_CH_LAYOUT_NAME, ",") | |||
| FilterGraph *init_simple_filtergraph(InputStream *ist, OutputStream *ost) | |||
| { | |||
| FilterGraph *fg = av_mallocz(sizeof(*fg)); | |||
| if (!fg) | |||
| exit_program(1); | |||
| fg->index = nb_filtergraphs; | |||
| fg->outputs = grow_array(fg->outputs, sizeof(*fg->outputs), &fg->nb_outputs, | |||
| fg->nb_outputs + 1); | |||
| if (!(fg->outputs[0] = av_mallocz(sizeof(*fg->outputs[0])))) | |||
| exit_program(1); | |||
| fg->outputs[0]->ost = ost; | |||
| fg->outputs[0]->graph = fg; | |||
| ost->filter = fg->outputs[0]; | |||
| fg->inputs = grow_array(fg->inputs, sizeof(*fg->inputs), &fg->nb_inputs, | |||
| fg->nb_inputs + 1); | |||
| if (!(fg->inputs[0] = av_mallocz(sizeof(*fg->inputs[0])))) | |||
| exit_program(1); | |||
| fg->inputs[0]->ist = ist; | |||
| fg->inputs[0]->graph = fg; | |||
| ist->filters = grow_array(ist->filters, sizeof(*ist->filters), | |||
| &ist->nb_filters, ist->nb_filters + 1); | |||
| ist->filters[ist->nb_filters - 1] = fg->inputs[0]; | |||
| filtergraphs = grow_array(filtergraphs, sizeof(*filtergraphs), | |||
| &nb_filtergraphs, nb_filtergraphs + 1); | |||
| filtergraphs[nb_filtergraphs - 1] = fg; | |||
| return fg; | |||
| } | |||
| static void init_input_filter(FilterGraph *fg, AVFilterInOut *in) | |||
| { | |||
| InputStream *ist = NULL; | |||
| enum AVMediaType type = avfilter_pad_get_type(in->filter_ctx->input_pads, in->pad_idx); | |||
| int i; | |||
| // TODO: support other filter types | |||
| if (type != AVMEDIA_TYPE_VIDEO && type != AVMEDIA_TYPE_AUDIO) { | |||
| av_log(NULL, AV_LOG_FATAL, "Only video and audio filters supported " | |||
| "currently.\n"); | |||
| exit_program(1); | |||
| } | |||
| if (in->name) { | |||
| AVFormatContext *s; | |||
| AVStream *st = NULL; | |||
| char *p; | |||
| int file_idx = strtol(in->name, &p, 0); | |||
| if (file_idx < 0 || file_idx >= nb_input_files) { | |||
| av_log(NULL, AV_LOG_FATAL, "Invalid file index %d in filtergraph description %s.\n", | |||
| file_idx, fg->graph_desc); | |||
| exit_program(1); | |||
| } | |||
| s = input_files[file_idx]->ctx; | |||
| for (i = 0; i < s->nb_streams; i++) { | |||
| enum AVMediaType stream_type = s->streams[i]->codec->codec_type; | |||
| if (stream_type != type && | |||
| !(stream_type == AVMEDIA_TYPE_SUBTITLE && | |||
| type == AVMEDIA_TYPE_VIDEO /* sub2video hack */)) | |||
| continue; | |||
| if (check_stream_specifier(s, s->streams[i], *p == ':' ? p + 1 : p) == 1) { | |||
| st = s->streams[i]; | |||
| break; | |||
| } | |||
| } | |||
| if (!st) { | |||
| av_log(NULL, AV_LOG_FATAL, "Stream specifier '%s' in filtergraph description %s " | |||
| "matches no streams.\n", p, fg->graph_desc); | |||
| exit_program(1); | |||
| } | |||
| ist = input_streams[input_files[file_idx]->ist_index + st->index]; | |||
| } else { | |||
| /* find the first unused stream of corresponding type */ | |||
| for (i = 0; i < nb_input_streams; i++) { | |||
| ist = input_streams[i]; | |||
| if (ist->st->codec->codec_type == type && ist->discard) | |||
| break; | |||
| } | |||
| if (i == nb_input_streams) { | |||
| av_log(NULL, AV_LOG_FATAL, "Cannot find a matching stream for " | |||
| "unlabeled input pad %d on filter %s\n", in->pad_idx, | |||
| in->filter_ctx->name); | |||
| exit_program(1); | |||
| } | |||
| } | |||
| av_assert0(ist); | |||
| ist->discard = 0; | |||
| ist->decoding_needed = 1; | |||
| ist->st->discard = AVDISCARD_NONE; | |||
| fg->inputs = grow_array(fg->inputs, sizeof(*fg->inputs), | |||
| &fg->nb_inputs, fg->nb_inputs + 1); | |||
| if (!(fg->inputs[fg->nb_inputs - 1] = av_mallocz(sizeof(*fg->inputs[0])))) | |||
| exit_program(1); | |||
| fg->inputs[fg->nb_inputs - 1]->ist = ist; | |||
| fg->inputs[fg->nb_inputs - 1]->graph = fg; | |||
| ist->filters = grow_array(ist->filters, sizeof(*ist->filters), | |||
| &ist->nb_filters, ist->nb_filters + 1); | |||
| ist->filters[ist->nb_filters - 1] = fg->inputs[fg->nb_inputs - 1]; | |||
| } | |||
| static int configure_output_video_filter(FilterGraph *fg, OutputFilter *ofilter, AVFilterInOut *out) | |||
| { | |||
| char *pix_fmts; | |||
| OutputStream *ost = ofilter->ost; | |||
| AVCodecContext *codec = ost->st->codec; | |||
| AVFilterContext *last_filter = out->filter_ctx; | |||
| int pad_idx = out->pad_idx; | |||
| int ret; | |||
| char name[255]; | |||
| AVBufferSinkParams *buffersink_params = av_buffersink_params_alloc(); | |||
| snprintf(name, sizeof(name), "output stream %d:%d", ost->file_index, ost->index); | |||
| ret = avfilter_graph_create_filter(&ofilter->filter, | |||
| avfilter_get_by_name("buffersink"), | |||
| name, NULL, NULL/*buffersink_params*/, fg->graph); | |||
| av_freep(&buffersink_params); | |||
| if (ret < 0) | |||
| return ret; | |||
| if (codec->width || codec->height) { | |||
| char args[255]; | |||
| AVFilterContext *filter; | |||
| snprintf(args, sizeof(args), "%d:%d:flags=0x%X", | |||
| codec->width, | |||
| codec->height, | |||
| (unsigned)ost->sws_flags); | |||
| snprintf(name, sizeof(name), "scaler for output stream %d:%d", | |||
| ost->file_index, ost->index); | |||
| if ((ret = avfilter_graph_create_filter(&filter, avfilter_get_by_name("scale"), | |||
| name, args, NULL, fg->graph)) < 0) | |||
| return ret; | |||
| if ((ret = avfilter_link(last_filter, pad_idx, filter, 0)) < 0) | |||
| return ret; | |||
| last_filter = filter; | |||
| pad_idx = 0; | |||
| } | |||
| if ((pix_fmts = choose_pix_fmts(ost))) { | |||
| AVFilterContext *filter; | |||
| snprintf(name, sizeof(name), "pixel format for output stream %d:%d", | |||
| ost->file_index, ost->index); | |||
| if ((ret = avfilter_graph_create_filter(&filter, | |||
| avfilter_get_by_name("format"), | |||
| "format", pix_fmts, NULL, | |||
| fg->graph)) < 0) | |||
| return ret; | |||
| if ((ret = avfilter_link(last_filter, pad_idx, filter, 0)) < 0) | |||
| return ret; | |||
| last_filter = filter; | |||
| pad_idx = 0; | |||
| av_freep(&pix_fmts); | |||
| } | |||
| if (ost->frame_rate.num && 0) { | |||
| AVFilterContext *fps; | |||
| char args[255]; | |||
| snprintf(args, sizeof(args), "fps=%d/%d", ost->frame_rate.num, | |||
| ost->frame_rate.den); | |||
| snprintf(name, sizeof(name), "fps for output stream %d:%d", | |||
| ost->file_index, ost->index); | |||
| ret = avfilter_graph_create_filter(&fps, avfilter_get_by_name("fps"), | |||
| name, args, NULL, fg->graph); | |||
| if (ret < 0) | |||
| return ret; | |||
| ret = avfilter_link(last_filter, pad_idx, fps, 0); | |||
| if (ret < 0) | |||
| return ret; | |||
| last_filter = fps; | |||
| pad_idx = 0; | |||
| } | |||
| if ((ret = avfilter_link(last_filter, pad_idx, ofilter->filter, 0)) < 0) | |||
| return ret; | |||
| return 0; | |||
| } | |||
| static int configure_output_audio_filter(FilterGraph *fg, OutputFilter *ofilter, AVFilterInOut *out) | |||
| { | |||
| OutputStream *ost = ofilter->ost; | |||
| AVCodecContext *codec = ost->st->codec; | |||
| AVFilterContext *last_filter = out->filter_ctx; | |||
| int pad_idx = out->pad_idx; | |||
| char *sample_fmts, *sample_rates, *channel_layouts; | |||
| char name[255]; | |||
| int ret; | |||
| snprintf(name, sizeof(name), "output stream %d:%d", ost->file_index, ost->index); | |||
| ret = avfilter_graph_create_filter(&ofilter->filter, | |||
| avfilter_get_by_name("abuffersink"), | |||
| name, NULL, NULL, fg->graph); | |||
| if (ret < 0) | |||
| return ret; | |||
| #define AUTO_INSERT_FILTER(opt_name, filter_name, arg) do { \ | |||
| AVFilterContext *filt_ctx; \ | |||
| \ | |||
| av_log(NULL, AV_LOG_INFO, opt_name " is forwarded to lavfi " \ | |||
| "similarly to -af " filter_name "=%s.\n", arg); \ | |||
| \ | |||
| ret = avfilter_graph_create_filter(&filt_ctx, \ | |||
| avfilter_get_by_name(filter_name), \ | |||
| filter_name, arg, NULL, fg->graph); \ | |||
| if (ret < 0) \ | |||
| return ret; \ | |||
| \ | |||
| ret = avfilter_link(last_filter, pad_idx, filt_ctx, 0); \ | |||
| if (ret < 0) \ | |||
| return ret; \ | |||
| \ | |||
| last_filter = filt_ctx; \ | |||
| pad_idx = 0; \ | |||
| } while (0) | |||
| if (ost->audio_channels_mapped) { | |||
| int i; | |||
| AVBPrint pan_buf; | |||
| av_bprint_init(&pan_buf, 256, 8192); | |||
| av_bprintf(&pan_buf, "0x%"PRIx64, | |||
| av_get_default_channel_layout(ost->audio_channels_mapped)); | |||
| for (i = 0; i < ost->audio_channels_mapped; i++) | |||
| if (ost->audio_channels_map[i] != -1) | |||
| av_bprintf(&pan_buf, ":c%d=c%d", i, ost->audio_channels_map[i]); | |||
| AUTO_INSERT_FILTER("-map_channel", "pan", pan_buf.str); | |||
| av_bprint_finalize(&pan_buf, NULL); | |||
| } | |||
| if (codec->channels && !codec->channel_layout) | |||
| codec->channel_layout = av_get_default_channel_layout(codec->channels); | |||
| sample_fmts = choose_sample_fmts(ost); | |||
| sample_rates = choose_sample_rates(ost); | |||
| channel_layouts = choose_channel_layouts(ost); | |||
| if (sample_fmts || sample_rates || channel_layouts) { | |||
| AVFilterContext *format; | |||
| char args[256]; | |||
| int len = 0; | |||
| if (sample_fmts) | |||
| len += snprintf(args + len, sizeof(args) - len, "sample_fmts=%s:", | |||
| sample_fmts); | |||
| if (sample_rates) | |||
| len += snprintf(args + len, sizeof(args) - len, "sample_rates=%s:", | |||
| sample_rates); | |||
| if (channel_layouts) | |||
| len += snprintf(args + len, sizeof(args) - len, "channel_layouts=%s:", | |||
| channel_layouts); | |||
| args[len - 1] = 0; | |||
| av_freep(&sample_fmts); | |||
| av_freep(&sample_rates); | |||
| av_freep(&channel_layouts); | |||
| snprintf(name, sizeof(name), "audio format for output stream %d:%d", | |||
| ost->file_index, ost->index); | |||
| ret = avfilter_graph_create_filter(&format, | |||
| avfilter_get_by_name("aformat"), | |||
| name, args, NULL, fg->graph); | |||
| if (ret < 0) | |||
| return ret; | |||
| ret = avfilter_link(last_filter, pad_idx, format, 0); | |||
| if (ret < 0) | |||
| return ret; | |||
| last_filter = format; | |||
| pad_idx = 0; | |||
| } | |||
| if (audio_volume != 256 && 0) { | |||
| char args[256]; | |||
| snprintf(args, sizeof(args), "%f", audio_volume / 256.); | |||
| AUTO_INSERT_FILTER("-vol", "volume", args); | |||
| } | |||
| if ((ret = avfilter_link(last_filter, pad_idx, ofilter->filter, 0)) < 0) | |||
| return ret; | |||
| return 0; | |||
| } | |||
| #define DESCRIBE_FILTER_LINK(f, inout, in) \ | |||
| { \ | |||
| AVFilterContext *ctx = inout->filter_ctx; \ | |||
| AVFilterPad *pads = in ? ctx->input_pads : ctx->output_pads; \ | |||
| int nb_pads = in ? ctx->input_count : ctx->output_count; \ | |||
| AVIOContext *pb; \ | |||
| \ | |||
| if (avio_open_dyn_buf(&pb) < 0) \ | |||
| exit_program(1); \ | |||
| \ | |||
| avio_printf(pb, "%s", ctx->filter->name); \ | |||
| if (nb_pads > 1) \ | |||
| avio_printf(pb, ":%s", avfilter_pad_get_name(pads, inout->pad_idx));\ | |||
| avio_w8(pb, 0); \ | |||
| avio_close_dyn_buf(pb, &f->name); \ | |||
| } | |||
| int configure_output_filter(FilterGraph *fg, OutputFilter *ofilter, AVFilterInOut *out) | |||
| { | |||
| av_freep(&ofilter->name); | |||
| DESCRIBE_FILTER_LINK(ofilter, out, 0); | |||
| switch (avfilter_pad_get_type(out->filter_ctx->output_pads, out->pad_idx)) { | |||
| case AVMEDIA_TYPE_VIDEO: return configure_output_video_filter(fg, ofilter, out); | |||
| case AVMEDIA_TYPE_AUDIO: return configure_output_audio_filter(fg, ofilter, out); | |||
| default: av_assert0(0); | |||
| } | |||
| } | |||
| static int sub2video_prepare(InputStream *ist) | |||
| { | |||
| AVFormatContext *avf = input_files[ist->file_index]->ctx; | |||
| int i, ret, w, h; | |||
| uint8_t *image[4]; | |||
| int linesize[4]; | |||
| /* Compute the size of the canvas for the subtitles stream. | |||
| If the subtitles codec has set a size, use it. Otherwise use the | |||
| maximum dimensions of the video streams in the same file. */ | |||
| w = ist->st->codec->width; | |||
| h = ist->st->codec->height; | |||
| if (!(w && h)) { | |||
| for (i = 0; i < avf->nb_streams; i++) { | |||
| if (avf->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { | |||
| w = FFMAX(w, avf->streams[i]->codec->width); | |||
| h = FFMAX(h, avf->streams[i]->codec->height); | |||
| } | |||
| } | |||
| if (!(w && h)) { | |||
| w = FFMAX(w, 720); | |||
| h = FFMAX(h, 576); | |||
| } | |||
| av_log(avf, AV_LOG_INFO, "sub2video: using %dx%d canvas\n", w, h); | |||
| } | |||
| ist->sub2video.w = ist->st->codec->width = w; | |||
| ist->sub2video.h = ist->st->codec->height = h; | |||
| /* rectangles are PIX_FMT_PAL8, but we have no guarantee that the | |||
| palettes for all rectangles are identical or compatible */ | |||
| ist->st->codec->pix_fmt = PIX_FMT_RGB32; | |||
| ret = av_image_alloc(image, linesize, w, h, PIX_FMT_RGB32, 32); | |||
| if (ret < 0) | |||
| return ret; | |||
| memset(image[0], 0, h * linesize[0]); | |||
| ist->sub2video.ref = avfilter_get_video_buffer_ref_from_arrays( | |||
| image, linesize, AV_PERM_READ | AV_PERM_PRESERVE, | |||
| w, h, PIX_FMT_RGB32); | |||
| if (!ist->sub2video.ref) { | |||
| av_free(image[0]); | |||
| return AVERROR(ENOMEM); | |||
| } | |||
| return 0; | |||
| } | |||
| static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter, | |||
| AVFilterInOut *in) | |||
| { | |||
| AVFilterContext *first_filter = in->filter_ctx; | |||
| AVFilter *filter = avfilter_get_by_name("buffer"); | |||
| InputStream *ist = ifilter->ist; | |||
| AVRational tb = ist->framerate.num ? av_inv_q(ist->framerate) : | |||
| ist->st->time_base; | |||
| AVRational fr = ist->framerate.num ? ist->framerate : | |||
| ist->st->r_frame_rate; | |||
| AVRational sar; | |||
| AVBPrint args; | |||
| char name[255]; | |||
| int pad_idx = in->pad_idx; | |||
| int ret; | |||
| if (ist->st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) { | |||
| ret = sub2video_prepare(ist); | |||
| if (ret < 0) | |||
| return ret; | |||
| } | |||
| sar = ist->st->sample_aspect_ratio.num ? | |||
| ist->st->sample_aspect_ratio : | |||
| ist->st->codec->sample_aspect_ratio; | |||
| if(!sar.den) | |||
| sar = (AVRational){0,1}; | |||
| av_bprint_init(&args, 0, 1); | |||
| av_bprintf(&args, | |||
| "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:" | |||
| "pixel_aspect=%d/%d:sws_param=flags=%d", ist->st->codec->width, | |||
| ist->st->codec->height, ist->st->codec->pix_fmt, | |||
| tb.num, tb.den, sar.num, sar.den, | |||
| SWS_BILINEAR + ((ist->st->codec->flags&CODEC_FLAG_BITEXACT) ? SWS_BITEXACT:0)); | |||
| if (fr.num && fr.den) | |||
| av_bprintf(&args, ":frame_rate=%d/%d", fr.num, fr.den); | |||
| snprintf(name, sizeof(name), "graph %d input from stream %d:%d", fg->index, | |||
| ist->file_index, ist->st->index); | |||
| if ((ret = avfilter_graph_create_filter(&ifilter->filter, filter, name, | |||
| args.str, NULL, fg->graph)) < 0) | |||
| return ret; | |||
| if (ist->framerate.num) { | |||
| AVFilterContext *setpts; | |||
| snprintf(name, sizeof(name), "force CFR for input from stream %d:%d", | |||
| ist->file_index, ist->st->index); | |||
| if ((ret = avfilter_graph_create_filter(&setpts, | |||
| avfilter_get_by_name("setpts"), | |||
| name, "N", NULL, | |||
| fg->graph)) < 0) | |||
| return ret; | |||
| if ((ret = avfilter_link(setpts, 0, first_filter, pad_idx)) < 0) | |||
| return ret; | |||
| first_filter = setpts; | |||
| pad_idx = 0; | |||
| } | |||
| if ((ret = avfilter_link(ifilter->filter, 0, first_filter, pad_idx)) < 0) | |||
| return ret; | |||
| return 0; | |||
| } | |||
| static int configure_input_audio_filter(FilterGraph *fg, InputFilter *ifilter, | |||
| AVFilterInOut *in) | |||
| { | |||
| AVFilterContext *first_filter = in->filter_ctx; | |||
| AVFilter *filter = avfilter_get_by_name("abuffer"); | |||
| InputStream *ist = ifilter->ist; | |||
| int pad_idx = in->pad_idx; | |||
| char args[255], name[255]; | |||
| int ret; | |||
| snprintf(args, sizeof(args), "time_base=%d/%d:sample_rate=%d:sample_fmt=%s" | |||
| ":channel_layout=0x%"PRIx64, | |||
| 1, ist->st->codec->sample_rate, | |||
| ist->st->codec->sample_rate, | |||
| av_get_sample_fmt_name(ist->st->codec->sample_fmt), | |||
| ist->st->codec->channel_layout); | |||
| snprintf(name, sizeof(name), "graph %d input from stream %d:%d", fg->index, | |||
| ist->file_index, ist->st->index); | |||
| if ((ret = avfilter_graph_create_filter(&ifilter->filter, filter, | |||
| name, args, NULL, | |||
| fg->graph)) < 0) | |||
| return ret; | |||
| #define AUTO_INSERT_FILTER_INPUT(opt_name, filter_name, arg) do { \ | |||
| AVFilterContext *filt_ctx; \ | |||
| \ | |||
| av_log(NULL, AV_LOG_INFO, opt_name " is forwarded to lavfi " \ | |||
| "similarly to -af " filter_name "=%s.\n", arg); \ | |||
| \ | |||
| snprintf(name, sizeof(name), "graph %d %s for input stream %d:%d", \ | |||
| fg->index, filter_name, ist->file_index, ist->st->index); \ | |||
| ret = avfilter_graph_create_filter(&filt_ctx, \ | |||
| avfilter_get_by_name(filter_name), \ | |||
| name, arg, NULL, fg->graph); \ | |||
| if (ret < 0) \ | |||
| return ret; \ | |||
| \ | |||
| ret = avfilter_link(filt_ctx, 0, first_filter, pad_idx); \ | |||
| if (ret < 0) \ | |||
| return ret; \ | |||
| \ | |||
| first_filter = filt_ctx; \ | |||
| } while (0) | |||
| if (audio_sync_method > 0) { | |||
| char args[256] = {0}; | |||
| av_strlcatf(args, sizeof(args), "min_comp=0.001:min_hard_comp=%f", audio_drift_threshold); | |||
| if (audio_sync_method > 1) | |||
| av_strlcatf(args, sizeof(args), ":max_soft_comp=%f", audio_sync_method/(double)ist->st->codec->sample_rate); | |||
| AUTO_INSERT_FILTER_INPUT("-async", "aresample", args); | |||
| } | |||
| // if (ost->audio_channels_mapped) { | |||
| // int i; | |||
| // AVBPrint pan_buf; | |||
| // av_bprint_init(&pan_buf, 256, 8192); | |||
| // av_bprintf(&pan_buf, "0x%"PRIx64, | |||
| // av_get_default_channel_layout(ost->audio_channels_mapped)); | |||
| // for (i = 0; i < ost->audio_channels_mapped; i++) | |||
| // if (ost->audio_channels_map[i] != -1) | |||
| // av_bprintf(&pan_buf, ":c%d=c%d", i, ost->audio_channels_map[i]); | |||
| // AUTO_INSERT_FILTER_INPUT("-map_channel", "pan", pan_buf.str); | |||
| // av_bprint_finalize(&pan_buf, NULL); | |||
| // } | |||
| if (audio_volume != 256) { | |||
| char args[256]; | |||
| snprintf(args, sizeof(args), "%f", audio_volume / 256.); | |||
| AUTO_INSERT_FILTER_INPUT("-vol", "volume", args); | |||
| } | |||
| if ((ret = avfilter_link(ifilter->filter, 0, first_filter, pad_idx)) < 0) | |||
| return ret; | |||
| return 0; | |||
| } | |||
| static int configure_input_filter(FilterGraph *fg, InputFilter *ifilter, | |||
| AVFilterInOut *in) | |||
| { | |||
| av_freep(&ifilter->name); | |||
| DESCRIBE_FILTER_LINK(ifilter, in, 1); | |||
| switch (avfilter_pad_get_type(in->filter_ctx->input_pads, in->pad_idx)) { | |||
| case AVMEDIA_TYPE_VIDEO: return configure_input_video_filter(fg, ifilter, in); | |||
| case AVMEDIA_TYPE_AUDIO: return configure_input_audio_filter(fg, ifilter, in); | |||
| default: av_assert0(0); | |||
| } | |||
| } | |||
| int configure_filtergraph(FilterGraph *fg) | |||
| { | |||
| AVFilterInOut *inputs, *outputs, *cur; | |||
| int ret, i, init = !fg->graph, simple = !fg->graph_desc; | |||
| const char *graph_desc = simple ? fg->outputs[0]->ost->avfilter : | |||
| fg->graph_desc; | |||
| avfilter_graph_free(&fg->graph); | |||
| if (!(fg->graph = avfilter_graph_alloc())) | |||
| return AVERROR(ENOMEM); | |||
| if (simple) { | |||
| OutputStream *ost = fg->outputs[0]->ost; | |||
| char args[255]; | |||
| snprintf(args, sizeof(args), "flags=0x%X", (unsigned)ost->sws_flags); | |||
| fg->graph->scale_sws_opts = av_strdup(args); | |||
| } | |||
| if ((ret = avfilter_graph_parse2(fg->graph, graph_desc, &inputs, &outputs)) < 0) | |||
| return ret; | |||
| if (simple && (!inputs || inputs->next || !outputs || outputs->next)) { | |||
| av_log(NULL, AV_LOG_ERROR, "Simple filtergraph '%s' does not have " | |||
| "exactly one input and output.\n", graph_desc); | |||
| return AVERROR(EINVAL); | |||
| } | |||
| for (cur = inputs; !simple && init && cur; cur = cur->next) | |||
| init_input_filter(fg, cur); | |||
| for (cur = inputs, i = 0; cur; cur = cur->next, i++) | |||
| if ((ret = configure_input_filter(fg, fg->inputs[i], cur)) < 0) | |||
| return ret; | |||
| avfilter_inout_free(&inputs); | |||
| if (!init || simple) { | |||
| /* we already know the mappings between lavfi outputs and output streams, | |||
| * so we can finish the setup */ | |||
| for (cur = outputs, i = 0; cur; cur = cur->next, i++) | |||
| configure_output_filter(fg, fg->outputs[i], cur); | |||
| avfilter_inout_free(&outputs); | |||
| if ((ret = avfilter_graph_config(fg->graph, NULL)) < 0) | |||
| return ret; | |||
| } else { | |||
| /* wait until output mappings are processed */ | |||
| for (cur = outputs; cur;) { | |||
| fg->outputs = grow_array(fg->outputs, sizeof(*fg->outputs), | |||
| &fg->nb_outputs, fg->nb_outputs + 1); | |||
| if (!(fg->outputs[fg->nb_outputs - 1] = av_mallocz(sizeof(*fg->outputs[0])))) | |||
| exit_program(1); | |||
| fg->outputs[fg->nb_outputs - 1]->graph = fg; | |||
| fg->outputs[fg->nb_outputs - 1]->out_tmp = cur; | |||
| cur = cur->next; | |||
| fg->outputs[fg->nb_outputs - 1]->out_tmp->next = NULL; | |||
| } | |||
| } | |||
| return 0; | |||
| } | |||
| int ist_in_filtergraph(FilterGraph *fg, InputStream *ist) | |||
| { | |||
| int i; | |||
| for (i = 0; i < fg->nb_inputs; i++) | |||
| if (fg->inputs[i]->ist == ist) | |||
| return 1; | |||
| return 0; | |||
| } | |||
| @@ -264,6 +264,7 @@ static int scale_vector(int16_t *vector, int length) | |||
| for (i = 0; i < length; i++) | |||
| max = FFMAX(max, FFABS(vector[i])); | |||
| max = FFMIN(max, 0x7FFF); | |||
| bits = normalize_bits(max, 15); | |||
| scale = shift_table[bits]; | |||
| @@ -913,6 +914,7 @@ static void formant_postfilter(G723_1_Context *p, int16_t *lpc, int16_t *buf) | |||
| } | |||
| iir_filter(filter_coef[0], filter_coef[1], buf + i, | |||
| filter_signal + i, 1); | |||
| lpc += LPC_ORDER; | |||
| } | |||
| memcpy(p->fir_mem, buf + FRAME_LEN, LPC_ORDER * sizeof(int16_t)); | |||
| @@ -419,6 +419,8 @@ static int mpc8_decode_frame(AVCodecContext * avctx, void *data, | |||
| c->cur_frame++; | |||
| c->last_bits_used = get_bits_count(gb); | |||
| if(get_bits_left(gb) < 8) // we have only padding left | |||
| c->last_bits_used = buf_size << 3; | |||
| if(c->cur_frame >= c->frames) | |||
| c->cur_frame = 0; | |||
| @@ -1686,7 +1686,7 @@ static int decode_frame(AVCodecContext * avctx, void *data, int *got_frame_ptr, | |||
| if (s->frame_size <= 0 || s->frame_size > buf_size) { | |||
| av_log(avctx, AV_LOG_ERROR, "incomplete frame\n"); | |||
| return AVERROR_INVALIDDATA; | |||
| }else if(s->frame_size < buf_size){ | |||
| } else if (s->frame_size < buf_size) { | |||
| av_log(avctx, AV_LOG_DEBUG, "incorrect frame size - multiple frames in buffer?\n"); | |||
| buf_size= s->frame_size; | |||
| } | |||
| @@ -24,6 +24,8 @@ | |||
| * The simplest mpeg audio layer 2 encoder. | |||
| */ | |||
| #include "libavutil/audioconvert.h" | |||
| #include "avcodec.h" | |||
| #include "internal.h" | |||
| #include "put_bits.h" | |||
| @@ -792,6 +794,9 @@ AVCodec ff_mp2_encoder = { | |||
| .supported_samplerates = (const int[]){ | |||
| 44100, 48000, 32000, 22050, 24000, 16000, 0 | |||
| }, | |||
| .channel_layouts = (const uint64_t[]){ AV_CH_LAYOUT_MONO, | |||
| AV_CH_LAYOUT_STEREO, | |||
| 0 }, | |||
| .long_name = NULL_IF_CONFIG_SMALL("MP2 (MPEG audio layer 2)"), | |||
| .defaults = mp2_defaults, | |||
| }; | |||
| @@ -28,7 +28,7 @@ SECTION_RODATA | |||
| cextern pw_255 | |||
| SECTION_TEXT 16 | |||
| SECTION_TEXT | |||
| ; %1 = nr. of xmm registers used | |||
| %macro ADD_BYTES_FN 1 | |||
| @@ -131,6 +131,8 @@ const CodecMime ff_id3v2_mime_tags[] = { | |||
| {"image/png" , AV_CODEC_ID_PNG}, | |||
| {"image/tiff", AV_CODEC_ID_TIFF}, | |||
| {"image/bmp", AV_CODEC_ID_BMP}, | |||
| {"JPG", AV_CODEC_ID_MJPEG}, /* ID3v2.2 */ | |||
| {"PNG" , AV_CODEC_ID_PNG}, /* ID3v2.2 */ | |||
| {"", AV_CODEC_ID_NONE}, | |||
| }; | |||
| @@ -32,6 +32,15 @@ | |||
| #define HMAC_IPAD_VAL 0x36 | |||
| #define HMAC_OPAD_VAL 0x5C | |||
| /** | |||
| * A non-zero transaction id requires the server to send back | |||
| * a _result or _error response. | |||
| * Setting it to 0 marks the message as a notification not | |||
| * requiring feedback. | |||
| */ | |||
| #define RTMP_NOTIFICATION 0 | |||
| /** | |||
| * emulated Flash client version - 9.0.124.2 on Linux | |||
| * @{ | |||
| @@ -91,6 +91,7 @@ typedef struct RTMPContext { | |||
| char* flashver; ///< version of the flash plugin | |||
| char* swfurl; ///< url of the swf player | |||
| char* pageurl; ///< url of the web page | |||
| char* subscribe; ///< name of live stream to subscribe | |||
| int server_bw; ///< server bandwidth | |||
| int client_buffer_time; ///< client buffer time in ms | |||
| int flush_interval; ///< number of packets flushed in the same request (RTMPT only) | |||
| @@ -572,7 +573,7 @@ static int gen_check_bw(URLContext *s, RTMPContext *rt) | |||
| p = pkt.data; | |||
| ff_amf_write_string(&p, "_checkbw"); | |||
| ff_amf_write_number(&p, ++rt->nb_invokes); | |||
| ff_amf_write_number(&p, RTMP_NOTIFICATION); | |||
| ff_amf_write_null(&p); | |||
| ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, | |||
| @@ -604,6 +605,30 @@ static int gen_bytes_read(URLContext *s, RTMPContext *rt, uint32_t ts) | |||
| return ret; | |||
| } | |||
| static int gen_fcsubscribe_stream(URLContext *s, RTMPContext *rt, | |||
| const char *subscribe) | |||
| { | |||
| RTMPPacket pkt; | |||
| uint8_t *p; | |||
| int ret; | |||
| if ((ret = ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE, | |||
| 0, 27 + strlen(subscribe))) < 0) | |||
| return ret; | |||
| p = pkt.data; | |||
| ff_amf_write_string(&p, "FCSubscribe"); | |||
| ff_amf_write_number(&p, ++rt->nb_invokes); | |||
| ff_amf_write_null(&p); | |||
| ff_amf_write_string(&p, subscribe); | |||
| ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, | |||
| rt->prev_pkt[1]); | |||
| ff_rtmp_packet_destroy(&pkt); | |||
| return ret; | |||
| } | |||
| int ff_rtmp_calc_digest(const uint8_t *src, int len, int gap, | |||
| const uint8_t *key, int keylen, uint8_t *dst) | |||
| { | |||
| @@ -1011,6 +1036,20 @@ static int handle_invoke(URLContext *s, RTMPPacket *pkt) | |||
| } | |||
| if ((ret = gen_create_stream(s, rt)) < 0) | |||
| return ret; | |||
| if (rt->is_input) { | |||
| /* Send the FCSubscribe command when the name of live | |||
| * stream is defined by the user or if it's a live stream. */ | |||
| if (rt->subscribe) { | |||
| if ((ret = gen_fcsubscribe_stream(s, rt, | |||
| rt->subscribe)) < 0) | |||
| return ret; | |||
| } else if (rt->live == -1) { | |||
| if ((ret = gen_fcsubscribe_stream(s, rt, | |||
| rt->playpath)) < 0) | |||
| return ret; | |||
| } | |||
| } | |||
| break; | |||
| case STATE_FCPUBLISH: | |||
| rt->state = STATE_CONNECTING; | |||
| @@ -1593,115 +1632,35 @@ static const AVOption rtmp_options[] = { | |||
| {"recorded", "recorded stream", 0, AV_OPT_TYPE_CONST, {0}, 0, 0, DEC, "rtmp_live"}, | |||
| {"rtmp_pageurl", "URL of the web page in which the media was embedded. By default no value will be sent.", OFFSET(pageurl), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC}, | |||
| {"rtmp_playpath", "Stream identifier to play or to publish", OFFSET(playpath), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC}, | |||
| {"rtmp_subscribe", "Name of live stream to subscribe to. Defaults to rtmp_playpath.", OFFSET(subscribe), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC}, | |||
| {"rtmp_swfurl", "URL of the SWF player. By default no value will be sent", OFFSET(swfurl), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC}, | |||
| {"rtmp_tcurl", "URL of the target stream. Defaults to proto://host[:port]/app.", OFFSET(tcurl), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC}, | |||
| { NULL }, | |||
| }; | |||
| static const AVClass rtmp_class = { | |||
| .class_name = "rtmp", | |||
| .item_name = av_default_item_name, | |||
| .option = rtmp_options, | |||
| .version = LIBAVUTIL_VERSION_INT, | |||
| }; | |||
| URLProtocol ff_rtmp_protocol = { | |||
| .name = "rtmp", | |||
| .url_open = rtmp_open, | |||
| .url_read = rtmp_read, | |||
| .url_write = rtmp_write, | |||
| .url_close = rtmp_close, | |||
| .priv_data_size = sizeof(RTMPContext), | |||
| .flags = URL_PROTOCOL_FLAG_NETWORK, | |||
| .priv_data_class= &rtmp_class, | |||
| #define RTMP_PROTOCOL(flavor) \ | |||
| static const AVClass flavor##_class = { \ | |||
| .class_name = #flavor, \ | |||
| .item_name = av_default_item_name, \ | |||
| .option = rtmp_options, \ | |||
| .version = LIBAVUTIL_VERSION_INT, \ | |||
| }; \ | |||
| \ | |||
| URLProtocol ff_##flavor##_protocol = { \ | |||
| .name = #flavor, \ | |||
| .url_open = rtmp_open, \ | |||
| .url_read = rtmp_read, \ | |||
| .url_write = rtmp_write, \ | |||
| .url_close = rtmp_close, \ | |||
| .priv_data_size = sizeof(RTMPContext), \ | |||
| .flags = URL_PROTOCOL_FLAG_NETWORK, \ | |||
| .priv_data_class= &flavor##_class, \ | |||
| }; | |||
| static const AVClass rtmpe_class = { | |||
| .class_name = "rtmpe", | |||
| .item_name = av_default_item_name, | |||
| .option = rtmp_options, | |||
| .version = LIBAVUTIL_VERSION_INT, | |||
| }; | |||
| URLProtocol ff_rtmpe_protocol = { | |||
| .name = "rtmpe", | |||
| .url_open = rtmp_open, | |||
| .url_read = rtmp_read, | |||
| .url_write = rtmp_write, | |||
| .url_close = rtmp_close, | |||
| .priv_data_size = sizeof(RTMPContext), | |||
| .flags = URL_PROTOCOL_FLAG_NETWORK, | |||
| .priv_data_class = &rtmpe_class, | |||
| }; | |||
| static const AVClass rtmps_class = { | |||
| .class_name = "rtmps", | |||
| .item_name = av_default_item_name, | |||
| .option = rtmp_options, | |||
| .version = LIBAVUTIL_VERSION_INT, | |||
| }; | |||
| URLProtocol ff_rtmps_protocol = { | |||
| .name = "rtmps", | |||
| .url_open = rtmp_open, | |||
| .url_read = rtmp_read, | |||
| .url_write = rtmp_write, | |||
| .url_close = rtmp_close, | |||
| .priv_data_size = sizeof(RTMPContext), | |||
| .flags = URL_PROTOCOL_FLAG_NETWORK, | |||
| .priv_data_class = &rtmps_class, | |||
| }; | |||
| static const AVClass rtmpt_class = { | |||
| .class_name = "rtmpt", | |||
| .item_name = av_default_item_name, | |||
| .option = rtmp_options, | |||
| .version = LIBAVUTIL_VERSION_INT, | |||
| }; | |||
| URLProtocol ff_rtmpt_protocol = { | |||
| .name = "rtmpt", | |||
| .url_open = rtmp_open, | |||
| .url_read = rtmp_read, | |||
| .url_write = rtmp_write, | |||
| .url_close = rtmp_close, | |||
| .priv_data_size = sizeof(RTMPContext), | |||
| .flags = URL_PROTOCOL_FLAG_NETWORK, | |||
| .priv_data_class = &rtmpt_class, | |||
| }; | |||
| static const AVClass rtmpte_class = { | |||
| .class_name = "rtmpte", | |||
| .item_name = av_default_item_name, | |||
| .option = rtmp_options, | |||
| .version = LIBAVUTIL_VERSION_INT, | |||
| }; | |||
| URLProtocol ff_rtmpte_protocol = { | |||
| .name = "rtmpte", | |||
| .url_open = rtmp_open, | |||
| .url_read = rtmp_read, | |||
| .url_write = rtmp_write, | |||
| .url_close = rtmp_close, | |||
| .priv_data_size = sizeof(RTMPContext), | |||
| .flags = URL_PROTOCOL_FLAG_NETWORK, | |||
| .priv_data_class = &rtmpte_class, | |||
| }; | |||
| static const AVClass rtmpts_class = { | |||
| .class_name = "rtmpts", | |||
| .item_name = av_default_item_name, | |||
| .option = rtmp_options, | |||
| .version = LIBAVUTIL_VERSION_INT, | |||
| }; | |||
| URLProtocol ff_rtmpts_protocol = { | |||
| .name = "rtmpts", | |||
| .url_open = rtmp_open, | |||
| .url_read = rtmp_read, | |||
| .url_write = rtmp_write, | |||
| .url_close = rtmp_close, | |||
| .priv_data_size = sizeof(RTMPContext), | |||
| .flags = URL_PROTOCOL_FLAG_NETWORK, | |||
| .priv_data_class = &rtmpts_class, | |||
| }; | |||
| RTMP_PROTOCOL(rtmp) | |||
| RTMP_PROTOCOL(rtmpe) | |||
| RTMP_PROTOCOL(rtmps) | |||
| RTMP_PROTOCOL(rtmpt) | |||
| RTMP_PROTOCOL(rtmpte) | |||
| RTMP_PROTOCOL(rtmpts) | |||
| @@ -31,7 +31,7 @@ | |||
| #define LIBAVFORMAT_VERSION_MAJOR 54 | |||
| #define LIBAVFORMAT_VERSION_MINOR 22 | |||
| #define LIBAVFORMAT_VERSION_MICRO 102 | |||
| #define LIBAVFORMAT_VERSION_MICRO 103 | |||
| #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ | |||
| LIBAVFORMAT_VERSION_MINOR, \ | |||
| @@ -97,6 +97,8 @@ static av_always_inline av_const int FASTDIV(int a, int b) | |||
| #endif /* HAVE_ARMV6 */ | |||
| #if HAVE_ASM_MOD_Q | |||
| #define av_clipl_int32 av_clipl_int32_arm | |||
| static av_always_inline av_const int32_t av_clipl_int32_arm(int64_t a) | |||
| { | |||
| @@ -110,6 +112,8 @@ static av_always_inline av_const int32_t av_clipl_int32_arm(int64_t a) | |||
| return x; | |||
| } | |||
| #endif /* HAVE_ASM_MOD_Q */ | |||
| #endif /* HAVE_INLINE_ASM */ | |||
| #endif /* AVUTIL_ARM_INTMATH_H */ | |||
| @@ -61,6 +61,8 @@ static av_always_inline void AV_WN32(void *p, uint32_t v) | |||
| __asm__ ("str %1, %0" : "=m"(*(uint32_t *)p) : "r"(v)); | |||
| } | |||
| #if HAVE_ASM_MOD_Q | |||
| #define AV_RN64 AV_RN64 | |||
| static av_always_inline uint64_t AV_RN64(const void *p) | |||
| { | |||
| @@ -82,6 +84,8 @@ static av_always_inline void AV_WN64(void *p, uint64_t v) | |||
| : "r"(v)); | |||
| } | |||
| #endif /* HAVE_ASM_MOD_Q */ | |||
| #endif /* HAVE_INLINE_ASM */ | |||
| #endif /* AVUTIL_ARM_INTREADWRITE_H */ | |||
| @@ -20,7 +20,7 @@ $(SUBDIR)x86/%.o: $(SUBDIR)x86/%.asm | |||
| $(DEPYASM) $(YASMFLAGS) -I $(<D)/ -M -o $@ $< > $(@:.o=.d) | |||
| $(YASM) $(YASMFLAGS) -I $(<D)/ -o $@ $< | |||
| $(OBJS) $(OBJS:.o=.s) $(SUBDIR)%.ho $(TESTOBJS): CPPFLAGS += -DHAVE_AV_CONFIG_H | |||
| $(OBJS) $(OBJS:.o=.s) $(SUBDIR)%.h.o $(TESTOBJS): CPPFLAGS += -DHAVE_AV_CONFIG_H | |||
| $(TESTOBJS): CPPFLAGS += -DTEST | |||
| $(SUBDIR)$(LIBNAME): $(OBJS) | |||
| @@ -87,7 +87,7 @@ uninstall-libs:: | |||
| -$(RM) "$(LIBDIR)/$(LIBNAME)" | |||
| uninstall-headers:: | |||
| $(RM) $(addprefix "$(INCINSTDIR)/",$(HEADERS)) $(addprefix "$(INCINSTDIR)/",$(BUILT_HEADERS)) | |||
| $(RM) $(addprefix "$(INCINSTDIR)/",$(HEADERS) $(BUILT_HEADERS)) | |||
| $(RM) "$(LIBDIR)/pkgconfig/lib$(NAME).pc" | |||
| -rmdir "$(INCINSTDIR)" | |||
| endef | |||
| @@ -167,8 +167,14 @@ FATE_VIDEO += fate-mpeg2-field-enc | |||
| fate-mpeg2-field-enc: CMD = framecrc -flags +bitexact -dct fastint -idct simple -i $(SAMPLES)/mpeg2/mpeg2_field_encoding.ts -an | |||
| # FIXME dropped frames in this test because of coarse timebase | |||
| FATE_VIDEO += fate-nuv | |||
| fate-nuv: CMD = framecrc -idct simple -i $(SAMPLES)/nuv/Today.nuv -an | |||
| FATE_NUV += fate-nuv-rtjpeg | |||
| fate-nuv-rtjpeg: CMD = framecrc -idct simple -i $(SAMPLES)/nuv/Today.nuv -an | |||
| FATE_NUV += fate-nuv-rtjpeg-fh | |||
| fate-nuv-rtjpeg-fh: CMD = framecrc -idct simple -i $(SAMPLES)/nuv/rtjpeg_frameheader.nuv -an | |||
| FATE_VIDEO += $(FATE_NUV) | |||
| fate-nuv: $(FATE_NUV) | |||
| FATE_VIDEO += fate-paf-video | |||
| fate-paf-video: CMD = framecrc -i $(SAMPLES)/paf/hod1-partial.paf -pix_fmt rgb24 -an | |||
| @@ -1,4 +1,4 @@ | |||
| dec0deb2425e908d232d2471acff04a3 *tests/data/fate/acodec-g723_1.g723_1 | |||
| 4800 tests/data/fate/acodec-g723_1.g723_1 | |||
| 87fd529c9e41914f73a865d147cc9516 *tests/data/fate/acodec-g723_1.out.wav | |||
| stddev: 8425.98 PSNR: 17.82 MAXDIFF:53268 bytes: 95992/ 96000 | |||
| d70776846d77c652bceed281fcca9cc8 *tests/data/fate/acodec-g723_1.out.wav | |||
| stddev: 8423.47 PSNR: 17.82 MAXDIFF:53292 bytes: 95992/ 96000 | |||
| @@ -0,0 +1,51 @@ | |||
| #tb 0: 1/50 | |||
| 0, 0, 0, 1, 221184, 0xf48c94f6 | |||
| 0, 2, 2, 1, 221184, 0x89b625b2 | |||
| 0, 3, 3, 1, 221184, 0x37e04714 | |||
| 0, 4, 4, 1, 221184, 0x4f4c5224 | |||
| 0, 5, 5, 1, 221184, 0x9193c9f1 | |||
| 0, 6, 6, 1, 221184, 0x5d1a6197 | |||
| 0, 7, 7, 1, 221184, 0x40cd51e7 | |||
| 0, 8, 8, 1, 221184, 0xb2c1a729 | |||
| 0, 10, 10, 1, 221184, 0x998d6144 | |||
| 0, 11, 11, 1, 221184, 0xf5d52311 | |||
| 0, 12, 12, 1, 221184, 0xea9dd6bf | |||
| 0, 13, 13, 1, 221184, 0x0e2ed854 | |||
| 0, 14, 14, 1, 221184, 0xe295ba58 | |||
| 0, 15, 15, 1, 221184, 0x8aedbb69 | |||
| 0, 16, 16, 1, 221184, 0x253c9aaa | |||
| 0, 17, 17, 1, 221184, 0x5eaf9fb1 | |||
| 0, 18, 18, 1, 221184, 0xcdb5a0cb | |||
| 0, 19, 19, 1, 221184, 0xcdb5a0cb | |||
| 0, 20, 20, 1, 221184, 0x23f89994 | |||
| 0, 21, 21, 1, 221184, 0x23f89994 | |||
| 0, 22, 22, 1, 221184, 0x10dc98d6 | |||
| 0, 23, 23, 1, 221184, 0x799b9d98 | |||
| 0, 24, 24, 1, 221184, 0xb226996c | |||
| 0, 25, 25, 1, 221184, 0x0ac59a42 | |||
| 0, 26, 26, 1, 221184, 0x87c2a654 | |||
| 0, 27, 27, 1, 221184, 0xf4c1a711 | |||
| 0, 28, 28, 1, 221184, 0xf60fa72e | |||
| 0, 29, 29, 1, 221184, 0xc8f8b6fc | |||
| 0, 30, 30, 1, 221184, 0xd709b813 | |||
| 0, 31, 31, 1, 221184, 0x5fdfb76b | |||
| 0, 32, 32, 1, 221184, 0x5798b0aa | |||
| 0, 33, 33, 1, 221184, 0xf572b1c3 | |||
| 0, 34, 34, 1, 221184, 0x14b0afdf | |||
| 0, 35, 35, 1, 221184, 0x0a66b5b8 | |||
| 0, 36, 36, 1, 221184, 0xe316c620 | |||
| 0, 37, 37, 1, 221184, 0xbc76c5c2 | |||
| 0, 38, 38, 1, 221184, 0x77c7c5e5 | |||
| 0, 39, 39, 1, 221184, 0xfc7ac63e | |||
| 0, 40, 40, 1, 221184, 0x05a29ffe | |||
| 0, 41, 41, 1, 221184, 0x9bffbf6c | |||
| 0, 42, 42, 1, 221184, 0x3c55be40 | |||
| 0, 43, 43, 1, 221184, 0x6f46c14e | |||
| 0, 44, 44, 1, 221184, 0x9cf4ae70 | |||
| 0, 45, 45, 1, 221184, 0xf205b2f8 | |||
| 0, 46, 46, 1, 221184, 0x7180aff8 | |||
| 0, 47, 47, 1, 221184, 0x125eaffe | |||
| 0, 48, 48, 1, 221184, 0x6970a32d | |||
| 0, 49, 49, 1, 221184, 0xaea79f62 | |||
| 0, 50, 50, 1, 221184, 0x48d2a093 | |||
| 0, 51, 51, 1, 221184, 0x10a59eb5 | |||