diff --git a/Changelog b/Changelog index 3fb8e650c8..084bac32a9 100644 --- a/Changelog +++ b/Changelog @@ -11,37 +11,72 @@ version next: - added avconv, which is almost the same for now, except for a few incompatible changes in the options, which will hopefully make them easier to use. The changes are: - * -newvideo/-newaudio/-newsubtitle are gone, because they were redundant and - worked in a nonstandard way. -map is sufficient to add streams to output - files. - * -map now has slightly different and more powerful syntax. - + it's possible to specify stream type. E.g. -map 0:a:2 means 'third - audio stream'. - + omitting the stream index now maps all the streams of the given - type, not just the first. E.g. -map 0:s maps all the subtitle streams. - + colons (':') are used to separate file index/stream type/stream - index. Comma (',') is used to separate the sync stream. This is done - for consistency with other options. - + since -map can now match multiple streams, negative mappings were + * The options placement is now strictly enforced! While in theory the + options for ffmpeg should be given in [input options] -i INPUT [output + options] OUTPUT order, in practice it was possible to give output options + before the -i and it mostly worked. Except when it didn't - the behavior was + a bit inconsistent. In avconv, it is not possible to mix input and output + options. All non-global options are reset after an input or output filename. + * All per-file options are now truly per-file - they apply only to the next + input or output file and specifying different values for different files + will now work properly (notably -ss and -t options). + * All per-stream options are now truly per-stream - it is possible to + specify which stream(s) should a given option apply to. See the Stream + specifiers section in the avconv manual for details. + * In ffmpeg some options (like -newvideo/-newaudio/...) are irregular in the + sense that they're specified after the output filename instead of before, + like all other options. In avconv this irregularity is removed, all options + apply to the next input or output file. + * -newvideo/-newaudio/-newsubtitle options were removed. Not only were they + irregular and highly confusing, they were also redundant. In avconv the -map + option will create new streams in the output file and map input streams to + them. E.g. avconv -i INPUT -map 0 OUTPUT will create an output stream for + each stream in the first input file. + * The -map option now has slightly different and more powerful syntax: + + Colons (':') are used to separate file index/stream type/stream index + instead of dots. Comma (',') is used to separate the sync stream instead + of colon.. This is done for consistency with other options. + + It's possible to specify stream type. E.g. -map 0:a:2 creates an + output stream from the third input audio stream. + + Omitting the stream index now maps all the streams of the given type, + not just the first. E.g. -map 0:s creates output streams for all the + subtitle streams in the first input file. + + Since -map can now match multiple streams, negative mappings were introduced. Negative mappings disable some streams from an already - defined map. E.g. '-map 0 -map -0:a:1' means 'map everything except - for the second audio stream'. - * -vcodec/-acodec/-scodec are replaced by -c (or -codec), which - allows to precisely specify target stream(s) consistently with other - options. E.g. '-c:v libx264' sets the codec for all video streams, - '-c:a:0 libvorbis' sets the codec for the first audio stream and '-c - copy' copies all the streams. + defined map. E.g. '-map 0 -map -0:a:1' means 'create output streams for + all the stream in the first input file, except for the second audio + stream'. + * There is a new option -c (or -codec) for choosing the decoder/encoder to + use, which allows to precisely specify target stream(s) consistently with + other options. E.g. -c:v lib264 sets the codec for all video streams, -c:a:0 + libvorbis sets the codec for the first audio stream and -c copy copies all + the streams without reencoding. Old -vcodec/-acodec/-scodec options are now + aliases to -c:v/a/s * It is now possible to precisely specify which stream should an AVOption - apply to. See the manual for detailed explanation. + apply to. E.g. -b:v:0 2M sets the bitrate for the first video stream, while + -b:a 128k sets the bitrate for all audio streams. Note that the old -ab 128k + syntax is deprecated and will stop working soon. * -map_chapters now takes only an input file index and applies to the next output file. This is consistent with how all the other options work. * -map_metadata now takes only an input metadata specifier and applies to the next output file. Output metadata specifier is now part of the option name, similarly to the AVOptions/map/codec feature above. - * Presets in avconv are disabled, because only libx264 used them and - presets for libx264 can now be specified using a private option - '-preset '. - * -intra option was removed, it's equivalent to -g 0. + * -metadata can now be used to set metadata on streams and chapters, e.g. + -metadata:s:1 language=eng sets the language of the first stream to 'eng'. + This made -vlang/-alang/-slang options redundant, so they were removed. + * -qscale option now uses stream specifiers and applies to all streams, not + just video. I.e. plain -qscale number would now apply to all streams. To get + the old behavior, use -qscale:v. Also there is now a shortcut -q for -qscale + and -aq is now an alias for -q:a. + * -vbsf/-absf/-sbsf options were removed and replaced by a -bsf option which + uses stream specifiers. Use -bsf:v/a/s instead of the old options. + * -itsscale option now uses stream specifiers, so its argument is only the + scale parameter. + * -intra option was removed, use -g 0 for the same effect. + * -psnr option was removed, use -flags +psnr for the same effect. + * -vf option is now an alias to the new -filter option, which uses stream specifiers. + * -vframes/-aframes/-dframes options are now aliases to the new -frames option. + * -vtag/-atag/-stag options are now aliases to the new -tag option. - XMV demuxer - LOAS demuxer - ashowinfo filter added @@ -68,6 +103,7 @@ easier to use. The changes are: - Ut Video decoder - Speex encoding via libspeex - 4:2:2 H.264 decoding support +- 4:2:2 and 4:4:4 H.264 encoding with libx264 - Pulseaudio input device - Prores encoder - Video Decoder Acceleration (VDA) HWAccel module. @@ -77,6 +113,11 @@ easier to use. The changes are: - earwax audio filter added - libv4l2 support (--enable-libv4l2) - TLS/SSL and HTTPS protocol support +- AVOptions API rewritten and documented +- most of CODEC_FLAG2_*, some CODEC_FLAG_* and many codec-specific fields in + AVCodecContext deprecated. Codec private options should be used instead. +- Properly working defaults in libx264 wrapper, support for native presets. +- Encrypted OMA files support version 0.8: diff --git a/avconv.c b/avconv.c index 335b47e98c..89264aa8d3 100644 --- a/avconv.c +++ b/avconv.c @@ -132,7 +132,6 @@ static int copy_tb= 0; static int opt_shortest = 0; static char *vstats_filename; static FILE *vstats_file; -static int copy_initial_nonkeyframes = 0; static int audio_volume = 256; @@ -240,11 +239,12 @@ typedef struct OutputStream { AVFilterGraph *graph; #endif - int64_t sws_flags; - AVDictionary *opts; - int is_past_recording_time; - int stream_copy; - const char *attachment_filename; + int64_t sws_flags; + AVDictionary *opts; + int is_past_recording_time; + int stream_copy; + const char *attachment_filename; + int copy_initial_nonkeyframes; } OutputStream; #if HAVE_TERMIOS_H @@ -355,6 +355,8 @@ typedef struct OptionsContext { int nb_top_field_first; SpecifierOpt *presets; int nb_presets; + SpecifierOpt *copy_initial_nonkeyframes; + int nb_copy_initial_nonkeyframes; #if CONFIG_AVFILTER SpecifierOpt *filters; int nb_filters; @@ -628,6 +630,7 @@ void exit_program(int ret) #if CONFIG_AVFILTER avfilter_uninit(); #endif + avformat_network_deinit(); if (received_sigterm) { av_log(NULL, AV_LOG_INFO, "Received signal %d: terminating.\n", @@ -822,7 +825,7 @@ need_realloc: if ((ost->audio_resample && !ost->resample) || resample_changed) { if (resample_changed) { - av_log(NULL, AV_LOG_INFO, "Input stream #%d.%d frame changed from rate:%d fmt:%s ch:%d to rate:%d fmt:%s ch:%d\n", + av_log(NULL, AV_LOG_INFO, "Input stream #%d:%d frame changed from rate:%d fmt:%s ch:%d to rate:%d fmt:%s ch:%d\n", ist->file_index, ist->st->index, ost->resample_sample_rate, av_get_sample_fmt_name(ost->resample_sample_fmt), ost->resample_channels, dec->sample_rate, av_get_sample_fmt_name(dec->sample_fmt), dec->channels); @@ -1137,7 +1140,7 @@ static void do_video_resample(OutputStream *ost, #if !CONFIG_AVFILTER if (resample_changed) { av_log(NULL, AV_LOG_INFO, - "Input stream #%d.%d frame changed from size:%dx%d fmt:%s to size:%dx%d fmt:%s\n", + "Input stream #%d:%d frame changed from size:%dx%d fmt:%s to size:%dx%d fmt:%s\n", ist->file_index, ist->st->index, ost->resample_width, ost->resample_height, av_get_pix_fmt_name(ost->resample_pix_fmt), dec->width , dec->height , av_get_pix_fmt_name(dec->pix_fmt)); @@ -1886,7 +1889,8 @@ static int output_packet(InputStream *ist, int ist_index, int64_t ost_tb_start_time= av_rescale_q(of->start_time, AV_TIME_BASE_Q, ost->st->time_base); av_init_packet(&opkt); - if ((!ost->frame_number && !(pkt->flags & AV_PKT_FLAG_KEY)) && !copy_initial_nonkeyframes) + if ((!ost->frame_number && !(pkt->flags & AV_PKT_FLAG_KEY)) && + !ost->copy_initial_nonkeyframes) #if !CONFIG_AVFILTER continue; #else @@ -1994,13 +1998,13 @@ static int init_input_stream(int ist_index, OutputStream *output_streams, int nb if (ist->decoding_needed) { AVCodec *codec = ist->dec; if (!codec) { - snprintf(error, error_len, "Decoder (codec id %d) not found for input stream #%d.%d", + snprintf(error, error_len, "Decoder (codec id %d) not found for input stream #%d:%d", ist->st->codec->codec_id, ist->file_index, ist->st->index); return AVERROR(EINVAL); } if (avcodec_open2(ist->st->codec, codec, &ist->opts) < 0) { - snprintf(error, error_len, "Error while opening decoder for input stream #%d.%d", + snprintf(error, error_len, "Error while opening decoder for input stream #%d:%d", ist->file_index, ist->st->index); return AVERROR(EINVAL); } @@ -2280,7 +2284,7 @@ static int transcode_init(OutputFile *output_files, AVCodec *codec = ost->enc; AVCodecContext *dec = input_streams[ost->source_index].st->codec; if (!codec) { - snprintf(error, sizeof(error), "Encoder (codec id %d) not found for output stream #%d.%d", + snprintf(error, sizeof(error), "Encoder (codec id %d) not found for output stream #%d:%d", ost->st->codec->codec_id, ost->file_index, ost->index); ret = AVERROR(EINVAL); goto dump_format; @@ -2295,7 +2299,7 @@ static int transcode_init(OutputFile *output_files, ost->st->codec->subtitle_header_size = dec->subtitle_header_size; } if (avcodec_open2(ost->st->codec, codec, &ost->opts) < 0) { - snprintf(error, sizeof(error), "Error while opening encoder for output stream #%d.%d - maybe incorrect parameters such as bit_rate, rate, width or height", + snprintf(error, sizeof(error), "Error while opening encoder for output stream #%d:%d - maybe incorrect parameters such as bit_rate, rate, width or height", ost->file_index, ost->index); ret = AVERROR(EINVAL); goto dump_format; @@ -2365,13 +2369,13 @@ static int transcode_init(OutputFile *output_files, ost->attachment_filename, ost->file_index, ost->index); continue; } - av_log(NULL, AV_LOG_INFO, " Stream #%d.%d -> #%d.%d", + av_log(NULL, AV_LOG_INFO, " Stream #%d:%d -> #%d:%d", input_streams[ost->source_index].file_index, input_streams[ost->source_index].st->index, ost->file_index, ost->index); if (ost->sync_ist != &input_streams[ost->source_index]) - av_log(NULL, AV_LOG_INFO, " [sync #%d.%d]", + av_log(NULL, AV_LOG_INFO, " [sync #%d:%d]", ost->sync_ist->file_index, ost->sync_ist->st->index); if (ost->stream_copy) @@ -2591,7 +2595,7 @@ static int transcode(OutputFile *output_files, //fprintf(stderr,"read #%d.%d size=%d\n", ist->file_index, ist->st->index, pkt.size); if (output_packet(ist, ist_index, output_streams, nb_output_streams, &pkt) < 0) { - av_log(NULL, AV_LOG_ERROR, "Error while decoding stream #%d.%d\n", + av_log(NULL, AV_LOG_ERROR, "Error while decoding stream #%d:%d\n", ist->file_index, ist->st->index); if (exit_on_error) exit_program(1); @@ -2909,7 +2913,6 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic) AVStream *st = ic->streams[i]; AVCodecContext *dec = st->codec; InputStream *ist; - double scale = 1.0; input_streams = grow_array(input_streams, sizeof(*input_streams), &nb_input_streams, nb_input_streams + 1); ist = &input_streams[nb_input_streams - 1]; @@ -2918,8 +2921,8 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic) ist->discard = 1; ist->opts = filter_codec_opts(codec_opts, ist->st->codec->codec_id, ic, st); - MATCH_PER_STREAM_OPT(ts_scale, dbl, scale, ic, st); - ist->ts_scale = scale; + ist->ts_scale = 1.0; + MATCH_PER_STREAM_OPT(ts_scale, dbl, ist->ts_scale, ic, st); ist->dec = choose_decoder(o, ic, st); @@ -3231,7 +3234,6 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e OutputStream *ost; AVStream *st = avformat_new_stream(oc, NULL); int idx = oc->nb_streams - 1, ret = 0; - int64_t max_frames = INT64_MAX; char *bsf = NULL, *next, *codec_tag = NULL; AVBitStreamFilterContext *bsfc, *bsfc_prev = NULL; double qscale = -1; @@ -3286,8 +3288,8 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e exit_program(1); } - MATCH_PER_STREAM_OPT(max_frames, i64, max_frames, oc, st); - ost->max_frames = max_frames; + ost->max_frames = INT64_MAX; + MATCH_PER_STREAM_OPT(max_frames, i64, ost->max_frames, oc, st); MATCH_PER_STREAM_OPT(bitstream_filters, str, bsf, oc, st); while (bsf) { @@ -3359,7 +3361,7 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc) char *forced_key_frames = NULL, *frame_rate = NULL, *frame_size = NULL; char *frame_aspect_ratio = NULL, *frame_pix_fmt = NULL; char *intra_matrix = NULL, *inter_matrix = NULL, *filters = NULL; - int i, force_fps = 0, top_field_first = -1; + int i; MATCH_PER_STREAM_OPT(frame_rates, str, frame_rate, oc, st); if (frame_rate && av_parse_video_rate(&ost->frame_rate, frame_rate) < 0) { @@ -3443,11 +3445,12 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc) if (forced_key_frames) parse_forced_key_frames(forced_key_frames, ost, video_enc); - MATCH_PER_STREAM_OPT(force_fps, i, force_fps, oc, st); - ost->force_fps = force_fps; + MATCH_PER_STREAM_OPT(force_fps, i, ost->force_fps, oc, st); - MATCH_PER_STREAM_OPT(top_field_first, i, top_field_first, oc, st); - ost->top_field_first = top_field_first; + ost->top_field_first = -1; + MATCH_PER_STREAM_OPT(top_field_first, i, ost->top_field_first, oc, st); + + MATCH_PER_STREAM_OPT(copy_initial_nonkeyframes, i, ost->copy_initial_nonkeyframes, oc ,st); #if CONFIG_AVFILTER MATCH_PER_STREAM_OPT(filters, str, filters, oc, st); @@ -3711,7 +3714,7 @@ static void opt_output_file(void *optctx, const char *filename) case AVMEDIA_TYPE_DATA: ost = new_data_stream(o, oc); break; case AVMEDIA_TYPE_ATTACHMENT: ost = new_attachment_stream(o, oc); break; default: - av_log(NULL, AV_LOG_FATAL, "Cannot map stream #%d.%d - unsupported type.\n", + av_log(NULL, AV_LOG_FATAL, "Cannot map stream #%d:%d - unsupported type.\n", map->file_index, map->stream_index); exit_program(1); } @@ -4248,7 +4251,7 @@ static const OptionDef options[] = { { "shortest", OPT_BOOL | OPT_EXPERT, {(void*)&opt_shortest}, "finish encoding within shortest input" }, // { "dts_delta_threshold", HAS_ARG | OPT_FLOAT | OPT_EXPERT, {(void*)&dts_delta_threshold}, "timestamp discontinuity delta threshold", "threshold" }, { "xerror", OPT_BOOL, {(void*)&exit_on_error}, "exit on error", "error" }, - { "copyinkf", OPT_BOOL | OPT_EXPERT, {(void*)©_initial_nonkeyframes}, "copy initial non-keyframes" }, + { "copyinkf", OPT_BOOL | OPT_EXPERT | OPT_SPEC, {.off = OFFSET(copy_initial_nonkeyframes)}, "copy initial non-keyframes" }, { "frames", OPT_INT64 | HAS_ARG | OPT_SPEC, {.off = OFFSET(max_frames)}, "set the number of frames to record", "number" }, { "tag", OPT_STRING | HAS_ARG | OPT_SPEC, {.off = OFFSET(codec_tags)}, "force codec tag/fourcc", "fourcc/tag" }, { "q", HAS_ARG | OPT_EXPERT | OPT_DOUBLE | OPT_SPEC, {.off = OFFSET(qscale)}, "use fixed quality scale (VBR)", "q" }, @@ -4349,6 +4352,7 @@ int main(int argc, char **argv) avfilter_register_all(); #endif av_register_all(); + avformat_network_init(); #if HAVE_ISATTY if(isatty(STDIN_FILENO)) diff --git a/doc/APIchanges b/doc/APIchanges index a326584645..8a2a9de550 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -19,7 +19,13 @@ API changes, most recent first: 2011-10-20 - b35e9e1 - lavu 51.22.0 Add av_strtok() to avstring.h. -2011-11-xx - xxxxxxx - lavf 53.13.0 +2011-11-06 - ba04ecf - lavu 51.14.0 + Add av_strcasecmp() and av_strncasecmp() to avstring.h. + +2011-11-06 - 07b172f - lavu 51.13.0 + Add av_toupper()/av_tolower() + +2011-11-05 - b6d08f4 - lavf 53.13.0 Add avformat_network_init()/avformat_network_uninit() 2011-10-27 - 512557b - lavc 53.15.0 diff --git a/doc/avconv.texi b/doc/avconv.texi index bcbf2e5861..53e9890022 100644 --- a/doc/avconv.texi +++ b/doc/avconv.texi @@ -26,6 +26,23 @@ avconv is a very fast video and audio converter that can also grab from a live audio/video source. It can also convert between arbitrary sample rates and resize video on the fly with a high quality polyphase filter. +avconv reads from an arbitrary number of input "files" (which can be regular +files, pipes, network streams, grabbing devices, etc.), specified by the +@code{-i} option, and writes to an arbitrary number of output "files", which are +specified by a plain output filename. Anything found on the commandline which +cannot be interpreted as an option is considered to be an output filename. + +Each input or output file can in principle contain any number of streams of +different types (video/audio/subtitle/attachment/data). Allowed number and/or +types of streams can be limited by the container format. Selecting, which +streams from which inputs go into output, is done either automatically or with +the @code{-map} option (see the Stream selection chapter). + +To refer to input files in options, you must use their indices (0-based). E.g. +the first input file is @code{0}, the second is @code{1} etc. Similarly, streams +within a file are referred to by their indices. E.g. @code{2:3} refers to the +fourth stream in the third input file. See also the Stream specifiers chapter. + As a general rule, options are applied to the next specified file. Therefore, order is important, and you can have the same option on the command line multiple times. Each occurrence is @@ -33,6 +50,10 @@ then applied to the next input or output file. Exceptions from this rule are the global options (e.g. verbosity level), which should be specified first. +Do not mix input and output files -- first specify all input files, then all +output files. Also do not mix options which belong to different files. All +options apply ONLY to the next input or output file and are reset between files. + @itemize @item To set the video bitrate of the output file to 64kbit/s: @@ -525,6 +546,10 @@ frames after each specified time. This option can be useful to ensure that a seek point is present at a chapter mark or any other designated place in the output file. The timestamps must be specified in ascending order. + +@item -copyinkf[:@var{stream_specifier}] (@emph{output,per-stream}) +When doing stream copy, copy also non-key frames found at the +beginning. @end table @section Audio Options @@ -549,7 +574,7 @@ Disable audio recording. @item -acodec @var{codec} (@emph{input/output}) Set the audio codec. This is an alias for @code{-codec:a}. @item -sample_fmt[:@var{stream_specifier}] @var{sample_fmt} (@emph{output,per-stream}) -Set the audio sample format. Use @code{-help sample_fmts} to get a list +Set the audio sample format. Use @code{-sample_fmts} to get a list of supported sample formats. @end table diff --git a/ffmpeg.c b/ffmpeg.c index a836c98abb..f7232c9f8d 100644 --- a/ffmpeg.c +++ b/ffmpeg.c @@ -144,7 +144,6 @@ static int copy_tb= 0; static int opt_shortest = 0; static char *vstats_filename; static FILE *vstats_file; -static int copy_initial_nonkeyframes = 0; static int audio_volume = 256; @@ -255,11 +254,12 @@ typedef struct OutputStream { AVFilterGraph *graph; #endif - int64_t sws_flags; - AVDictionary *opts; - int is_past_recording_time; - int stream_copy; - const char *attachment_filename; + int64_t sws_flags; + AVDictionary *opts; + int is_past_recording_time; + int stream_copy; + const char *attachment_filename; + int copy_initial_nonkeyframes; } OutputStream; @@ -375,6 +375,8 @@ typedef struct OptionsContext { int nb_top_field_first; SpecifierOpt *presets; int nb_presets; + SpecifierOpt *copy_initial_nonkeyframes; + int nb_copy_initial_nonkeyframes; #if CONFIG_AVFILTER SpecifierOpt *filters; int nb_filters; @@ -569,6 +571,7 @@ static void term_init(void) signal(SIGQUIT, sigterm_handler); /* Quit (POSIX). */ } #endif + avformat_network_deinit(); signal(SIGINT , sigterm_handler); /* Interrupt (ANSI). */ signal(SIGTERM, sigterm_handler); /* Termination (ANSI). */ @@ -672,6 +675,7 @@ void exit_program(int ret) #if CONFIG_AVFILTER avfilter_uninit(); #endif + avformat_network_deinit(); av_freep(&input_tmp); @@ -869,7 +873,7 @@ need_realloc: if ((ost->audio_resample && !ost->swr) || resample_changed || ost->audio_channels_mapped) { if (resample_changed) { - av_log(NULL, AV_LOG_INFO, "Input stream #%d.%d frame changed from rate:%d fmt:%s ch:%d to rate:%d fmt:%s ch:%d\n", + av_log(NULL, AV_LOG_INFO, "Input stream #%d:%d frame changed from rate:%d fmt:%s ch:%d to rate:%d fmt:%s ch:%d\n", ist->file_index, ist->st->index, ost->resample_sample_rate, av_get_sample_fmt_name(ost->resample_sample_fmt), ost->resample_channels, dec->sample_rate, av_get_sample_fmt_name(dec->sample_fmt), dec->channels); @@ -1165,7 +1169,7 @@ static void do_video_resample(OutputStream *ost, *out_picture = in_picture; if (resample_changed) { av_log(NULL, AV_LOG_INFO, - "Input stream #%d.%d frame changed from size:%dx%d fmt:%s to size:%dx%d fmt:%s\n", + "Input stream #%d:%d frame changed from size:%dx%d fmt:%s to size:%dx%d fmt:%s\n", ist->file_index, ist->st->index, ost->resample_width, ost->resample_height, av_get_pix_fmt_name(ost->resample_pix_fmt), dec->width , dec->height , av_get_pix_fmt_name(dec->pix_fmt)); @@ -1918,7 +1922,8 @@ static int output_packet(InputStream *ist, int ist_index, int64_t ost_tb_start_time= av_rescale_q(of->start_time, AV_TIME_BASE_Q, ost->st->time_base); av_init_packet(&opkt); - if ((!ost->frame_number && !(pkt->flags & AV_PKT_FLAG_KEY)) && !copy_initial_nonkeyframes) + if ((!ost->frame_number && !(pkt->flags & AV_PKT_FLAG_KEY)) && + !ost->copy_initial_nonkeyframes) #if !CONFIG_AVFILTER continue; #else @@ -2024,12 +2029,12 @@ static int init_input_stream(int ist_index, OutputStream *output_streams, int nb if (ist->decoding_needed) { AVCodec *codec = ist->dec; if (!codec) { - snprintf(error, error_len, "Decoder (codec %s) not found for input stream #%d.%d", + snprintf(error, error_len, "Decoder (codec %s) not found for input stream #%d:%d", avcodec_get_name(ist->st->codec->codec_id), ist->file_index, ist->st->index); return AVERROR(EINVAL); } if (avcodec_open2(ist->st->codec, codec, &ist->opts) < 0) { - snprintf(error, error_len, "Error while opening decoder for input stream #%d.%d", + snprintf(error, error_len, "Error while opening decoder for input stream #%d:%d", ist->file_index, ist->st->index); return AVERROR(EINVAL); } @@ -2330,7 +2335,7 @@ static int transcode_init(OutputFile *output_files, int nb_output_files, AVCodec *codec = ost->enc; AVCodecContext *dec = input_streams[ost->source_index].st->codec; if (!codec) { - snprintf(error, sizeof(error), "Encoder (codec %s) not found for output stream #%d.%d", + snprintf(error, sizeof(error), "Encoder (codec %s) not found for output stream #%d:%d", avcodec_get_name(ost->st->codec->codec_id), ost->file_index, ost->index); ret = AVERROR(EINVAL); goto dump_format; @@ -2345,7 +2350,7 @@ static int transcode_init(OutputFile *output_files, int nb_output_files, ost->st->codec->subtitle_header_size = dec->subtitle_header_size; } if (avcodec_open2(ost->st->codec, codec, &ost->opts) < 0) { - snprintf(error, sizeof(error), "Error while opening encoder for output stream #%d.%d - maybe incorrect parameters such as bit_rate, rate, width or height", + snprintf(error, sizeof(error), "Error while opening encoder for output stream #%d:%d - maybe incorrect parameters such as bit_rate, rate, width or height", ost->file_index, ost->index); ret = AVERROR(EINVAL); goto dump_format; @@ -2415,7 +2420,7 @@ static int transcode_init(OutputFile *output_files, int nb_output_files, ost->attachment_filename, ost->file_index, ost->index); continue; } - av_log(NULL, AV_LOG_INFO, " Stream #%d.%d -> #%d.%d", + av_log(NULL, AV_LOG_INFO, " Stream #%d:%d -> #%d:%d", input_streams[ost->source_index].file_index, input_streams[ost->source_index].st->index, ost->file_index, @@ -2430,7 +2435,7 @@ static int transcode_init(OutputFile *output_files, int nb_output_files, av_log(NULL, AV_LOG_INFO, "]"); } if (ost->sync_ist != &input_streams[ost->source_index]) - av_log(NULL, AV_LOG_INFO, " [sync #%d.%d]", + av_log(NULL, AV_LOG_INFO, " [sync #%d:%d]", ost->sync_ist->file_index, ost->sync_ist->st->index); if (ost->stream_copy) @@ -2691,7 +2696,7 @@ static int transcode(OutputFile *output_files, int nb_output_files, //fprintf(stderr,"read #%d.%d size=%d\n", ist->file_index, ist->st->index, pkt.size); if (output_packet(ist, ist_index, output_streams, nb_output_streams, &pkt) < 0) { - av_log(NULL, AV_LOG_ERROR, "Error while decoding stream #%d.%d\n", + av_log(NULL, AV_LOG_ERROR, "Error while decoding stream #%d:%d\n", ist->file_index, ist->st->index); if (exit_on_error) exit_program(1); @@ -3114,7 +3119,6 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic) AVStream *st = ic->streams[i]; AVCodecContext *dec = st->codec; InputStream *ist; - double scale = 1.0; input_streams = grow_array(input_streams, sizeof(*input_streams), &nb_input_streams, nb_input_streams + 1); ist = &input_streams[nb_input_streams - 1]; @@ -3123,8 +3127,8 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic) ist->discard = 1; ist->opts = filter_codec_opts(codec_opts, ist->st->codec->codec_id, ic, st); - MATCH_PER_STREAM_OPT(ts_scale, dbl, scale, ic, st); - ist->ts_scale = scale; + ist->ts_scale = 1.0; + MATCH_PER_STREAM_OPT(ts_scale, dbl, ist->ts_scale, ic, st); MATCH_PER_STREAM_OPT(codec_tags, str, codec_tag, ic, st); if (codec_tag) { @@ -3454,7 +3458,6 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e OutputStream *ost; AVStream *st = avformat_new_stream(oc, NULL); int idx = oc->nb_streams - 1, ret = 0; - int64_t max_frames = INT64_MAX; char *bsf = NULL, *next, *codec_tag = NULL; AVBitStreamFilterContext *bsfc, *bsfc_prev = NULL; double qscale = -1; @@ -3509,8 +3512,8 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e exit_program(1); } - MATCH_PER_STREAM_OPT(max_frames, i64, max_frames, oc, st); - ost->max_frames = max_frames; + ost->max_frames = INT64_MAX; + MATCH_PER_STREAM_OPT(max_frames, i64, ost->max_frames, oc, st); MATCH_PER_STREAM_OPT(bitstream_filters, str, bsf, oc, st); while (bsf) { @@ -3582,7 +3585,7 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc) char *forced_key_frames = NULL, *frame_rate = NULL, *frame_size = NULL; char *frame_aspect_ratio = NULL, *frame_pix_fmt = NULL; char *intra_matrix = NULL, *inter_matrix = NULL, *filters = NULL; - int i, force_fps = 0, top_field_first = -1; + int i; MATCH_PER_STREAM_OPT(frame_rates, str, frame_rate, oc, st); if (frame_rate && av_parse_video_rate(&ost->frame_rate, frame_rate) < 0) { @@ -3671,11 +3674,12 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc) if (forced_key_frames) parse_forced_key_frames(forced_key_frames, ost); - MATCH_PER_STREAM_OPT(force_fps, i, force_fps, oc, st); - ost->force_fps = force_fps; + MATCH_PER_STREAM_OPT(force_fps, i, ost->force_fps, oc, st); - MATCH_PER_STREAM_OPT(top_field_first, i, top_field_first, oc, st); - ost->top_field_first = top_field_first; + ost->top_field_first = -1; + MATCH_PER_STREAM_OPT(top_field_first, i, ost->top_field_first, oc, st); + + MATCH_PER_STREAM_OPT(copy_initial_nonkeyframes, i, ost->copy_initial_nonkeyframes, oc ,st); #if CONFIG_AVFILTER MATCH_PER_STREAM_OPT(filters, str, filters, oc, st); @@ -3980,7 +3984,7 @@ static void opt_output_file(void *optctx, const char *filename) case AVMEDIA_TYPE_DATA: ost = new_data_stream(o, oc); break; case AVMEDIA_TYPE_ATTACHMENT: ost = new_attachment_stream(o, oc); break; default: - av_log(NULL, AV_LOG_FATAL, "Cannot map stream #%d.%d - unsupported type.\n", + av_log(NULL, AV_LOG_FATAL, "Cannot map stream #%d:%d - unsupported type.\n", map->file_index, map->stream_index); exit_program(1); } @@ -4580,7 +4584,7 @@ static const OptionDef options[] = { { "shortest", OPT_BOOL | OPT_EXPERT, {(void*)&opt_shortest}, "finish encoding within shortest input" }, // { "dts_delta_threshold", HAS_ARG | OPT_FLOAT | OPT_EXPERT, {(void*)&dts_delta_threshold}, "timestamp discontinuity delta threshold", "threshold" }, { "xerror", OPT_BOOL, {(void*)&exit_on_error}, "exit on error", "error" }, - { "copyinkf", OPT_BOOL | OPT_EXPERT, {(void*)©_initial_nonkeyframes}, "copy initial non-keyframes" }, + { "copyinkf", OPT_BOOL | OPT_EXPERT | OPT_SPEC, {.off = OFFSET(copy_initial_nonkeyframes)}, "copy initial non-keyframes" }, { "frames", OPT_INT64 | HAS_ARG | OPT_SPEC, {.off = OFFSET(max_frames)}, "set the number of frames to record", "number" }, { "tag", OPT_STRING | HAS_ARG | OPT_SPEC, {.off = OFFSET(codec_tags)}, "force codec tag/fourcc", "fourcc/tag" }, { "q", HAS_ARG | OPT_EXPERT | OPT_DOUBLE | OPT_SPEC, {.off = OFFSET(qscale)}, "use fixed quality scale (VBR)", "q" }, @@ -4702,6 +4706,7 @@ int main(int argc, char **argv) avfilter_register_all(); #endif av_register_all(); + avformat_network_init(); #if HAVE_ISATTY if(isatty(STDIN_FILENO)) diff --git a/ffplay.c b/ffplay.c index ebcb8c04c3..1d14c08415 100644 --- a/ffplay.c +++ b/ffplay.c @@ -914,6 +914,7 @@ static void do_exit(VideoState *is) #if CONFIG_AVFILTER avfilter_uninit(); #endif + avformat_network_deinit(); if (show_status) printf("\n"); SDL_Quit(); @@ -3143,6 +3144,7 @@ int main(int argc, char **argv) avfilter_register_all(); #endif av_register_all(); + avformat_network_init(); init_opts(); diff --git a/ffprobe.c b/ffprobe.c index baffe0b375..e00805afa2 100644 --- a/ffprobe.c +++ b/ffprobe.c @@ -936,6 +936,7 @@ int main(int argc, char **argv) parse_loglevel(argc, argv, options); av_register_all(); + avformat_network_init(); init_opts(); #if CONFIG_AVDEVICE avdevice_register_all(); @@ -953,5 +954,7 @@ int main(int argc, char **argv) ret = probe_file(input_filename); + avformat_network_deinit(); + return ret; } diff --git a/ffserver.c b/ffserver.c index 788755d613..90c4ae6f4c 100644 --- a/ffserver.c +++ b/ffserver.c @@ -24,7 +24,6 @@ #define closesocket close #endif #include -#include #include #include "libavformat/avformat.h" #include "libavformat/ffm.h" @@ -1085,13 +1084,13 @@ static int extract_rates(char *rates, int ratelen, const char *request) const char *p; for (p = request; *p && *p != '\r' && *p != '\n'; ) { - if (strncasecmp(p, "Pragma:", 7) == 0) { + if (av_strncasecmp(p, "Pragma:", 7) == 0) { const char *q = p + 7; while (*q && *q != '\n' && isspace(*q)) q++; - if (strncasecmp(q, "stream-switch-entry=", 20) == 0) { + if (av_strncasecmp(q, "stream-switch-entry=", 20) == 0) { int stream_no; int rate_no; @@ -1271,9 +1270,9 @@ static void parse_acl_row(FFStream *stream, FFStream* feed, IPAddressACL *ext_ac int errors = 0; get_arg(arg, sizeof(arg), &p); - if (strcasecmp(arg, "allow") == 0) + if (av_strcasecmp(arg, "allow") == 0) acl.action = IP_ALLOW; - else if (strcasecmp(arg, "deny") == 0) + else if (av_strcasecmp(arg, "deny") == 0) acl.action = IP_DENY; else { fprintf(stderr, "%s:%d: ACL action '%s' is not ALLOW or DENY\n", @@ -1358,7 +1357,7 @@ static IPAddressACL* parse_dynamic_acl(FFStream *stream, HTTPContext *c) continue; get_arg(cmd, sizeof(cmd), &p); - if (!strcasecmp(cmd, "ACL")) + if (!av_strcasecmp(cmd, "ACL")) parse_acl_row(NULL, NULL, acl, p, stream->dynamic_acl, line_num); } fclose(f); @@ -1500,7 +1499,7 @@ static int http_parse_request(HTTPContext *c) av_strlcpy(filename, url + ((*url == '/') ? 1 : 0), sizeof(filename)-1); for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) { - if (strncasecmp(p, "User-Agent:", 11) == 0) { + if (av_strncasecmp(p, "User-Agent:", 11) == 0) { useragent = p + 11; if (*useragent && *useragent != '\n' && isspace(*useragent)) useragent++; @@ -1518,7 +1517,7 @@ static int http_parse_request(HTTPContext *c) redir_type = REDIR_ASX; filename[strlen(filename)-1] = 'f'; } else if (av_match_ext(filename, "asf") && - (!useragent || strncasecmp(useragent, "NSPlayer", 8) != 0)) { + (!useragent || av_strncasecmp(useragent, "NSPlayer", 8) != 0)) { /* if this isn't WMP or lookalike, return the redirector file */ redir_type = REDIR_ASF; } else if (av_match_ext(filename, "rpm,ram")) { @@ -1613,7 +1612,7 @@ static int http_parse_request(HTTPContext *c) char *hostinfo = 0; for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) { - if (strncasecmp(p, "Host:", 5) == 0) { + if (av_strncasecmp(p, "Host:", 5) == 0) { hostinfo = p + 5; break; } @@ -1742,11 +1741,11 @@ static int http_parse_request(HTTPContext *c) int client_id = 0; for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) { - if (strncasecmp(p, "Pragma: log-line=", 17) == 0) { + if (av_strncasecmp(p, "Pragma: log-line=", 17) == 0) { logline = p; break; } - if (strncasecmp(p, "Pragma: client-id=", 18) == 0) + if (av_strncasecmp(p, "Pragma: client-id=", 18) == 0) client_id = strtol(p + 18, 0, 10); p = strchr(p, '\n'); if (!p) @@ -4059,40 +4058,40 @@ static int parse_ffconfig(const char *filename) get_arg(cmd, sizeof(cmd), &p); - if (!strcasecmp(cmd, "Port")) { + if (!av_strcasecmp(cmd, "Port")) { get_arg(arg, sizeof(arg), &p); val = atoi(arg); if (val < 1 || val > 65536) { ERROR("Invalid_port: %s\n", arg); } my_http_addr.sin_port = htons(val); - } else if (!strcasecmp(cmd, "BindAddress")) { + } else if (!av_strcasecmp(cmd, "BindAddress")) { get_arg(arg, sizeof(arg), &p); if (resolve_host(&my_http_addr.sin_addr, arg) != 0) { ERROR("%s:%d: Invalid host/IP address: %s\n", arg); } - } else if (!strcasecmp(cmd, "NoDaemon")) { + } else if (!av_strcasecmp(cmd, "NoDaemon")) { ffserver_daemon = 0; - } else if (!strcasecmp(cmd, "RTSPPort")) { + } else if (!av_strcasecmp(cmd, "RTSPPort")) { get_arg(arg, sizeof(arg), &p); val = atoi(arg); if (val < 1 || val > 65536) { ERROR("%s:%d: Invalid port: %s\n", arg); } my_rtsp_addr.sin_port = htons(atoi(arg)); - } else if (!strcasecmp(cmd, "RTSPBindAddress")) { + } else if (!av_strcasecmp(cmd, "RTSPBindAddress")) { get_arg(arg, sizeof(arg), &p); if (resolve_host(&my_rtsp_addr.sin_addr, arg) != 0) { ERROR("Invalid host/IP address: %s\n", arg); } - } else if (!strcasecmp(cmd, "MaxHTTPConnections")) { + } else if (!av_strcasecmp(cmd, "MaxHTTPConnections")) { get_arg(arg, sizeof(arg), &p); val = atoi(arg); if (val < 1 || val > 65536) { ERROR("Invalid MaxHTTPConnections: %s\n", arg); } nb_max_http_connections = val; - } else if (!strcasecmp(cmd, "MaxClients")) { + } else if (!av_strcasecmp(cmd, "MaxClients")) { get_arg(arg, sizeof(arg), &p); val = atoi(arg); if (val < 1 || val > nb_max_http_connections) { @@ -4100,7 +4099,7 @@ static int parse_ffconfig(const char *filename) } else { nb_max_connections = val; } - } else if (!strcasecmp(cmd, "MaxBandwidth")) { + } else if (!av_strcasecmp(cmd, "MaxBandwidth")) { int64_t llval; get_arg(arg, sizeof(arg), &p); llval = atoll(arg); @@ -4108,10 +4107,10 @@ static int parse_ffconfig(const char *filename) ERROR("Invalid MaxBandwidth: %s\n", arg); } else max_bandwidth = llval; - } else if (!strcasecmp(cmd, "CustomLog")) { + } else if (!av_strcasecmp(cmd, "CustomLog")) { if (!ffserver_debug) get_arg(logfilename, sizeof(logfilename), &p); - } else if (!strcasecmp(cmd, "next_feed; } - } else if (!strcasecmp(cmd, "Launch")) { + } else if (!av_strcasecmp(cmd, "Launch")) { if (feed) { int i; @@ -4167,24 +4166,24 @@ static int parse_ffconfig(const char *filename) inet_ntoa(my_http_addr.sin_addr), ntohs(my_http_addr.sin_port), feed->filename); } - } else if (!strcasecmp(cmd, "ReadOnlyFile")) { + } else if (!av_strcasecmp(cmd, "ReadOnlyFile")) { if (feed) { get_arg(feed->feed_filename, sizeof(feed->feed_filename), &p); feed->readonly = 1; } else if (stream) { get_arg(stream->feed_filename, sizeof(stream->feed_filename), &p); } - } else if (!strcasecmp(cmd, "File")) { + } else if (!av_strcasecmp(cmd, "File")) { if (feed) { get_arg(feed->feed_filename, sizeof(feed->feed_filename), &p); } else if (stream) get_arg(stream->feed_filename, sizeof(stream->feed_filename), &p); - } else if (!strcasecmp(cmd, "Truncate")) { + } else if (!av_strcasecmp(cmd, "Truncate")) { if (feed) { get_arg(arg, sizeof(arg), &p); feed->truncate = strtod(arg, NULL); } - } else if (!strcasecmp(cmd, "FileMaxSize")) { + } else if (!av_strcasecmp(cmd, "FileMaxSize")) { if (feed) { char *p1; double fsize; @@ -4208,12 +4207,12 @@ static int parse_ffconfig(const char *filename) ERROR("Feed max file size is too small, must be at least %d\n", FFM_PACKET_SIZE*4); } } - } else if (!strcasecmp(cmd, "")) { + } else if (!av_strcasecmp(cmd, "")) { if (!feed) { ERROR("No corresponding for \n"); } feed = NULL; - } else if (!strcasecmp(cmd, "next; } - } else if (!strcasecmp(cmd, "Feed")) { + } else if (!av_strcasecmp(cmd, "Feed")) { get_arg(arg, sizeof(arg), &p); if (stream) { FFStream *sfeed; @@ -4263,7 +4262,7 @@ static int parse_ffconfig(const char *filename) else stream->feed = sfeed; } - } else if (!strcasecmp(cmd, "Format")) { + } else if (!av_strcasecmp(cmd, "Format")) { get_arg(arg, sizeof(arg), &p); if (stream) { if (!strcmp(arg, "status")) { @@ -4284,7 +4283,7 @@ static int parse_ffconfig(const char *filename) video_id = stream->fmt->video_codec; } } - } else if (!strcasecmp(cmd, "InputFormat")) { + } else if (!av_strcasecmp(cmd, "InputFormat")) { get_arg(arg, sizeof(arg), &p); if (stream) { stream->ifmt = av_find_input_format(arg); @@ -4292,65 +4291,65 @@ static int parse_ffconfig(const char *filename) ERROR("Unknown input format: %s\n", arg); } } - } else if (!strcasecmp(cmd, "FaviconURL")) { + } else if (!av_strcasecmp(cmd, "FaviconURL")) { if (stream && stream->stream_type == STREAM_TYPE_STATUS) { get_arg(stream->feed_filename, sizeof(stream->feed_filename), &p); } else { ERROR("FaviconURL only permitted for status streams\n"); } - } else if (!strcasecmp(cmd, "Author")) { + } else if (!av_strcasecmp(cmd, "Author")) { if (stream) get_arg(stream->author, sizeof(stream->author), &p); - } else if (!strcasecmp(cmd, "Comment")) { + } else if (!av_strcasecmp(cmd, "Comment")) { if (stream) get_arg(stream->comment, sizeof(stream->comment), &p); - } else if (!strcasecmp(cmd, "Copyright")) { + } else if (!av_strcasecmp(cmd, "Copyright")) { if (stream) get_arg(stream->copyright, sizeof(stream->copyright), &p); - } else if (!strcasecmp(cmd, "Title")) { + } else if (!av_strcasecmp(cmd, "Title")) { if (stream) get_arg(stream->title, sizeof(stream->title), &p); - } else if (!strcasecmp(cmd, "Preroll")) { + } else if (!av_strcasecmp(cmd, "Preroll")) { get_arg(arg, sizeof(arg), &p); if (stream) stream->prebuffer = atof(arg) * 1000; - } else if (!strcasecmp(cmd, "StartSendOnKey")) { + } else if (!av_strcasecmp(cmd, "StartSendOnKey")) { if (stream) stream->send_on_key = 1; - } else if (!strcasecmp(cmd, "AudioCodec")) { + } else if (!av_strcasecmp(cmd, "AudioCodec")) { get_arg(arg, sizeof(arg), &p); audio_id = opt_audio_codec(arg); if (audio_id == CODEC_ID_NONE) { ERROR("Unknown AudioCodec: %s\n", arg); } - } else if (!strcasecmp(cmd, "VideoCodec")) { + } else if (!av_strcasecmp(cmd, "VideoCodec")) { get_arg(arg, sizeof(arg), &p); video_id = opt_video_codec(arg); if (video_id == CODEC_ID_NONE) { ERROR("Unknown VideoCodec: %s\n", arg); } - } else if (!strcasecmp(cmd, "MaxTime")) { + } else if (!av_strcasecmp(cmd, "MaxTime")) { get_arg(arg, sizeof(arg), &p); if (stream) stream->max_time = atof(arg) * 1000; - } else if (!strcasecmp(cmd, "AudioBitRate")) { + } else if (!av_strcasecmp(cmd, "AudioBitRate")) { get_arg(arg, sizeof(arg), &p); if (stream) audio_enc.bit_rate = lrintf(atof(arg) * 1000); - } else if (!strcasecmp(cmd, "AudioChannels")) { + } else if (!av_strcasecmp(cmd, "AudioChannels")) { get_arg(arg, sizeof(arg), &p); if (stream) audio_enc.channels = atoi(arg); - } else if (!strcasecmp(cmd, "AudioSampleRate")) { + } else if (!av_strcasecmp(cmd, "AudioSampleRate")) { get_arg(arg, sizeof(arg), &p); if (stream) audio_enc.sample_rate = atoi(arg); - } else if (!strcasecmp(cmd, "AudioQuality")) { + } else if (!av_strcasecmp(cmd, "AudioQuality")) { get_arg(arg, sizeof(arg), &p); if (stream) { // audio_enc.quality = atof(arg) * 1000; } - } else if (!strcasecmp(cmd, "VideoBitRateRange")) { + } else if (!av_strcasecmp(cmd, "VideoBitRateRange")) { if (stream) { int minrate, maxrate; @@ -4363,32 +4362,32 @@ static int parse_ffconfig(const char *filename) ERROR("Incorrect format for VideoBitRateRange -- should be -: %s\n", arg); } } - } else if (!strcasecmp(cmd, "Debug")) { + } else if (!av_strcasecmp(cmd, "Debug")) { if (stream) { get_arg(arg, sizeof(arg), &p); video_enc.debug = strtol(arg,0,0); } - } else if (!strcasecmp(cmd, "Strict")) { + } else if (!av_strcasecmp(cmd, "Strict")) { if (stream) { get_arg(arg, sizeof(arg), &p); video_enc.strict_std_compliance = atoi(arg); } - } else if (!strcasecmp(cmd, "VideoBufferSize")) { + } else if (!av_strcasecmp(cmd, "VideoBufferSize")) { if (stream) { get_arg(arg, sizeof(arg), &p); video_enc.rc_buffer_size = atoi(arg) * 8*1024; } - } else if (!strcasecmp(cmd, "VideoBitRateTolerance")) { + } else if (!av_strcasecmp(cmd, "VideoBitRateTolerance")) { if (stream) { get_arg(arg, sizeof(arg), &p); video_enc.bit_rate_tolerance = atoi(arg) * 1000; } - } else if (!strcasecmp(cmd, "VideoBitRate")) { + } else if (!av_strcasecmp(cmd, "VideoBitRate")) { get_arg(arg, sizeof(arg), &p); if (stream) { video_enc.bit_rate = atoi(arg) * 1000; } - } else if (!strcasecmp(cmd, "VideoSize")) { + } else if (!av_strcasecmp(cmd, "VideoSize")) { get_arg(arg, sizeof(arg), &p); if (stream) { av_parse_video_size(&video_enc.width, &video_enc.height, arg); @@ -4397,7 +4396,7 @@ static int parse_ffconfig(const char *filename) ERROR("Image size must be a multiple of 16\n"); } } - } else if (!strcasecmp(cmd, "VideoFrameRate")) { + } else if (!av_strcasecmp(cmd, "VideoFrameRate")) { get_arg(arg, sizeof(arg), &p); if (stream) { AVRational frame_rate; @@ -4408,29 +4407,29 @@ static int parse_ffconfig(const char *filename) video_enc.time_base.den = frame_rate.num; } } - } else if (!strcasecmp(cmd, "VideoGopSize")) { + } else if (!av_strcasecmp(cmd, "VideoGopSize")) { get_arg(arg, sizeof(arg), &p); if (stream) video_enc.gop_size = atoi(arg); - } else if (!strcasecmp(cmd, "VideoIntraOnly")) { + } else if (!av_strcasecmp(cmd, "VideoIntraOnly")) { if (stream) video_enc.gop_size = 1; - } else if (!strcasecmp(cmd, "VideoHighQuality")) { + } else if (!av_strcasecmp(cmd, "VideoHighQuality")) { if (stream) video_enc.mb_decision = FF_MB_DECISION_BITS; - } else if (!strcasecmp(cmd, "Video4MotionVector")) { + } else if (!av_strcasecmp(cmd, "Video4MotionVector")) { if (stream) { video_enc.mb_decision = FF_MB_DECISION_BITS; //FIXME remove video_enc.flags |= CODEC_FLAG_4MV; } - } else if (!strcasecmp(cmd, "AVOptionVideo") || - !strcasecmp(cmd, "AVOptionAudio")) { + } else if (!av_strcasecmp(cmd, "AVOptionVideo") || + !av_strcasecmp(cmd, "AVOptionAudio")) { char arg2[1024]; AVCodecContext *avctx; int type; get_arg(arg, sizeof(arg), &p); get_arg(arg2, sizeof(arg2), &p); - if (!strcasecmp(cmd, "AVOptionVideo")) { + if (!av_strcasecmp(cmd, "AVOptionVideo")) { avctx = &video_enc; type = AV_OPT_FLAG_VIDEO_PARAM; } else { @@ -4440,12 +4439,12 @@ static int parse_ffconfig(const char *filename) if (ffserver_opt_default(arg, arg2, avctx, type|AV_OPT_FLAG_ENCODING_PARAM)) { ERROR("AVOption error: %s %s\n", arg, arg2); } - } else if (!strcasecmp(cmd, "AVPresetVideo") || - !strcasecmp(cmd, "AVPresetAudio")) { + } else if (!av_strcasecmp(cmd, "AVPresetVideo") || + !av_strcasecmp(cmd, "AVPresetAudio")) { AVCodecContext *avctx; int type; get_arg(arg, sizeof(arg), &p); - if (!strcasecmp(cmd, "AVPresetVideo")) { + if (!av_strcasecmp(cmd, "AVPresetVideo")) { avctx = &video_enc; video_enc.codec_id = video_id; type = AV_OPT_FLAG_VIDEO_PARAM; @@ -4457,26 +4456,26 @@ static int parse_ffconfig(const char *filename) if (ffserver_opt_preset(arg, avctx, type|AV_OPT_FLAG_ENCODING_PARAM, &audio_id, &video_id)) { ERROR("AVPreset error: %s\n", arg); } - } else if (!strcasecmp(cmd, "VideoTag")) { + } else if (!av_strcasecmp(cmd, "VideoTag")) { get_arg(arg, sizeof(arg), &p); if ((strlen(arg) == 4) && stream) video_enc.codec_tag = MKTAG(arg[0], arg[1], arg[2], arg[3]); - } else if (!strcasecmp(cmd, "BitExact")) { + } else if (!av_strcasecmp(cmd, "BitExact")) { if (stream) video_enc.flags |= CODEC_FLAG_BITEXACT; - } else if (!strcasecmp(cmd, "DctFastint")) { + } else if (!av_strcasecmp(cmd, "DctFastint")) { if (stream) video_enc.dct_algo = FF_DCT_FASTINT; - } else if (!strcasecmp(cmd, "IdctSimple")) { + } else if (!av_strcasecmp(cmd, "IdctSimple")) { if (stream) video_enc.idct_algo = FF_IDCT_SIMPLE; - } else if (!strcasecmp(cmd, "Qscale")) { + } else if (!av_strcasecmp(cmd, "Qscale")) { get_arg(arg, sizeof(arg), &p); if (stream) { video_enc.flags |= CODEC_FLAG_QSCALE; video_enc.global_quality = FF_QP2LAMBDA * atoi(arg); } - } else if (!strcasecmp(cmd, "VideoQDiff")) { + } else if (!av_strcasecmp(cmd, "VideoQDiff")) { get_arg(arg, sizeof(arg), &p); if (stream) { video_enc.max_qdiff = atoi(arg); @@ -4484,7 +4483,7 @@ static int parse_ffconfig(const char *filename) ERROR("VideoQDiff out of range\n"); } } - } else if (!strcasecmp(cmd, "VideoQMax")) { + } else if (!av_strcasecmp(cmd, "VideoQMax")) { get_arg(arg, sizeof(arg), &p); if (stream) { video_enc.qmax = atoi(arg); @@ -4492,7 +4491,7 @@ static int parse_ffconfig(const char *filename) ERROR("VideoQMax out of range\n"); } } - } else if (!strcasecmp(cmd, "VideoQMin")) { + } else if (!av_strcasecmp(cmd, "VideoQMin")) { get_arg(arg, sizeof(arg), &p); if (stream) { video_enc.qmin = atoi(arg); @@ -4500,39 +4499,39 @@ static int parse_ffconfig(const char *filename) ERROR("VideoQMin out of range\n"); } } - } else if (!strcasecmp(cmd, "LumaElim")) { + } else if (!av_strcasecmp(cmd, "LumaElim")) { get_arg(arg, sizeof(arg), &p); if (stream) video_enc.luma_elim_threshold = atoi(arg); - } else if (!strcasecmp(cmd, "ChromaElim")) { + } else if (!av_strcasecmp(cmd, "ChromaElim")) { get_arg(arg, sizeof(arg), &p); if (stream) video_enc.chroma_elim_threshold = atoi(arg); - } else if (!strcasecmp(cmd, "LumiMask")) { + } else if (!av_strcasecmp(cmd, "LumiMask")) { get_arg(arg, sizeof(arg), &p); if (stream) video_enc.lumi_masking = atof(arg); - } else if (!strcasecmp(cmd, "DarkMask")) { + } else if (!av_strcasecmp(cmd, "DarkMask")) { get_arg(arg, sizeof(arg), &p); if (stream) video_enc.dark_masking = atof(arg); - } else if (!strcasecmp(cmd, "NoVideo")) { + } else if (!av_strcasecmp(cmd, "NoVideo")) { video_id = CODEC_ID_NONE; - } else if (!strcasecmp(cmd, "NoAudio")) { + } else if (!av_strcasecmp(cmd, "NoAudio")) { audio_id = CODEC_ID_NONE; - } else if (!strcasecmp(cmd, "ACL")) { + } else if (!av_strcasecmp(cmd, "ACL")) { parse_acl_row(stream, feed, NULL, p, filename, line_num); - } else if (!strcasecmp(cmd, "DynamicACL")) { + } else if (!av_strcasecmp(cmd, "DynamicACL")) { if (stream) { get_arg(stream->dynamic_acl, sizeof(stream->dynamic_acl), &p); } - } else if (!strcasecmp(cmd, "RTSPOption")) { + } else if (!av_strcasecmp(cmd, "RTSPOption")) { get_arg(arg, sizeof(arg), &p); if (stream) { av_freep(&stream->rtsp_option); stream->rtsp_option = av_strdup(arg); } - } else if (!strcasecmp(cmd, "MulticastAddress")) { + } else if (!av_strcasecmp(cmd, "MulticastAddress")) { get_arg(arg, sizeof(arg), &p); if (stream) { if (resolve_host(&stream->multicast_ip, arg) != 0) { @@ -4541,18 +4540,18 @@ static int parse_ffconfig(const char *filename) stream->is_multicast = 1; stream->loop = 1; /* default is looping */ } - } else if (!strcasecmp(cmd, "MulticastPort")) { + } else if (!av_strcasecmp(cmd, "MulticastPort")) { get_arg(arg, sizeof(arg), &p); if (stream) stream->multicast_port = atoi(arg); - } else if (!strcasecmp(cmd, "MulticastTTL")) { + } else if (!av_strcasecmp(cmd, "MulticastTTL")) { get_arg(arg, sizeof(arg), &p); if (stream) stream->multicast_ttl = atoi(arg); - } else if (!strcasecmp(cmd, "NoLoop")) { + } else if (!av_strcasecmp(cmd, "NoLoop")) { if (stream) stream->loop = 0; - } else if (!strcasecmp(cmd, "")) { + } else if (!av_strcasecmp(cmd, "")) { if (!stream) { ERROR("No corresponding for \n"); } else { @@ -4570,7 +4569,7 @@ static int parse_ffconfig(const char *filename) } stream = NULL; } - } else if (!strcasecmp(cmd, "stream_type = STREAM_TYPE_REDIRECT; } - } else if (!strcasecmp(cmd, "URL")) { + } else if (!av_strcasecmp(cmd, "URL")) { if (redirect) get_arg(redirect->feed_filename, sizeof(redirect->feed_filename), &p); - } else if (!strcasecmp(cmd, "")) { + } else if (!av_strcasecmp(cmd, "")) { if (!redirect) { ERROR("No corresponding for \n"); } else { @@ -4598,7 +4597,7 @@ static int parse_ffconfig(const char *filename) } redirect = NULL; } - } else if (!strcasecmp(cmd, "LoadModule")) { + } else if (!av_strcasecmp(cmd, "LoadModule")) { get_arg(arg, sizeof(arg), &p); #if HAVE_DLOPEN load_module(arg); @@ -4673,6 +4672,7 @@ int main(int argc, char **argv) parse_loglevel(argc, argv, options); av_register_all(); + avformat_network_init(); show_banner(); diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 27c6f5e9f5..aedacd76c8 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -153,7 +153,9 @@ enum CodecID { CODEC_ID_TIERTEXSEQVIDEO, CODEC_ID_TIFF, CODEC_ID_GIF, +#if LIBAVCODEC_VERSION_MAJOR == 53 CODEC_ID_FFH264, +#endif CODEC_ID_DXA, CODEC_ID_DNXHD, CODEC_ID_THP, @@ -171,8 +173,10 @@ enum CodecID { CODEC_ID_INDEO5, CODEC_ID_MIMIC, CODEC_ID_RL2, +#if LIBAVCODEC_VERSION_MAJOR == 53 CODEC_ID_8SVX_EXP, CODEC_ID_8SVX_FIB, +#endif CODEC_ID_ESCAPE124, CODEC_ID_DIRAC, CODEC_ID_BFI, @@ -222,7 +226,7 @@ enum CodecID { /* various PCM "codecs" */ CODEC_ID_FIRST_AUDIO = 0x10000, ///< A dummy id pointing at the start of audio codecs - CODEC_ID_PCM_S16LE= 0x10000, + CODEC_ID_PCM_S16LE = 0x10000, CODEC_ID_PCM_S16BE, CODEC_ID_PCM_U16LE, CODEC_ID_PCM_U16BE, @@ -251,7 +255,7 @@ enum CodecID { CODEC_ID_S302M, /* various ADPCM codecs */ - CODEC_ID_ADPCM_IMA_QT= 0x11000, + CODEC_ID_ADPCM_IMA_QT = 0x11000, CODEC_ID_ADPCM_IMA_WAV, CODEC_ID_ADPCM_IMA_DK3, CODEC_ID_ADPCM_IMA_DK4, @@ -282,21 +286,21 @@ enum CodecID { CODEC_ID_ADPCM_G722, /* AMR */ - CODEC_ID_AMR_NB= 0x12000, + CODEC_ID_AMR_NB = 0x12000, CODEC_ID_AMR_WB, /* RealAudio codecs*/ - CODEC_ID_RA_144= 0x13000, + CODEC_ID_RA_144 = 0x13000, CODEC_ID_RA_288, /* various DPCM codecs */ - CODEC_ID_ROQ_DPCM= 0x14000, + CODEC_ID_ROQ_DPCM = 0x14000, CODEC_ID_INTERPLAY_DPCM, CODEC_ID_XAN_DPCM, CODEC_ID_SOL_DPCM, /* audio codecs */ - CODEC_ID_MP2= 0x15000, + CODEC_ID_MP2 = 0x15000, CODEC_ID_MP3, ///< preferred ID for decoding MPEG audio layer 1, 2 or 3 CODEC_ID_AAC, CODEC_ID_AC3, @@ -308,8 +312,10 @@ enum CodecID { CODEC_ID_MACE3, CODEC_ID_MACE6, CODEC_ID_VMDAUDIO, +#if LIBAVCODEC_VERSION_MAJOR == 53 CODEC_ID_SONIC, CODEC_ID_SONIC_LS, +#endif CODEC_ID_FLAC, CODEC_ID_MP3ADU, CODEC_ID_MP3ON4, @@ -354,6 +360,8 @@ enum CodecID { #if LIBAVCODEC_VERSION_MAJOR > 53 CODEC_ID_G723_1_DEPRECATED, CODEC_ID_G729_DEPRECATED, + CODEC_ID_8SVX_EXP, + CODEC_ID_8SVX_FIB, #endif CODEC_ID_G729 = 0x15800, CODEC_ID_G723_1= 0x15801, @@ -361,7 +369,7 @@ enum CodecID { /* subtitle codecs */ CODEC_ID_FIRST_SUBTITLE = 0x17000, ///< A dummy ID pointing at the start of subtitle codecs. - CODEC_ID_DVD_SUBTITLE= 0x17000, + CODEC_ID_DVD_SUBTITLE = 0x17000, CODEC_ID_DVB_SUBTITLE, CODEC_ID_TEXT, ///< raw UTF-8 text CODEC_ID_XSUB, @@ -374,18 +382,18 @@ enum CodecID { /* other specific kind of codecs (generally used for attachments) */ CODEC_ID_FIRST_UNKNOWN = 0x18000, ///< A dummy ID pointing at the start of various fake codecs. - CODEC_ID_TTF= 0x18000, + CODEC_ID_TTF = 0x18000, CODEC_ID_BINTEXT = MKBETAG('B','T','X','T'), CODEC_ID_XBIN = MKBETAG('X','B','I','N'), CODEC_ID_IDF = MKBETAG( 0 ,'I','D','F'), - CODEC_ID_PROBE= 0x19000, ///< codec_id is not known (like CODEC_ID_NONE) but lavf should attempt to identify it + CODEC_ID_PROBE = 0x19000, ///< codec_id is not known (like CODEC_ID_NONE) but lavf should attempt to identify it - CODEC_ID_MPEG2TS= 0x20000, /**< _FAKE_ codec to indicate a raw MPEG-2 TS + CODEC_ID_MPEG2TS = 0x20000, /**< _FAKE_ codec to indicate a raw MPEG-2 TS * stream (only used by libavformat) */ CODEC_ID_MPEG4SYSTEMS = 0x20001, /**< _FAKE_ codec to indicate a MPEG-4 Systems * stream (only used by libavformat) */ - CODEC_ID_FFMETADATA=0x21000, ///< Dummy codec for streams containing only metadata information. + CODEC_ID_FFMETADATA = 0x21000, ///< Dummy codec for streams containing only metadata information. }; #if FF_API_OLD_SAMPLE_FMT diff --git a/libavdevice/bktr.c b/libavdevice/bktr.c index db917c450a..72f0cc272e 100644 --- a/libavdevice/bktr.c +++ b/libavdevice/bktr.c @@ -46,7 +46,6 @@ #include #include #include -#include #include "avdevice.h" typedef struct { diff --git a/libavdevice/dv1394.c b/libavdevice/dv1394.c index 44d401a99f..30bbe6b482 100644 --- a/libavdevice/dv1394.c +++ b/libavdevice/dv1394.c @@ -28,7 +28,6 @@ #include #include #include -#include #include "libavutil/log.h" #include "libavutil/opt.h" diff --git a/libavdevice/v4l.c b/libavdevice/v4l.c index 3e5e5eb919..bbb58fbded 100644 --- a/libavdevice/v4l.c +++ b/libavdevice/v4l.c @@ -38,7 +38,6 @@ #define _LINUX_TIME_H 1 #include #include -#include #include "avdevice.h" typedef struct { diff --git a/libavformat/network.c b/libavformat/network.c index 33435cf524..e5482a1475 100644 --- a/libavformat/network.c +++ b/libavformat/network.c @@ -46,7 +46,7 @@ static void openssl_lock(int mode, int type, const char *file, int line) else pthread_mutex_unlock(&openssl_mutexes[type]); } -#ifndef WIN32 +#if !defined(WIN32) && OPENSSL_VERSION_NUMBER < 0x10000000 static unsigned long openssl_thread_id(void) { return (intptr_t) pthread_self(); @@ -79,7 +79,7 @@ void ff_tls_init(void) for (i = 0; i < CRYPTO_num_locks(); i++) pthread_mutex_init(&openssl_mutexes[i], NULL); CRYPTO_set_locking_callback(openssl_lock); -#ifndef WIN32 +#if !defined(WIN32) && OPENSSL_VERSION_NUMBER < 0x10000000 CRYPTO_set_id_callback(openssl_thread_id); #endif } diff --git a/libavformat/os_support.c b/libavformat/os_support.c index a242693cc1..467053e196 100644 --- a/libavformat/os_support.c +++ b/libavformat/os_support.c @@ -71,7 +71,6 @@ int ff_win32_open(const char *filename_utf8, int oflag, int pmode) #if !HAVE_INET_ATON #include -#include int ff_inet_aton (const char * str, struct in_addr * add) { diff --git a/libavformat/rtpdec_latm.c b/libavformat/rtpdec_latm.c index 4bf2c3fb23..f08415dde7 100644 --- a/libavformat/rtpdec_latm.c +++ b/libavformat/rtpdec_latm.c @@ -23,7 +23,6 @@ #include "internal.h" #include "libavutil/avstring.h" #include "libavcodec/get_bits.h" -#include struct PayloadContext { AVIOContext *dyn_buf; diff --git a/libavformat/utils.c b/libavformat/utils.c index f52c93d8bf..35a6ab89a5 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -1434,7 +1434,7 @@ void ff_read_frame_flush(AVFormatContext *s) #if FF_API_SEEK_PUBLIC void av_update_cur_dts(AVFormatContext *s, AVStream *ref_st, int64_t timestamp) { - return ff_update_cur_dts(s, ref_st, timestamp); + ff_update_cur_dts(s, ref_st, timestamp); } #endif diff --git a/libavutil/avstring.c b/libavutil/avstring.c index d167d5245e..76f6bb2c9b 100644 --- a/libavutil/avstring.c +++ b/libavutil/avstring.c @@ -189,16 +189,12 @@ char *av_strtok(char *s, const char *delim, char **saveptr) return tok; } -#define TOUPPER(c) do { if (c >= 'a' && c <= 'z') c -= 'a' - 'A'; } while (0) - int av_strcasecmp(const char *a, const char *b) { uint8_t c1, c2; do { - c1 = *a++; - c2 = *b++; - TOUPPER(c1); - TOUPPER(c2); + c1 = av_tolower(*a++); + c2 = av_tolower(*b++); } while (c1 && c1 == c2); return c1 - c2; } @@ -208,10 +204,8 @@ int av_strncasecmp(const char *a, const char *b, size_t n) const char *end = a + n; uint8_t c1, c2; do { - c1 = *a++; - c2 = *b++; - TOUPPER(c1); - TOUPPER(c2); + c1 = av_tolower(*a++); + c2 = av_tolower(*b++); } while (a < end && c1 && c1 == c2); return c1 - c2; } diff --git a/libavutil/avstring.h b/libavutil/avstring.h index 3fb3fbaf04..4ea64e46a9 100644 --- a/libavutil/avstring.h +++ b/libavutil/avstring.h @@ -165,6 +165,26 @@ char *av_get_token(const char **buf, const char *term); */ char *av_strtok(char *s, const char *delim, char **saveptr); +/** + * Locale independent conversion of ASCII characters to upper case. + */ +static inline int av_toupper(int c) +{ + if (c >= 'a' && c <= 'z') + c ^= 0x20; + return c; +} + +/** + * Locale independent conversion of ASCII characters to lower case. + */ +static inline int av_tolower(int c) +{ + if (c >= 'A' && c <= 'Z') + c ^= 0x20; + return c; +} + /** * Locale independent case-insensitive compare. * Note: This means only ASCII-range characters are case-insensitive diff --git a/libavutil/avutil.h b/libavutil/avutil.h index 94e42714f1..6c32787743 100644 --- a/libavutil/avutil.h +++ b/libavutil/avutil.h @@ -40,7 +40,7 @@ #define AV_VERSION(a, b, c) AV_VERSION_DOT(a, b, c) #define LIBAVUTIL_VERSION_MAJOR 51 -#define LIBAVUTIL_VERSION_MINOR 23 +#define LIBAVUTIL_VERSION_MINOR 24 #define LIBAVUTIL_VERSION_MICRO 0 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ diff --git a/libavutil/dict.c b/libavutil/dict.c index a0e7fb4c0e..6177ddd335 100644 --- a/libavutil/dict.c +++ b/libavutil/dict.c @@ -18,7 +18,6 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include #include "avstring.h" #include "dict.h" #include "internal.h" diff --git a/libavutil/x86/x86inc.asm b/libavutil/x86/x86inc.asm index c84d5566a2..31f74b9b3e 100644 --- a/libavutil/x86/x86inc.asm +++ b/libavutil/x86/x86inc.asm @@ -1,5 +1,5 @@ ;***************************************************************************** -;* x86inc.asm +;* x86inc.asm: x264asm abstraction layer ;***************************************************************************** ;* Copyright (C) 2005-2011 x264 project ;* @@ -112,7 +112,7 @@ ; we need more flexible macro. ; RET: -; Pops anything that was pushed by PROLOGUE +; Pops anything that was pushed by PROLOGUE, and returns. ; REP_RET: ; Same, but if it doesn't pop anything it becomes a 2-byte ret, for athlons @@ -297,6 +297,9 @@ DECLARE_REG 6, rax, eax, ax, al, [rsp + stack_offset + 56] %macro WIN64_SPILL_XMM 1 %assign xmm_regs_used %1 + %if mmsize == 8 + %assign xmm_regs_used 0 + %endif ASSERT xmm_regs_used <= 16 %if xmm_regs_used > 6 sub rsp, (xmm_regs_used-6)*16+16 @@ -459,10 +462,24 @@ DECLARE_REG 6, ebp, ebp, bp, null, [esp + stack_offset + 28] %assign function_align 16 -; Symbol prefix for C linkage -%macro cglobal 1-2+ - %xdefine %1 mangle(program_name %+ _ %+ %1) - %xdefine %1.skip_prologue %1 %+ .skip_prologue +; Begin a function. +; Applies any symbol mangling needed for C linkage, and sets up a define such that +; subsequent uses of the function name automatically refer to the mangled version. +; Appends cpuflags to the function name if cpuflags has been specified. +%macro cglobal 1-2+ ; name, [PROLOGUE args] +%if %0 == 1 + cglobal_internal %1 %+ SUFFIX +%else + cglobal_internal %1 %+ SUFFIX, %2 +%endif +%endmacro +%macro cglobal_internal 1-2+ + %ifndef cglobaled_%1 + %xdefine %1 mangle(program_name %+ _ %+ %1) + %xdefine %1.skip_prologue %1 %+ .skip_prologue + CAT_XDEFINE cglobaled_, %1, 1 + %endif + %xdefine current_function %1 %ifidn __OUTPUT_FORMAT__,elf global %1:function hidden %else @@ -479,12 +496,14 @@ DECLARE_REG 6, ebp, ebp, bp, null, [esp + stack_offset + 28] %macro cextern 1 %xdefine %1 mangle(program_name %+ _ %+ %1) + CAT_XDEFINE cglobaled_, %1, 1 extern %1 %endmacro -;like cextern, but without the prefix +; like cextern, but without the prefix %macro cextern_naked 1 %xdefine %1 mangle(%1) + CAT_XDEFINE cglobaled_, %1, 1 extern %1 %endmacro @@ -500,6 +519,66 @@ DECLARE_REG 6, ebp, ebp, bp, null, [esp + stack_offset + 28] SECTION .note.GNU-stack noalloc noexec nowrite progbits %endif +; cpuflags + +%assign cpuflags_mmx (1<<0) +%assign cpuflags_mmx2 (1<<1) | cpuflags_mmx +%assign cpuflags_3dnow (1<<2) | cpuflags_mmx +%assign cpuflags_3dnow2 (1<<3) | cpuflags_3dnow +%assign cpuflags_sse (1<<4) | cpuflags_mmx2 +%assign cpuflags_sse2 (1<<5) | cpuflags_sse +%assign cpuflags_sse2slow (1<<6) | cpuflags_sse2 +%assign cpuflags_sse3 (1<<7) | cpuflags_sse2 +%assign cpuflags_ssse3 (1<<8) | cpuflags_sse3 +%assign cpuflags_sse4 (1<<9) | cpuflags_ssse3 +%assign cpuflags_sse42 (1<<10)| cpuflags_sse4 +%assign cpuflags_avx (1<<11)| cpuflags_sse42 +%assign cpuflags_xop (1<<12)| cpuflags_avx +%assign cpuflags_fma4 (1<<13)| cpuflags_avx + +%assign cpuflags_cache32 (1<<16) +%assign cpuflags_cache64 (1<<17) +%assign cpuflags_slowctz (1<<18) +%assign cpuflags_lzcnt (1<<19) +%assign cpuflags_misalign (1<<20) +%assign cpuflags_aligned (1<<21) ; not a cpu feature, but a function variant +%assign cpuflags_atom (1<<22) + +%define cpuflag(x) ((cpuflags & (cpuflags_ %+ x)) == (cpuflags_ %+ x)) +%define notcpuflag(x) ((cpuflags & (cpuflags_ %+ x)) != (cpuflags_ %+ x)) + +; Takes up to 2 cpuflags from the above list. +; All subsequent functions (up to the next INIT_CPUFLAGS) is built for the specified cpu. +; You shouldn't need to invoke this macro directly, it's a subroutine for INIT_MMX &co. +%macro INIT_CPUFLAGS 0-2 + %if %0 >= 1 + %xdefine cpuname %1 + %assign cpuflags cpuflags_%1 + %if %0 >= 2 + %xdefine cpuname %1_%2 + %assign cpuflags cpuflags | cpuflags_%2 + %endif + %xdefine SUFFIX _ %+ cpuname + %if cpuflag(avx) + %assign avx_enabled 1 + %endif + %if mmsize == 16 && notcpuflag(sse2) + %define mova movaps + %define movu movups + %define movnta movntps + %endif + %if cpuflag(aligned) + %define movu mova + %elifidn %1, sse3 + %define movu lddqu + %endif + %else + %xdefine SUFFIX + %undef cpuname + %undef cpuflags + %endif +%endmacro + ; merge mmx and sse* %macro CAT_XDEFINE 3 @@ -510,9 +589,9 @@ SECTION .note.GNU-stack noalloc noexec nowrite progbits %undef %1%2 %endmacro -%macro INIT_MMX 0 +%macro INIT_MMX 0-1+ %assign avx_enabled 0 - %define RESET_MM_PERMUTATION INIT_MMX + %define RESET_MM_PERMUTATION INIT_MMX %1 %define mmsize 8 %define num_mmregs 8 %define mova movq @@ -530,11 +609,12 @@ SECTION .note.GNU-stack noalloc noexec nowrite progbits CAT_UNDEF nmm, %%i %assign %%i %%i+1 %endrep + INIT_CPUFLAGS %1 %endmacro -%macro INIT_XMM 0 +%macro INIT_XMM 0-1+ %assign avx_enabled 0 - %define RESET_MM_PERMUTATION INIT_XMM + %define RESET_MM_PERMUTATION INIT_XMM %1 %define mmsize 16 %define num_mmregs 8 %ifdef ARCH_X86_64 @@ -550,8 +630,10 @@ SECTION .note.GNU-stack noalloc noexec nowrite progbits CAT_XDEFINE nxmm, %%i, %%i %assign %%i %%i+1 %endrep + INIT_CPUFLAGS %1 %endmacro +; FIXME: INIT_AVX can be replaced by INIT_XMM avx %macro INIT_AVX 0 INIT_XMM %assign avx_enabled 1 @@ -559,9 +641,9 @@ SECTION .note.GNU-stack noalloc noexec nowrite progbits %define RESET_MM_PERMUTATION INIT_AVX %endmacro -%macro INIT_YMM 0 +%macro INIT_YMM 0-1+ %assign avx_enabled 1 - %define RESET_MM_PERMUTATION INIT_YMM + %define RESET_MM_PERMUTATION INIT_YMM %1 %define mmsize 32 %define num_mmregs 8 %ifdef ARCH_X86_64 @@ -569,15 +651,18 @@ SECTION .note.GNU-stack noalloc noexec nowrite progbits %endif %define mova vmovaps %define movu vmovups + %undef movh + %define movnta vmovntps %assign %%i 0 %rep num_mmregs CAT_XDEFINE m, %%i, ymm %+ %%i CAT_XDEFINE nymm, %%i, %%i %assign %%i %%i+1 %endrep + INIT_CPUFLAGS %1 %endmacro -INIT_MMX +INIT_XMM ; I often want to use macros that permute their arguments. e.g. there's no ; efficient way to implement butterfly or transpose or dct without swapping some @@ -633,31 +718,46 @@ INIT_MMX %endrep %endmacro -; If SAVE_MM_PERMUTATION is placed at the end of a function and given the -; function name, then any later calls to that function will automatically -; load the permutation, so values can be returned in mmregs. -%macro SAVE_MM_PERMUTATION 1 ; name to save as +; If SAVE_MM_PERMUTATION is placed at the end of a function, then any later +; calls to that function will automatically load the permutation, so values can +; be returned in mmregs. +%macro SAVE_MM_PERMUTATION 0-1 + %if %0 + %xdefine %%f %1_m + %else + %xdefine %%f current_function %+ _m + %endif %assign %%i 0 %rep num_mmregs - CAT_XDEFINE %1_m, %%i, m %+ %%i + CAT_XDEFINE %%f, %%i, m %+ %%i %assign %%i %%i+1 %endrep %endmacro %macro LOAD_MM_PERMUTATION 1 ; name to load from - %assign %%i 0 - %rep num_mmregs - CAT_XDEFINE m, %%i, %1_m %+ %%i - CAT_XDEFINE n, m %+ %%i, %%i - %assign %%i %%i+1 - %endrep + %ifdef %1_m0 + %assign %%i 0 + %rep num_mmregs + CAT_XDEFINE m, %%i, %1_m %+ %%i + CAT_XDEFINE n, m %+ %%i, %%i + %assign %%i %%i+1 + %endrep + %endif %endmacro +; Append cpuflags to the callee's name iff the appended name is known and the plain name isn't %macro call 1 - call %1 - %ifdef %1_m0 - LOAD_MM_PERMUTATION %1 + call_internal %1, %1 %+ SUFFIX +%endmacro +%macro call_internal 2 + %xdefine %%i %1 + %ifndef cglobaled_%1 + %ifdef cglobaled_%2 + %xdefine %%i %2 + %endif %endif + call %%i + LOAD_MM_PERMUTATION %%i %endmacro ; Substitutions that reduce instruction size but are functionally equivalent @@ -702,14 +802,19 @@ INIT_MMX ;%1 == instruction ;%2 == 1 if float, 0 if int -;%3 == 0 if 3-operand (xmm, xmm, xmm), 1 if 4-operand (xmm, xmm, xmm, imm) +;%3 == 1 if 4-operand (xmm, xmm, xmm, imm), 0 if 3-operand (xmm, xmm, xmm) ;%4 == number of operands given ;%5+: operands %macro RUN_AVX_INSTR 6-7+ - %if sizeof%5==32 + %ifid %5 + %define %%size sizeof%5 + %else + %define %%size mmsize + %endif + %if %%size==32 v%1 %5, %6, %7 %else - %if sizeof%5==8 + %if %%size==8 %define %%regmov movq %elif %2 %define %%regmov movaps @@ -736,15 +841,37 @@ INIT_MMX %endif %endmacro +; 3arg AVX ops with a memory arg can only have it in src2, +; whereas SSE emulation of 3arg prefers to have it in src1 (i.e. the mov). +; So, if the op is symmetric and the wrong one is memory, swap them. +%macro RUN_AVX_INSTR1 8 + %assign %%swap 0 + %if avx_enabled + %ifnid %6 + %assign %%swap 1 + %endif + %elifnidn %5, %6 + %ifnid %7 + %assign %%swap 1 + %endif + %endif + %if %%swap && %3 == 0 && %8 == 1 + RUN_AVX_INSTR %1, %2, %3, %4, %5, %7, %6 + %else + RUN_AVX_INSTR %1, %2, %3, %4, %5, %6, %7 + %endif +%endmacro + ;%1 == instruction ;%2 == 1 if float, 0 if int -;%3 == 0 if 3-operand (xmm, xmm, xmm), 1 if 4-operand (xmm, xmm, xmm, imm) -%macro AVX_INSTR 3 - %macro %1 2-8 fnord, fnord, fnord, %1, %2, %3 +;%3 == 1 if 4-operand (xmm, xmm, xmm, imm), 0 if 3-operand (xmm, xmm, xmm) +;%4 == 1 if symmetric (i.e. doesn't matter which src arg is which), 0 if not +%macro AVX_INSTR 4 + %macro %1 2-9 fnord, fnord, fnord, %1, %2, %3, %4 %ifidn %3, fnord RUN_AVX_INSTR %6, %7, %8, 2, %1, %2 %elifidn %4, fnord - RUN_AVX_INSTR %6, %7, %8, 3, %1, %2, %3 + RUN_AVX_INSTR1 %6, %7, %8, 3, %1, %2, %3, %9 %elifidn %5, fnord RUN_AVX_INSTR %6, %7, %8, 4, %1, %2, %3, %4 %else @@ -753,153 +880,188 @@ INIT_MMX %endmacro %endmacro -AVX_INSTR addpd, 1, 0 -AVX_INSTR addps, 1, 0 -AVX_INSTR addsd, 1, 0 -AVX_INSTR addss, 1, 0 -AVX_INSTR addsubpd, 1, 0 -AVX_INSTR addsubps, 1, 0 -AVX_INSTR andpd, 1, 0 -AVX_INSTR andps, 1, 0 -AVX_INSTR andnpd, 1, 0 -AVX_INSTR andnps, 1, 0 -AVX_INSTR blendpd, 1, 0 -AVX_INSTR blendps, 1, 0 -AVX_INSTR blendvpd, 1, 0 -AVX_INSTR blendvps, 1, 0 -AVX_INSTR cmppd, 1, 0 -AVX_INSTR cmpps, 1, 0 -AVX_INSTR cmpsd, 1, 0 -AVX_INSTR cmpss, 1, 0 -AVX_INSTR divpd, 1, 0 -AVX_INSTR divps, 1, 0 -AVX_INSTR divsd, 1, 0 -AVX_INSTR divss, 1, 0 -AVX_INSTR dppd, 1, 0 -AVX_INSTR dpps, 1, 0 -AVX_INSTR haddpd, 1, 0 -AVX_INSTR haddps, 1, 0 -AVX_INSTR hsubpd, 1, 0 -AVX_INSTR hsubps, 1, 0 -AVX_INSTR maxpd, 1, 0 -AVX_INSTR maxps, 1, 0 -AVX_INSTR maxsd, 1, 0 -AVX_INSTR maxss, 1, 0 -AVX_INSTR minpd, 1, 0 -AVX_INSTR minps, 1, 0 -AVX_INSTR minsd, 1, 0 -AVX_INSTR minss, 1, 0 -AVX_INSTR mpsadbw, 0, 1 -AVX_INSTR mulpd, 1, 0 -AVX_INSTR mulps, 1, 0 -AVX_INSTR mulsd, 1, 0 -AVX_INSTR mulss, 1, 0 -AVX_INSTR orpd, 1, 0 -AVX_INSTR orps, 1, 0 -AVX_INSTR packsswb, 0, 0 -AVX_INSTR packssdw, 0, 0 -AVX_INSTR packuswb, 0, 0 -AVX_INSTR packusdw, 0, 0 -AVX_INSTR paddb, 0, 0 -AVX_INSTR paddw, 0, 0 -AVX_INSTR paddd, 0, 0 -AVX_INSTR paddq, 0, 0 -AVX_INSTR paddsb, 0, 0 -AVX_INSTR paddsw, 0, 0 -AVX_INSTR paddusb, 0, 0 -AVX_INSTR paddusw, 0, 0 -AVX_INSTR palignr, 0, 1 -AVX_INSTR pand, 0, 0 -AVX_INSTR pandn, 0, 0 -AVX_INSTR pavgb, 0, 0 -AVX_INSTR pavgw, 0, 0 -AVX_INSTR pblendvb, 0, 0 -AVX_INSTR pblendw, 0, 1 -AVX_INSTR pcmpestri, 0, 0 -AVX_INSTR pcmpestrm, 0, 0 -AVX_INSTR pcmpistri, 0, 0 -AVX_INSTR pcmpistrm, 0, 0 -AVX_INSTR pcmpeqb, 0, 0 -AVX_INSTR pcmpeqw, 0, 0 -AVX_INSTR pcmpeqd, 0, 0 -AVX_INSTR pcmpeqq, 0, 0 -AVX_INSTR pcmpgtb, 0, 0 -AVX_INSTR pcmpgtw, 0, 0 -AVX_INSTR pcmpgtd, 0, 0 -AVX_INSTR pcmpgtq, 0, 0 -AVX_INSTR phaddw, 0, 0 -AVX_INSTR phaddd, 0, 0 -AVX_INSTR phaddsw, 0, 0 -AVX_INSTR phsubw, 0, 0 -AVX_INSTR phsubd, 0, 0 -AVX_INSTR phsubsw, 0, 0 -AVX_INSTR pmaddwd, 0, 0 -AVX_INSTR pmaddubsw, 0, 0 -AVX_INSTR pmaxsb, 0, 0 -AVX_INSTR pmaxsw, 0, 0 -AVX_INSTR pmaxsd, 0, 0 -AVX_INSTR pmaxub, 0, 0 -AVX_INSTR pmaxuw, 0, 0 -AVX_INSTR pmaxud, 0, 0 -AVX_INSTR pminsb, 0, 0 -AVX_INSTR pminsw, 0, 0 -AVX_INSTR pminsd, 0, 0 -AVX_INSTR pminub, 0, 0 -AVX_INSTR pminuw, 0, 0 -AVX_INSTR pminud, 0, 0 -AVX_INSTR pmulhuw, 0, 0 -AVX_INSTR pmulhrsw, 0, 0 -AVX_INSTR pmulhw, 0, 0 -AVX_INSTR pmullw, 0, 0 -AVX_INSTR pmulld, 0, 0 -AVX_INSTR pmuludq, 0, 0 -AVX_INSTR pmuldq, 0, 0 -AVX_INSTR por, 0, 0 -AVX_INSTR psadbw, 0, 0 -AVX_INSTR pshufb, 0, 0 -AVX_INSTR psignb, 0, 0 -AVX_INSTR psignw, 0, 0 -AVX_INSTR psignd, 0, 0 -AVX_INSTR psllw, 0, 0 -AVX_INSTR pslld, 0, 0 -AVX_INSTR psllq, 0, 0 -AVX_INSTR pslldq, 0, 0 -AVX_INSTR psraw, 0, 0 -AVX_INSTR psrad, 0, 0 -AVX_INSTR psrlw, 0, 0 -AVX_INSTR psrld, 0, 0 -AVX_INSTR psrlq, 0, 0 -AVX_INSTR psrldq, 0, 0 -AVX_INSTR psubb, 0, 0 -AVX_INSTR psubw, 0, 0 -AVX_INSTR psubd, 0, 0 -AVX_INSTR psubq, 0, 0 -AVX_INSTR psubsb, 0, 0 -AVX_INSTR psubsw, 0, 0 -AVX_INSTR psubusb, 0, 0 -AVX_INSTR psubusw, 0, 0 -AVX_INSTR punpckhbw, 0, 0 -AVX_INSTR punpckhwd, 0, 0 -AVX_INSTR punpckhdq, 0, 0 -AVX_INSTR punpckhqdq, 0, 0 -AVX_INSTR punpcklbw, 0, 0 -AVX_INSTR punpcklwd, 0, 0 -AVX_INSTR punpckldq, 0, 0 -AVX_INSTR punpcklqdq, 0, 0 -AVX_INSTR pxor, 0, 0 -AVX_INSTR shufps, 0, 1 -AVX_INSTR subpd, 1, 0 -AVX_INSTR subps, 1, 0 -AVX_INSTR subsd, 1, 0 -AVX_INSTR subss, 1, 0 -AVX_INSTR unpckhpd, 1, 0 -AVX_INSTR unpckhps, 1, 0 -AVX_INSTR unpcklpd, 1, 0 -AVX_INSTR unpcklps, 1, 0 -AVX_INSTR xorpd, 1, 0 -AVX_INSTR xorps, 1, 0 +AVX_INSTR addpd, 1, 0, 1 +AVX_INSTR addps, 1, 0, 1 +AVX_INSTR addsd, 1, 0, 1 +AVX_INSTR addss, 1, 0, 1 +AVX_INSTR addsubpd, 1, 0, 0 +AVX_INSTR addsubps, 1, 0, 0 +AVX_INSTR andpd, 1, 0, 1 +AVX_INSTR andps, 1, 0, 1 +AVX_INSTR andnpd, 1, 0, 0 +AVX_INSTR andnps, 1, 0, 0 +AVX_INSTR blendpd, 1, 0, 0 +AVX_INSTR blendps, 1, 0, 0 +AVX_INSTR blendvpd, 1, 0, 0 +AVX_INSTR blendvps, 1, 0, 0 +AVX_INSTR cmppd, 1, 0, 0 +AVX_INSTR cmpps, 1, 0, 0 +AVX_INSTR cmpsd, 1, 0, 0 +AVX_INSTR cmpss, 1, 0, 0 +AVX_INSTR divpd, 1, 0, 0 +AVX_INSTR divps, 1, 0, 0 +AVX_INSTR divsd, 1, 0, 0 +AVX_INSTR divss, 1, 0, 0 +AVX_INSTR dppd, 1, 1, 0 +AVX_INSTR dpps, 1, 1, 0 +AVX_INSTR haddpd, 1, 0, 0 +AVX_INSTR haddps, 1, 0, 0 +AVX_INSTR hsubpd, 1, 0, 0 +AVX_INSTR hsubps, 1, 0, 0 +AVX_INSTR maxpd, 1, 0, 1 +AVX_INSTR maxps, 1, 0, 1 +AVX_INSTR maxsd, 1, 0, 1 +AVX_INSTR maxss, 1, 0, 1 +AVX_INSTR minpd, 1, 0, 1 +AVX_INSTR minps, 1, 0, 1 +AVX_INSTR minsd, 1, 0, 1 +AVX_INSTR minss, 1, 0, 1 +AVX_INSTR movsd, 1, 0, 0 +AVX_INSTR movss, 1, 0, 0 +AVX_INSTR mpsadbw, 0, 1, 0 +AVX_INSTR mulpd, 1, 0, 1 +AVX_INSTR mulps, 1, 0, 1 +AVX_INSTR mulsd, 1, 0, 1 +AVX_INSTR mulss, 1, 0, 1 +AVX_INSTR orpd, 1, 0, 1 +AVX_INSTR orps, 1, 0, 1 +AVX_INSTR packsswb, 0, 0, 0 +AVX_INSTR packssdw, 0, 0, 0 +AVX_INSTR packuswb, 0, 0, 0 +AVX_INSTR packusdw, 0, 0, 0 +AVX_INSTR paddb, 0, 0, 1 +AVX_INSTR paddw, 0, 0, 1 +AVX_INSTR paddd, 0, 0, 1 +AVX_INSTR paddq, 0, 0, 1 +AVX_INSTR paddsb, 0, 0, 1 +AVX_INSTR paddsw, 0, 0, 1 +AVX_INSTR paddusb, 0, 0, 1 +AVX_INSTR paddusw, 0, 0, 1 +AVX_INSTR palignr, 0, 1, 0 +AVX_INSTR pand, 0, 0, 1 +AVX_INSTR pandn, 0, 0, 0 +AVX_INSTR pavgb, 0, 0, 1 +AVX_INSTR pavgw, 0, 0, 1 +AVX_INSTR pblendvb, 0, 0, 0 +AVX_INSTR pblendw, 0, 1, 0 +AVX_INSTR pcmpestri, 0, 0, 0 +AVX_INSTR pcmpestrm, 0, 0, 0 +AVX_INSTR pcmpistri, 0, 0, 0 +AVX_INSTR pcmpistrm, 0, 0, 0 +AVX_INSTR pcmpeqb, 0, 0, 1 +AVX_INSTR pcmpeqw, 0, 0, 1 +AVX_INSTR pcmpeqd, 0, 0, 1 +AVX_INSTR pcmpeqq, 0, 0, 1 +AVX_INSTR pcmpgtb, 0, 0, 0 +AVX_INSTR pcmpgtw, 0, 0, 0 +AVX_INSTR pcmpgtd, 0, 0, 0 +AVX_INSTR pcmpgtq, 0, 0, 0 +AVX_INSTR phaddw, 0, 0, 0 +AVX_INSTR phaddd, 0, 0, 0 +AVX_INSTR phaddsw, 0, 0, 0 +AVX_INSTR phsubw, 0, 0, 0 +AVX_INSTR phsubd, 0, 0, 0 +AVX_INSTR phsubsw, 0, 0, 0 +AVX_INSTR pmaddwd, 0, 0, 1 +AVX_INSTR pmaddubsw, 0, 0, 0 +AVX_INSTR pmaxsb, 0, 0, 1 +AVX_INSTR pmaxsw, 0, 0, 1 +AVX_INSTR pmaxsd, 0, 0, 1 +AVX_INSTR pmaxub, 0, 0, 1 +AVX_INSTR pmaxuw, 0, 0, 1 +AVX_INSTR pmaxud, 0, 0, 1 +AVX_INSTR pminsb, 0, 0, 1 +AVX_INSTR pminsw, 0, 0, 1 +AVX_INSTR pminsd, 0, 0, 1 +AVX_INSTR pminub, 0, 0, 1 +AVX_INSTR pminuw, 0, 0, 1 +AVX_INSTR pminud, 0, 0, 1 +AVX_INSTR pmulhuw, 0, 0, 1 +AVX_INSTR pmulhrsw, 0, 0, 1 +AVX_INSTR pmulhw, 0, 0, 1 +AVX_INSTR pmullw, 0, 0, 1 +AVX_INSTR pmulld, 0, 0, 1 +AVX_INSTR pmuludq, 0, 0, 1 +AVX_INSTR pmuldq, 0, 0, 1 +AVX_INSTR por, 0, 0, 1 +AVX_INSTR psadbw, 0, 0, 1 +AVX_INSTR pshufb, 0, 0, 0 +AVX_INSTR psignb, 0, 0, 0 +AVX_INSTR psignw, 0, 0, 0 +AVX_INSTR psignd, 0, 0, 0 +AVX_INSTR psllw, 0, 0, 0 +AVX_INSTR pslld, 0, 0, 0 +AVX_INSTR psllq, 0, 0, 0 +AVX_INSTR pslldq, 0, 0, 0 +AVX_INSTR psraw, 0, 0, 0 +AVX_INSTR psrad, 0, 0, 0 +AVX_INSTR psrlw, 0, 0, 0 +AVX_INSTR psrld, 0, 0, 0 +AVX_INSTR psrlq, 0, 0, 0 +AVX_INSTR psrldq, 0, 0, 0 +AVX_INSTR psubb, 0, 0, 0 +AVX_INSTR psubw, 0, 0, 0 +AVX_INSTR psubd, 0, 0, 0 +AVX_INSTR psubq, 0, 0, 0 +AVX_INSTR psubsb, 0, 0, 0 +AVX_INSTR psubsw, 0, 0, 0 +AVX_INSTR psubusb, 0, 0, 0 +AVX_INSTR psubusw, 0, 0, 0 +AVX_INSTR punpckhbw, 0, 0, 0 +AVX_INSTR punpckhwd, 0, 0, 0 +AVX_INSTR punpckhdq, 0, 0, 0 +AVX_INSTR punpckhqdq, 0, 0, 0 +AVX_INSTR punpcklbw, 0, 0, 0 +AVX_INSTR punpcklwd, 0, 0, 0 +AVX_INSTR punpckldq, 0, 0, 0 +AVX_INSTR punpcklqdq, 0, 0, 0 +AVX_INSTR pxor, 0, 0, 1 +AVX_INSTR shufps, 0, 1, 0 +AVX_INSTR subpd, 1, 0, 0 +AVX_INSTR subps, 1, 0, 0 +AVX_INSTR subsd, 1, 0, 0 +AVX_INSTR subss, 1, 0, 0 +AVX_INSTR unpckhpd, 1, 0, 0 +AVX_INSTR unpckhps, 1, 0, 0 +AVX_INSTR unpcklpd, 1, 0, 0 +AVX_INSTR unpcklps, 1, 0, 0 +AVX_INSTR xorpd, 1, 0, 1 +AVX_INSTR xorps, 1, 0, 1 ; 3DNow instructions, for sharing code between AVX, SSE and 3DN -AVX_INSTR pfadd, 1, 0 -AVX_INSTR pfsub, 1, 0 -AVX_INSTR pfmul, 1, 0 +AVX_INSTR pfadd, 1, 0, 1 +AVX_INSTR pfsub, 1, 0, 0 +AVX_INSTR pfmul, 1, 0, 1 + +; base-4 constants for shuffles +%assign i 0 +%rep 256 + %assign j ((i>>6)&3)*1000 + ((i>>4)&3)*100 + ((i>>2)&3)*10 + (i&3) + %if j < 10 + CAT_XDEFINE q000, j, i + %elif j < 100 + CAT_XDEFINE q00, j, i + %elif j < 1000 + CAT_XDEFINE q0, j, i + %else + CAT_XDEFINE q, j, i + %endif +%assign i i+1 +%endrep +%undef i +%undef j + +%macro FMA_INSTR 3 + %macro %1 4-7 %1, %2, %3 + %if cpuflag(xop) + v%5 %1, %2, %3, %4 + %else + %6 %1, %2, %3 + %7 %1, %4 + %endif + %endmacro +%endmacro + +FMA_INSTR pmacsdd, pmulld, paddd +FMA_INSTR pmacsww, pmullw, paddw +FMA_INSTR pmadcswd, pmaddwd, paddd diff --git a/libswscale/x86/scale.asm b/libswscale/x86/scale.asm index 2e754862f0..5f831aaebf 100644 --- a/libswscale/x86/scale.asm +++ b/libswscale/x86/scale.asm @@ -34,6 +34,12 @@ yuv2yuvX_10_start: times 4 dd 0x10000 yuv2yuvX_9_start: times 4 dd 0x20000 yuv2yuvX_10_upper: times 8 dw 0x3ff yuv2yuvX_9_upper: times 8 dw 0x1ff +pd_4: times 4 dd 4 +pd_4min0x40000:times 4 dd 4 - (0x40000) +pw_16: times 8 dw 16 +pw_32: times 8 dw 32 +pw_512: times 8 dw 512 +pw_1024: times 8 dw 1024 SECTION .text @@ -665,3 +671,139 @@ INIT_AVX yuv2planeX_fn avx, 8, 10, 7 yuv2planeX_fn avx, 9, 7, 5 yuv2planeX_fn avx, 10, 7, 5 + +; %1=outout-bpc, %2=alignment (u/a) +%macro yuv2plane1_mainloop 2 +.loop_%2: +%if %1 == 8 + paddsw m0, m2, [r0+r2*2+mmsize*0] + paddsw m1, m3, [r0+r2*2+mmsize*1] + psraw m0, 7 + psraw m1, 7 + packuswb m0, m1 + mov%2 [r1+r2], m0 +%elif %1 == 16 + paddd m0, m4, [r0+r2*4+mmsize*0] + paddd m1, m4, [r0+r2*4+mmsize*1] + paddd m2, m4, [r0+r2*4+mmsize*2] + paddd m3, m4, [r0+r2*4+mmsize*3] + psrad m0, 3 + psrad m1, 3 + psrad m2, 3 + psrad m3, 3 +%if cpuflag(sse4) ; avx/sse4 + packusdw m0, m1 + packusdw m2, m3 +%else ; mmx/sse2 + packssdw m0, m1 + packssdw m2, m3 + paddw m0, m5 + paddw m2, m5 +%endif ; mmx/sse2/sse4/avx + mov%2 [r1+r2*2], m0 + mov%2 [r1+r2*2+mmsize], m2 +%else + paddsw m0, m2, [r0+r2*2+mmsize*0] + paddsw m1, m2, [r0+r2*2+mmsize*1] + psraw m0, 15 - %1 + psraw m1, 15 - %1 + pmaxsw m0, m4 + pmaxsw m1, m4 + pminsw m0, m3 + pminsw m1, m3 + mov%2 [r1+r2*2], m0 + mov%2 [r1+r2*2+mmsize], m1 +%endif + add r2, mmsize + jl .loop_%2 +%endmacro + +%macro yuv2plane1_fn 3 +cglobal yuv2plane1_%1, %3, %3, %2 +%if %1 == 8 + add r1, r2 +%else ; %1 != 8 + lea r1, [r1+r2*2] +%endif ; %1 == 8 +%if %1 == 16 + lea r0, [r0+r2*4] +%else ; %1 != 16 + lea r0, [r0+r2*2] +%endif ; %1 == 16 + neg r2 + +%if %1 == 8 + pxor m4, m4 ; zero + + ; create registers holding dither + movq m3, [r3] ; dither + test r4d, r4d + jz .no_rot +%if mmsize == 16 + punpcklqdq m3, m3 +%endif ; mmsize == 16 + PALIGNR_MMX m3, m3, 3, m2 +.no_rot: +%if mmsize == 8 + mova m2, m3 + punpckhbw m3, m4 ; byte->word + punpcklbw m2, m4 ; byte->word +%else + punpcklbw m3, m4 + mova m2, m3 +%endif +%elif %1 == 9 + pxor m4, m4 + mova m3, [pw_512] + mova m2, [pw_32] +%elif %1 == 10 + pxor m4, m4 + mova m3, [pw_1024] + mova m2, [pw_16] +%else ; %1 == 16 +%if cpuflag(sse4) ; sse4/avx + mova m4, [pd_4] +%else ; mmx/sse2 + mova m4, [pd_4min0x40000] + mova m5, [minshort] +%endif ; mmx/sse2/sse4/avx +%endif ; %1 == .. + + ; actual pixel scaling +%if mmsize == 8 + yuv2plane1_mainloop %1, a +%else ; mmsize == 16 + test r1, 15 + jnz .unaligned + yuv2plane1_mainloop %1, a + REP_RET +.unaligned: + yuv2plane1_mainloop %1, u +%endif ; mmsize == 8/16 + REP_RET +%endmacro + +%ifdef ARCH_X86_32 +INIT_MMX mmx +yuv2plane1_fn 8, 0, 5 +yuv2plane1_fn 16, 0, 3 + +INIT_MMX mmx2 +yuv2plane1_fn 9, 0, 3 +yuv2plane1_fn 10, 0, 3 +%endif + +INIT_XMM sse2 +yuv2plane1_fn 8, 5, 5 +yuv2plane1_fn 9, 5, 3 +yuv2plane1_fn 10, 5, 3 +yuv2plane1_fn 16, 6, 3 + +INIT_XMM sse4 +yuv2plane1_fn 16, 5, 3 + +INIT_XMM avx +yuv2plane1_fn 8, 5, 5 +yuv2plane1_fn 9, 5, 3 +yuv2plane1_fn 10, 5, 3 +yuv2plane1_fn 16, 5, 3 diff --git a/libswscale/x86/swscale_mmx.c b/libswscale/x86/swscale_mmx.c index c16be83f13..8869274dd4 100644 --- a/libswscale/x86/swscale_mmx.c +++ b/libswscale/x86/swscale_mmx.c @@ -289,6 +289,22 @@ VSCALEX_FUNCS(sse4, sse4); VSCALEX_FUNC(16, sse4); VSCALEX_FUNCS(avx, avx); +#define VSCALE_FUNC(size, opt) \ +extern void ff_yuv2plane1_ ## size ## _ ## opt(const int16_t *src, uint8_t *dst, int dstW, \ + const uint8_t *dither, int offset) +#define VSCALE_FUNCS(opt1, opt2) \ + VSCALE_FUNC(8, opt1); \ + VSCALE_FUNC(9, opt2); \ + VSCALE_FUNC(10, opt2); \ + VSCALE_FUNC(16, opt1) + +#if ARCH_X86_32 +VSCALE_FUNCS(mmx, mmx2); +#endif +VSCALE_FUNCS(sse2, sse2); +VSCALE_FUNC(16, sse4); +VSCALE_FUNCS(avx, avx); + void ff_sws_init_swScale_mmx(SwsContext *c) { int cpu_flags = av_get_cpu_flags(); @@ -336,11 +352,19 @@ switch(c->dstBpc){ \ case 9: if (!isBE(c->dstFormat) && opt2chk) /*vscalefn = ff_yuv2planeX_9_ ## opt2;*/ break; \ default: /*vscalefn = ff_yuv2planeX_8_ ## opt1;*/ break; \ } +#define ASSIGN_VSCALE_FUNC(vscalefn, opt1, opt2, opt2chk) \ + switch(c->dstBpc){ \ + case 16: if (!isBE(c->dstFormat)) vscalefn = ff_yuv2plane1_16_ ## opt1; break; \ + case 10: if (!isBE(c->dstFormat) && opt2chk) vscalefn = ff_yuv2plane1_10_ ## opt2; break; \ + case 9: if (!isBE(c->dstFormat) && opt2chk) vscalefn = ff_yuv2plane1_9_ ## opt2; break; \ + default: vscalefn = ff_yuv2plane1_8_ ## opt1; break; \ + } #if ARCH_X86_32 if (cpu_flags & AV_CPU_FLAG_MMX) { ASSIGN_MMX_SCALE_FUNC(c->hyScale, c->hLumFilterSize, mmx, mmx); ASSIGN_MMX_SCALE_FUNC(c->hcScale, c->hChrFilterSize, mmx, mmx); ASSIGN_VSCALEX_FUNC(c->yuv2planeX, mmx, mmx2, cpu_flags & AV_CPU_FLAG_MMX2,); + ASSIGN_VSCALE_FUNC(c->yuv2plane1, mmx, mmx2, cpu_flags & AV_CPU_FLAG_MMX2); } #endif #define ASSIGN_SSE_SCALE_FUNC(hscalefn, filtersize, opt1, opt2) \ @@ -355,6 +379,7 @@ switch(c->dstBpc){ \ ASSIGN_SSE_SCALE_FUNC(c->hyScale, c->hLumFilterSize, sse2, sse2); ASSIGN_SSE_SCALE_FUNC(c->hcScale, c->hChrFilterSize, sse2, sse2); ASSIGN_VSCALEX_FUNC(c->yuv2planeX, sse2, sse2, 1,); + ASSIGN_VSCALE_FUNC(c->yuv2plane1, sse2, sse2, 1); } if (cpu_flags & AV_CPU_FLAG_SSSE3) { ASSIGN_SSE_SCALE_FUNC(c->hyScale, c->hLumFilterSize, ssse3, ssse3); @@ -366,10 +391,13 @@ switch(c->dstBpc){ \ ASSIGN_SSE_SCALE_FUNC(c->hcScale, c->hChrFilterSize, sse4, ssse3); ASSIGN_VSCALEX_FUNC(c->yuv2planeX, sse4, sse4, 1, if (!isBE(c->dstFormat)) c->yuv2planeX = ff_yuv2planeX_16_sse4); + if (c->dstBpc == 16 && !isBE(c->dstFormat)) + c->yuv2plane1 = ff_yuv2plane1_16_sse4; } if (cpu_flags & AV_CPU_FLAG_AVX) { ASSIGN_VSCALEX_FUNC(c->yuv2planeX, avx, avx, 1,); + ASSIGN_VSCALE_FUNC(c->yuv2plane1, avx, avx, 1); } #endif } diff --git a/libswscale/x86/swscale_template.c b/libswscale/x86/swscale_template.c index 0f177176cb..5be6072d3b 100644 --- a/libswscale/x86/swscale_template.c +++ b/libswscale/x86/swscale_template.c @@ -109,29 +109,6 @@ static void RENAME(yuv2yuvX)(const int16_t *filter, int filterSize, ); } -static void RENAME(yuv2yuv1_ar)(const int16_t *src, uint8_t *dst, int dstW, const uint8_t *dither, int offset) -{ - dither_8to16(dither, offset); - __asm__ volatile( - "mov %2, %%"REG_a" \n\t" - ".p2align 4 \n\t" /* FIXME Unroll? */ - "1: \n\t" - "movq (%0, %%"REG_a", 2), %%mm0 \n\t" - "movq 8(%0, %%"REG_a", 2), %%mm1 \n\t" - "paddsw %%mm3, %%mm0 \n\t" - "paddsw %%mm4, %%mm1 \n\t" - "psraw $7, %%mm0 \n\t" - "psraw $7, %%mm1 \n\t" - "packuswb %%mm1, %%mm0 \n\t" - MOVNTQ(%%mm0, (%1, %%REGa)) - "add $8, %%"REG_a" \n\t" - "jnc 1b \n\t" - :: "r" (src + dstW), "r" (dst + dstW), - "g" ((x86_reg)-dstW) - : "%"REG_a - ); -} - #define YSCALEYUV2PACKEDX_UV \ __asm__ volatile(\ "xor %%"REG_a", %%"REG_a" \n\t"\ @@ -1881,9 +1858,7 @@ static av_cold void RENAME(sws_init_swScale)(SwsContext *c) c->use_mmx_vfilter= 0; if (!is16BPS(dstFormat) && !is9_OR_10BPS(dstFormat) && dstFormat != PIX_FMT_NV12 && dstFormat != PIX_FMT_NV21 && !(c->flags & SWS_BITEXACT)) { - c->yuv2plane1 = RENAME(yuv2yuv1_ar ); if (c->flags & SWS_ACCURATE_RND) { - //c->yuv2yuv1 = RENAME(yuv2yuv1_ar ); if (!(c->flags & SWS_FULL_CHR_H_INT)) { switch (c->dstFormat) { case PIX_FMT_RGB32: c->yuv2packedX = RENAME(yuv2rgb32_X_ar); break; @@ -1896,7 +1871,6 @@ static av_cold void RENAME(sws_init_swScale)(SwsContext *c) } } else { int should_dither= isNBPS(c->srcFormat) || is16BPS(c->srcFormat); - //c->yuv2plane1 = should_dither ? RENAME(yuv2yuv1_ar ) : RENAME(yuv2yuv1 ); c->use_mmx_vfilter= 1; c->yuv2planeX = RENAME(yuv2yuvX ); if (!(c->flags & SWS_FULL_CHR_H_INT)) {