* qatar/master: mpegvideo_enc: don't use deprecated avcodec_encode_video(). cmdutils: refactor -codecs option. avconv: make -shortest a per-output file option. lavc: add avcodec_descriptor_get_by_name(). lavc: add const to AVCodec* function parameters. swf(dec): replace CODEC_ID with AV_CODEC_ID dvenc: don't use deprecated AVCODEC_MAX_AUDIO_FRAME_SIZE rtmpdh: Do not generate the same private key every time when using libnettle rtp: remove ff_rtp_get_rtcp_file_handle(). rtsp.c: use ffurl_get_multi_file_handle() instead of ff_rtp_get_rtcp_file_handle() avio: add (ff)url_get_multi_file_handle() for getting more than one fd h264: vdpau: fix crash with unsupported colorspace amrwbdec: Decode the fr_quality bit properly Conflicts: Changelog cmdutils.c cmdutils_common_opts.h doc/ffmpeg.texi ffmpeg.c ffmpeg.h ffmpeg_opt.c libavcodec/h264.c libavcodec/options.c libavcodec/utils.c Merged-by: Michael Niedermayer <michaelni@gmx.at>tags/n1.0
| @@ -49,6 +49,7 @@ version next: | |||||
| - SubRip encoder and decoder without embedded timing | - SubRip encoder and decoder without embedded timing | ||||
| - edge detection filter | - edge detection filter | ||||
| - framestep filter | - framestep filter | ||||
| - ffmpeg -shortest option is now per-output file | |||||
| version 0.11: | version 0.11: | ||||
| @@ -801,90 +801,127 @@ int opt_formats(const char *opt, const char *arg) | |||||
| static char get_media_type_char(enum AVMediaType type) | static char get_media_type_char(enum AVMediaType type) | ||||
| { | { | ||||
| static const char map[AVMEDIA_TYPE_NB] = { | |||||
| [AVMEDIA_TYPE_VIDEO] = 'V', | |||||
| [AVMEDIA_TYPE_AUDIO] = 'A', | |||||
| [AVMEDIA_TYPE_DATA] = 'D', | |||||
| [AVMEDIA_TYPE_SUBTITLE] = 'S', | |||||
| [AVMEDIA_TYPE_ATTACHMENT] = 'T', | |||||
| }; | |||||
| return type >= 0 && type < AVMEDIA_TYPE_NB && map[type] ? map[type] : '?'; | |||||
| switch (type) { | |||||
| case AVMEDIA_TYPE_VIDEO: return 'V'; | |||||
| case AVMEDIA_TYPE_AUDIO: return 'A'; | |||||
| case AVMEDIA_TYPE_DATA: return 'D'; | |||||
| case AVMEDIA_TYPE_SUBTITLE: return 'S'; | |||||
| case AVMEDIA_TYPE_ATTACHMENT:return 'T'; | |||||
| default: return '?'; | |||||
| } | |||||
| } | } | ||||
| int opt_codecs(const char *opt, const char *arg) | |||||
| static const AVCodec *next_codec_for_id(enum AVCodecID id, const AVCodec *prev, | |||||
| int encoder) | |||||
| { | { | ||||
| AVCodec *p = NULL, *p2; | |||||
| const char *last_name; | |||||
| while ((prev = av_codec_next(prev))) { | |||||
| if (prev->id == id && | |||||
| (encoder ? av_codec_is_encoder(prev) : av_codec_is_decoder(prev))) | |||||
| return prev; | |||||
| } | |||||
| return NULL; | |||||
| } | |||||
| static void print_codecs_for_id(enum AVCodecID id, int encoder) | |||||
| { | |||||
| const AVCodec *codec = NULL; | |||||
| printf(" (%s: ", encoder ? "encoders" : "decoders"); | |||||
| while ((codec = next_codec_for_id(id, codec, encoder))) | |||||
| printf("%s ", codec->name); | |||||
| printf(")"); | |||||
| } | |||||
| int show_codecs(const char *opt, const char *arg) | |||||
| { | |||||
| const AVCodecDescriptor *desc = NULL; | |||||
| printf("Codecs:\n" | printf("Codecs:\n" | ||||
| " D....... = Decoding supported\n" | |||||
| " .E...... = Encoding supported\n" | |||||
| " ..V..... = Video codec\n" | |||||
| " ..A..... = Audio codec\n" | |||||
| " ..S..... = Subtitle codec\n" | |||||
| " ...S.... = Supports draw_horiz_band\n" | |||||
| " ....D... = Supports direct rendering method 1\n" | |||||
| " .....T.. = Supports weird frame truncation\n" | |||||
| " ......F. = Supports frame-based multi-threaded decoding\n" | |||||
| " ......S. = Supports slice-based multi-threaded decoding\n" | |||||
| " ......B. = Supports both frame-based and slice-based multi-threaded decoding\n" | |||||
| " .......F = Supports frame-based multi-threaded encoding\n" | |||||
| " .......S = Supports slice-based multi-threaded encoding\n" | |||||
| " .......B = Supports both frame-based and slice-based multi-threaded encoding\n" | |||||
| " --------\n"); | |||||
| last_name= "000"; | |||||
| for (;;) { | |||||
| int decode = 0; | |||||
| int encode = 0; | |||||
| int cap = 0; | |||||
| p2 = NULL; | |||||
| while ((p = av_codec_next(p))) { | |||||
| if ((p2 == NULL || strcmp(p->name, p2->name) < 0) && | |||||
| strcmp(p->name, last_name) > 0) { | |||||
| p2 = p; | |||||
| decode = encode = cap = 0; | |||||
| " D... = Decoding supported\n" | |||||
| " .E.. = Encoding supported\n" | |||||
| " ..V. = Video codec\n" | |||||
| " ..A. = Audio codec\n" | |||||
| " ..S. = Subtitle codec\n" | |||||
| " ...I = Intra frame-only codec\n" | |||||
| " -----\n"); | |||||
| while ((desc = avcodec_descriptor_next(desc))) { | |||||
| const AVCodec *codec = NULL; | |||||
| printf(avcodec_find_decoder(desc->id) ? "D" : "."); | |||||
| printf(avcodec_find_encoder(desc->id) ? "E" : "."); | |||||
| printf("%c", get_media_type_char(desc->type)); | |||||
| printf((desc->props & AV_CODEC_PROP_INTRA_ONLY) ? "I" : "."); | |||||
| printf(" %-20s %s", desc->name, desc->long_name ? desc->long_name : ""); | |||||
| /* print decoders/encoders when there's more than one or their | |||||
| * names are different from codec name */ | |||||
| while ((codec = next_codec_for_id(desc->id, codec, 0))) { | |||||
| if (strcmp(codec->name, desc->name)) { | |||||
| print_codecs_for_id(desc->id, 0); | |||||
| break; | |||||
| } | } | ||||
| if (p2 && strcmp(p->name, p2->name) == 0) { | |||||
| if (av_codec_is_decoder(p)) | |||||
| decode = 1; | |||||
| if (av_codec_is_encoder(p)) | |||||
| encode = 1; | |||||
| cap |= p->capabilities; | |||||
| } | |||||
| codec = NULL; | |||||
| while ((codec = next_codec_for_id(desc->id, codec, 1))) { | |||||
| if (strcmp(codec->name, desc->name)) { | |||||
| print_codecs_for_id(desc->id, 1); | |||||
| break; | |||||
| } | } | ||||
| } | } | ||||
| if (p2 == NULL) | |||||
| break; | |||||
| last_name = p2->name; | |||||
| printf(" %s%s%c%s%s%s%s%s %-15s %s", | |||||
| decode ? "D" : (/* p2->decoder ? "d" : */ " "), | |||||
| encode ? "E" : " ", | |||||
| get_media_type_char(p2->type), | |||||
| cap & CODEC_CAP_DRAW_HORIZ_BAND ? "S" : " ", | |||||
| cap & CODEC_CAP_DR1 ? "D" : " ", | |||||
| cap & CODEC_CAP_TRUNCATED ? "T" : " ", | |||||
| decode ? | |||||
| cap & CODEC_CAP_FRAME_THREADS ? cap & CODEC_CAP_SLICE_THREADS ? "B" : "F" : | |||||
| cap & CODEC_CAP_SLICE_THREADS ? "S" : " " | |||||
| : " ", | |||||
| encode ? | |||||
| cap & CODEC_CAP_FRAME_THREADS ? cap & CODEC_CAP_SLICE_THREADS ? "B" : "F" : | |||||
| cap & CODEC_CAP_SLICE_THREADS ? "S" : " " | |||||
| : " ", | |||||
| p2->name, | |||||
| p2->long_name ? p2->long_name : ""); | |||||
| #if 0 | |||||
| if (p2->decoder && decode == 0) | |||||
| printf(" use %s for decoding", p2->decoder->name); | |||||
| #endif | |||||
| printf("\n"); | printf("\n"); | ||||
| } | } | ||||
| printf("\n"); | |||||
| printf("Note, the names of encoders and decoders do not always match, so there are\n" | |||||
| "several cases where the above table shows encoder only or decoder only entries\n" | |||||
| "even though both encoding and decoding are supported. For example, the h263\n" | |||||
| "decoder corresponds to the h263 and h263p encoders, for file formats it is even\n" | |||||
| "worse.\n"); | |||||
| return 0; | |||||
| } | |||||
| static void print_codecs(int encoder) | |||||
| { | |||||
| const AVCodecDescriptor *desc = NULL; | |||||
| printf("%s:\n" | |||||
| " V..... = Video\n" | |||||
| " A..... = Audio\n" | |||||
| " S..... = Subtitle\n" | |||||
| " .F.... = Frame-level multithreading\n" | |||||
| " ..S... = Slice-level multithreading\n" | |||||
| " ...X.. = Codec is experimental\n" | |||||
| " ....B. = Supports draw_horiz_band\n" | |||||
| " .....D = Supports direct rendering method 1\n" | |||||
| " ------\n", | |||||
| encoder ? "Encoders" : "Decoders"); | |||||
| while ((desc = avcodec_descriptor_next(desc))) { | |||||
| const AVCodec *codec = NULL; | |||||
| while ((codec = next_codec_for_id(desc->id, codec, encoder))) { | |||||
| printf("%c", get_media_type_char(desc->type)); | |||||
| printf((codec->capabilities & CODEC_CAP_FRAME_THREADS) ? "F" : "."); | |||||
| printf((codec->capabilities & CODEC_CAP_SLICE_THREADS) ? "S" : "."); | |||||
| printf((codec->capabilities & CODEC_CAP_EXPERIMENTAL) ? "X" : "."); | |||||
| printf((codec->capabilities & CODEC_CAP_DRAW_HORIZ_BAND)?"B" : "."); | |||||
| printf((codec->capabilities & CODEC_CAP_DR1) ? "D" : "."); | |||||
| printf(" %-20s %s", codec->name, codec->long_name ? codec->long_name : ""); | |||||
| if (strcmp(codec->name, desc->name)) | |||||
| printf(" (codec %s)", desc->name); | |||||
| printf("\n"); | |||||
| } | |||||
| } | |||||
| } | |||||
| int show_decoders(const char *opt, const char *arg) | |||||
| { | |||||
| print_codecs(0); | |||||
| return 0; | |||||
| } | |||||
| int show_encoders(const char *opt, const char *arg) | |||||
| { | |||||
| print_codecs(1); | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| @@ -298,7 +298,19 @@ int opt_formats(const char *opt, const char *arg); | |||||
| * program. | * program. | ||||
| * This option processing function does not utilize the arguments. | * This option processing function does not utilize the arguments. | ||||
| */ | */ | ||||
| int opt_codecs(const char *opt, const char *arg); | |||||
| int show_codecs(const char *opt, const char *arg); | |||||
| /** | |||||
| * Print a listing containing all the decoders supported by the | |||||
| * program. | |||||
| */ | |||||
| int show_decoders(const char *opt, const char *arg); | |||||
| /** | |||||
| * Print a listing containing all the encoders supported by the | |||||
| * program. | |||||
| */ | |||||
| int show_encoders(const char *opt, const char *arg); | |||||
| /** | /** | ||||
| * Print a listing containing all the filters supported by the | * Print a listing containing all the filters supported by the | ||||
| @@ -5,7 +5,9 @@ | |||||
| { "-help", OPT_EXIT, {(void*)opt_help}, "show help" }, | { "-help", OPT_EXIT, {(void*)opt_help}, "show help" }, | ||||
| { "version", OPT_EXIT, {(void*)opt_version}, "show version" }, | { "version", OPT_EXIT, {(void*)opt_version}, "show version" }, | ||||
| { "formats" , OPT_EXIT, {(void*)opt_formats }, "show available formats" }, | { "formats" , OPT_EXIT, {(void*)opt_formats }, "show available formats" }, | ||||
| { "codecs" , OPT_EXIT, {(void*)opt_codecs }, "show available codecs" }, | |||||
| { "codecs" , OPT_EXIT, {(void*)show_codecs }, "show available codecs" }, | |||||
| { "decoders" , OPT_EXIT, {(void*)show_decoders }, "show available decoders" }, | |||||
| { "encoders" , OPT_EXIT, {(void*)show_encoders }, "show available encoders" }, | |||||
| { "bsfs" , OPT_EXIT, {(void*)opt_bsfs }, "show available bit stream filters" }, | { "bsfs" , OPT_EXIT, {(void*)opt_bsfs }, "show available bit stream filters" }, | ||||
| { "protocols", OPT_EXIT, {(void*)opt_protocols}, "show available protocols" }, | { "protocols", OPT_EXIT, {(void*)opt_protocols}, "show available protocols" }, | ||||
| { "filters", OPT_EXIT, {(void*)opt_filters }, "show available filters" }, | { "filters", OPT_EXIT, {(void*)opt_filters }, "show available filters" }, | ||||
| @@ -72,23 +72,16 @@ Encoding available | |||||
| @end table | @end table | ||||
| @item -codecs | @item -codecs | ||||
| Show available codecs. | |||||
| Show all codecs known to libavcodec. | |||||
| The fields preceding the codec names have the following meanings: | |||||
| @table @samp | |||||
| @item D | |||||
| Decoding available | |||||
| @item E | |||||
| Encoding available | |||||
| @item V/A/S | |||||
| Video/audio/subtitle codec | |||||
| @item S | |||||
| Codec supports slices | |||||
| @item D | |||||
| Codec supports direct rendering | |||||
| @item T | |||||
| Codec can handle input truncated at random locations instead of only at frame boundaries | |||||
| @end table | |||||
| Note that the term 'codec' is used throughout this documentation as a shortcut | |||||
| for what is more correctly called a media bitstream format. | |||||
| @item -decoders | |||||
| Show available decoders. | |||||
| @item -encoders | |||||
| Show all available encoders. | |||||
| @item -bsfs | @item -bsfs | ||||
| Show available bitstream filters. | Show available bitstream filters. | ||||
| @@ -928,7 +928,7 @@ Try to make the choice automatically, in order to generate a sane output. | |||||
| Default value is -1. | Default value is -1. | ||||
| @item -shortest | |||||
| @item -shortest (@emph{output}) | |||||
| Finish encoding when the shortest input stream ends. | Finish encoding when the shortest input stream ends. | ||||
| @item -dts_delta_threshold | @item -dts_delta_threshold | ||||
| Timestamp discontinuity delta threshold. | Timestamp discontinuity delta threshold. | ||||
| @@ -2783,10 +2783,20 @@ static int process_input(void) | |||||
| poll_filters(); | poll_filters(); | ||||
| } | } | ||||
| if (opt_shortest) | |||||
| return AVERROR_EOF; | |||||
| else | |||||
| return AVERROR(EAGAIN); | |||||
| for (i = 0; i < nb_output_streams; i++) { | |||||
| OutputStream *ost = output_streams[i]; | |||||
| OutputFile *of = output_files[ost->file_index]; | |||||
| AVFormatContext *os = output_files[ost->file_index]->ctx; | |||||
| if (of->shortest) { | |||||
| int j; | |||||
| for (j = 0; j < of->ctx->nb_streams; j++) | |||||
| output_streams[of->ost_index + j]->finished = 1; | |||||
| continue; | |||||
| } | |||||
| } | |||||
| return AVERROR(EAGAIN); | |||||
| } | } | ||||
| reset_eagain(); | reset_eagain(); | ||||
| @@ -114,6 +114,7 @@ typedef struct OptionsContext { | |||||
| uint64_t limit_filesize; | uint64_t limit_filesize; | ||||
| float mux_preload; | float mux_preload; | ||||
| float mux_max_delay; | float mux_max_delay; | ||||
| int shortest; | |||||
| int video_disable; | int video_disable; | ||||
| int audio_disable; | int audio_disable; | ||||
| @@ -332,6 +333,8 @@ typedef struct OutputFile { | |||||
| int64_t recording_time; ///< desired length of the resulting file in microseconds == AV_TIME_BASE units | 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 | int64_t start_time; ///< start time in microseconds == AV_TIME_BASE units | ||||
| uint64_t limit_filesize; /* filesize limit expressed in bytes */ | uint64_t limit_filesize; /* filesize limit expressed in bytes */ | ||||
| int shortest; | |||||
| } OutputFile; | } OutputFile; | ||||
| extern InputStream **input_streams; | extern InputStream **input_streams; | ||||
| @@ -365,7 +368,6 @@ extern int do_pkt_dump; | |||||
| extern int copy_ts; | extern int copy_ts; | ||||
| extern int copy_tb; | extern int copy_tb; | ||||
| extern int debug_ts; | extern int debug_ts; | ||||
| extern int opt_shortest; | |||||
| extern int exit_on_error; | extern int exit_on_error; | ||||
| extern int print_stats; | extern int print_stats; | ||||
| extern int qp_hist; | extern int qp_hist; | ||||
| @@ -1613,6 +1613,7 @@ loop_end: | |||||
| oc->duration = o->recording_time; | oc->duration = o->recording_time; | ||||
| output_files[nb_output_files - 1]->start_time = o->start_time; | output_files[nb_output_files - 1]->start_time = o->start_time; | ||||
| output_files[nb_output_files - 1]->limit_filesize = o->limit_filesize; | output_files[nb_output_files - 1]->limit_filesize = o->limit_filesize; | ||||
| output_files[nb_output_files - 1]->shortest = o->shortest; | |||||
| av_dict_copy(&output_files[nb_output_files - 1]->opts, format_opts, 0); | av_dict_copy(&output_files[nb_output_files - 1]->opts, format_opts, 0); | ||||
| /* check filename in case of an image number is expected */ | /* check filename in case of an image number is expected */ | ||||
| @@ -2210,7 +2211,7 @@ const OptionDef options[] = { | |||||
| { "adrift_threshold", HAS_ARG | OPT_FLOAT | OPT_EXPERT, {(void*)&audio_drift_threshold}, "audio drift threshold", "threshold" }, | { "adrift_threshold", HAS_ARG | OPT_FLOAT | OPT_EXPERT, {(void*)&audio_drift_threshold}, "audio drift threshold", "threshold" }, | ||||
| { "copyts", OPT_BOOL | OPT_EXPERT, {(void*)©_ts}, "copy timestamps" }, | { "copyts", OPT_BOOL | OPT_EXPERT, {(void*)©_ts}, "copy timestamps" }, | ||||
| { "copytb", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)©_tb}, "copy input stream time base when stream copying", "mode" }, | { "copytb", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)©_tb}, "copy input stream time base when stream copying", "mode" }, | ||||
| { "shortest", OPT_BOOL | OPT_EXPERT, {(void*)&opt_shortest}, "finish encoding within shortest input" }, // | |||||
| { "shortest", OPT_BOOL | OPT_EXPERT | OPT_OFFSET, {.off = OFFSET(shortest)}, "finish encoding within shortest input" }, | |||||
| { "dts_delta_threshold", HAS_ARG | OPT_FLOAT | OPT_EXPERT, {(void*)&dts_delta_threshold}, "timestamp discontinuity delta threshold", "threshold" }, | { "dts_delta_threshold", HAS_ARG | OPT_FLOAT | OPT_EXPERT, {(void*)&dts_delta_threshold}, "timestamp discontinuity delta threshold", "threshold" }, | ||||
| { "dts_error_threshold", HAS_ARG | OPT_FLOAT | OPT_EXPERT, {(void*)&dts_error_threshold}, "timestamp error delta threshold", "threshold" }, | { "dts_error_threshold", HAS_ARG | OPT_FLOAT | OPT_EXPERT, {(void*)&dts_error_threshold}, "timestamp error delta threshold", "threshold" }, | ||||
| { "xerror", OPT_BOOL, {(void*)&exit_on_error}, "exit on error", "error" }, | { "xerror", OPT_BOOL, {(void*)&exit_on_error}, "exit on error", "error" }, | ||||
| @@ -133,7 +133,7 @@ static int decode_mime_header(AMRWBContext *ctx, const uint8_t *buf) | |||||
| { | { | ||||
| /* Decode frame header (1st octet) */ | /* Decode frame header (1st octet) */ | ||||
| ctx->fr_cur_mode = buf[0] >> 3 & 0x0F; | ctx->fr_cur_mode = buf[0] >> 3 & 0x0F; | ||||
| ctx->fr_quality = (buf[0] & 0x4) != 0x4; | |||||
| ctx->fr_quality = (buf[0] & 0x4) == 0x4; | |||||
| return 1; | return 1; | ||||
| } | } | ||||
| @@ -1440,7 +1440,7 @@ typedef struct AVCodecContext { | |||||
| int log_level_offset; | int log_level_offset; | ||||
| enum AVMediaType codec_type; /* see AVMEDIA_TYPE_xxx */ | enum AVMediaType codec_type; /* see AVMEDIA_TYPE_xxx */ | ||||
| struct AVCodec *codec; | |||||
| const struct AVCodec *codec; | |||||
| char codec_name[32]; | char codec_name[32]; | ||||
| enum AVCodecID codec_id; /* see AV_CODEC_ID_xxx */ | enum AVCodecID codec_id; /* see AV_CODEC_ID_xxx */ | ||||
| @@ -3338,7 +3338,7 @@ typedef struct AVSubtitle { | |||||
| * if c is non-NULL, returns the next registered codec after c, | * if c is non-NULL, returns the next registered codec after c, | ||||
| * or NULL if c is the last one. | * or NULL if c is the last one. | ||||
| */ | */ | ||||
| AVCodec *av_codec_next(AVCodec *c); | |||||
| AVCodec *av_codec_next(const AVCodec *c); | |||||
| /** | /** | ||||
| * Return the LIBAVCODEC_VERSION_INT constant. | * Return the LIBAVCODEC_VERSION_INT constant. | ||||
| @@ -3426,7 +3426,7 @@ void avcodec_get_context_defaults2(AVCodecContext *s, enum AVMediaType); | |||||
| * @return An AVCodecContext filled with default values or NULL on failure. | * @return An AVCodecContext filled with default values or NULL on failure. | ||||
| * @see avcodec_get_context_defaults | * @see avcodec_get_context_defaults | ||||
| */ | */ | ||||
| AVCodecContext *avcodec_alloc_context3(AVCodec *codec); | |||||
| AVCodecContext *avcodec_alloc_context3(const AVCodec *codec); | |||||
| /** | /** | ||||
| * Set the fields of the given AVCodecContext to default values corresponding | * Set the fields of the given AVCodecContext to default values corresponding | ||||
| @@ -3437,7 +3437,7 @@ AVCodecContext *avcodec_alloc_context3(AVCodec *codec); | |||||
| * If codec is non-NULL, it is illegal to call avcodec_open2() with a | * If codec is non-NULL, it is illegal to call avcodec_open2() with a | ||||
| * different codec on this AVCodecContext. | * different codec on this AVCodecContext. | ||||
| */ | */ | ||||
| int avcodec_get_context_defaults3(AVCodecContext *s, AVCodec *codec); | |||||
| int avcodec_get_context_defaults3(AVCodecContext *s, const AVCodec *codec); | |||||
| /** | /** | ||||
| * Get the AVClass for AVCodecContext. It can be used in combination with | * Get the AVClass for AVCodecContext. It can be used in combination with | ||||
| @@ -3562,7 +3562,7 @@ int avcodec_open(AVCodecContext *avctx, AVCodec *codec); | |||||
| * @see avcodec_alloc_context3(), avcodec_find_decoder(), avcodec_find_encoder(), | * @see avcodec_alloc_context3(), avcodec_find_decoder(), avcodec_find_encoder(), | ||||
| * av_dict_set(), av_opt_find(). | * av_dict_set(), av_opt_find(). | ||||
| */ | */ | ||||
| int avcodec_open2(AVCodecContext *avctx, AVCodec *codec, AVDictionary **options); | |||||
| int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options); | |||||
| /** | /** | ||||
| * Close a given AVCodecContext and free all the data associated with it | * Close a given AVCodecContext and free all the data associated with it | ||||
| @@ -4834,12 +4834,12 @@ int avcodec_is_open(AVCodecContext *s); | |||||
| /** | /** | ||||
| * @return a non-zero number if codec is an encoder, zero otherwise | * @return a non-zero number if codec is an encoder, zero otherwise | ||||
| */ | */ | ||||
| int av_codec_is_encoder(AVCodec *codec); | |||||
| int av_codec_is_encoder(const AVCodec *codec); | |||||
| /** | /** | ||||
| * @return a non-zero number if codec is a decoder, zero otherwise | * @return a non-zero number if codec is a decoder, zero otherwise | ||||
| */ | */ | ||||
| int av_codec_is_decoder(AVCodec *codec); | |||||
| int av_codec_is_decoder(const AVCodec *codec); | |||||
| /** | /** | ||||
| * @return descriptor for given codec ID or NULL if no descriptor exists. | * @return descriptor for given codec ID or NULL if no descriptor exists. | ||||
| @@ -4855,6 +4855,12 @@ const AVCodecDescriptor *avcodec_descriptor_get(enum AVCodecID id); | |||||
| */ | */ | ||||
| const AVCodecDescriptor *avcodec_descriptor_next(const AVCodecDescriptor *prev); | const AVCodecDescriptor *avcodec_descriptor_next(const AVCodecDescriptor *prev); | ||||
| /** | |||||
| * @return codec descriptor with the given name or NULL if no such descriptor | |||||
| * exists. | |||||
| */ | |||||
| const AVCodecDescriptor *avcodec_descriptor_get_by_name(const char *name); | |||||
| /** | /** | ||||
| * @} | * @} | ||||
| */ | */ | ||||
| @@ -19,6 +19,8 @@ | |||||
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||||
| */ | */ | ||||
| #include <string.h> | |||||
| #include "avcodec.h" | #include "avcodec.h" | ||||
| #include "libavutil/common.h" | #include "libavutil/common.h" | ||||
| @@ -2122,3 +2124,14 @@ const AVCodecDescriptor *avcodec_descriptor_next(const AVCodecDescriptor *prev) | |||||
| return prev + 1; | return prev + 1; | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| const AVCodecDescriptor *avcodec_descriptor_get_by_name(const char *name) | |||||
| { | |||||
| const AVCodecDescriptor *desc = NULL; | |||||
| while ((desc = avcodec_descriptor_next(desc))) { | |||||
| if (!strcmp(desc->name, name)) | |||||
| return desc; | |||||
| } | |||||
| return NULL; | |||||
| } | |||||
| @@ -1120,6 +1120,22 @@ static int skip_check(MpegEncContext *s, Picture *p, Picture *ref) | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| static int encode_frame(AVCodecContext *c, AVFrame *frame) | |||||
| { | |||||
| AVPacket pkt = { 0 }; | |||||
| int ret, got_output; | |||||
| av_init_packet(&pkt); | |||||
| av_init_packet(&pkt); | |||||
| ret = avcodec_encode_video2(c, &pkt, frame, &got_output); | |||||
| if (ret < 0) | |||||
| return ret; | |||||
| ret = pkt.size; | |||||
| av_free_packet(&pkt); | |||||
| return ret; | |||||
| } | |||||
| static int estimate_best_b_count(MpegEncContext *s) | static int estimate_best_b_count(MpegEncContext *s) | ||||
| { | { | ||||
| AVCodec *codec = avcodec_find_encoder(s->avctx->codec_id); | AVCodec *codec = avcodec_find_encoder(s->avctx->codec_id); | ||||
| @@ -1127,8 +1143,6 @@ static int estimate_best_b_count(MpegEncContext *s) | |||||
| AVFrame input[FF_MAX_B_FRAMES + 2]; | AVFrame input[FF_MAX_B_FRAMES + 2]; | ||||
| const int scale = s->avctx->brd_scale; | const int scale = s->avctx->brd_scale; | ||||
| int i, j, out_size, p_lambda, b_lambda, lambda2; | int i, j, out_size, p_lambda, b_lambda, lambda2; | ||||
| int outbuf_size = s->width * s->height; // FIXME | |||||
| uint8_t *outbuf = av_malloc(outbuf_size); | |||||
| int64_t best_rd = INT64_MAX; | int64_t best_rd = INT64_MAX; | ||||
| int best_b_count = -1; | int best_b_count = -1; | ||||
| @@ -1205,8 +1219,9 @@ static int estimate_best_b_count(MpegEncContext *s) | |||||
| input[0].pict_type = AV_PICTURE_TYPE_I; | input[0].pict_type = AV_PICTURE_TYPE_I; | ||||
| input[0].quality = 1 * FF_QP2LAMBDA; | input[0].quality = 1 * FF_QP2LAMBDA; | ||||
| out_size = avcodec_encode_video(c, outbuf, | |||||
| outbuf_size, &input[0]); | |||||
| out_size = encode_frame(c, &input[0]); | |||||
| //rd += (out_size * lambda2) >> FF_LAMBDA_SHIFT; | //rd += (out_size * lambda2) >> FF_LAMBDA_SHIFT; | ||||
| for (i = 0; i < s->max_b_frames + 1; i++) { | for (i = 0; i < s->max_b_frames + 1; i++) { | ||||
| @@ -1215,14 +1230,15 @@ static int estimate_best_b_count(MpegEncContext *s) | |||||
| input[i + 1].pict_type = is_p ? | input[i + 1].pict_type = is_p ? | ||||
| AV_PICTURE_TYPE_P : AV_PICTURE_TYPE_B; | AV_PICTURE_TYPE_P : AV_PICTURE_TYPE_B; | ||||
| input[i + 1].quality = is_p ? p_lambda : b_lambda; | input[i + 1].quality = is_p ? p_lambda : b_lambda; | ||||
| out_size = avcodec_encode_video(c, outbuf, outbuf_size, | |||||
| &input[i + 1]); | |||||
| out_size = encode_frame(c, &input[i + 1]); | |||||
| rd += (out_size * lambda2) >> (FF_LAMBDA_SHIFT - 3); | rd += (out_size * lambda2) >> (FF_LAMBDA_SHIFT - 3); | ||||
| } | } | ||||
| /* get the delayed frames */ | /* get the delayed frames */ | ||||
| while (out_size) { | while (out_size) { | ||||
| out_size = avcodec_encode_video(c, outbuf, outbuf_size, NULL); | |||||
| out_size = encode_frame(c, NULL); | |||||
| rd += (out_size * lambda2) >> (FF_LAMBDA_SHIFT - 3); | rd += (out_size * lambda2) >> (FF_LAMBDA_SHIFT - 3); | ||||
| } | } | ||||
| @@ -1234,7 +1250,6 @@ static int estimate_best_b_count(MpegEncContext *s) | |||||
| } | } | ||||
| } | } | ||||
| av_freep(&outbuf); | |||||
| avcodec_close(c); | avcodec_close(c); | ||||
| av_freep(&c); | av_freep(&c); | ||||
| @@ -94,7 +94,8 @@ void avcodec_get_context_defaults2(AVCodecContext *s, enum AVMediaType codec_typ | |||||
| } | } | ||||
| #endif | #endif | ||||
| int avcodec_get_context_defaults3(AVCodecContext *s, AVCodec *codec){ | |||||
| int avcodec_get_context_defaults3(AVCodecContext *s, const AVCodec *codec) | |||||
| { | |||||
| int flags=0; | int flags=0; | ||||
| memset(s, 0, sizeof(AVCodecContext)); | memset(s, 0, sizeof(AVCodecContext)); | ||||
| @@ -146,7 +147,8 @@ int avcodec_get_context_defaults3(AVCodecContext *s, AVCodec *codec){ | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| AVCodecContext *avcodec_alloc_context3(AVCodec *codec){ | |||||
| AVCodecContext *avcodec_alloc_context3(const AVCodec *codec) | |||||
| { | |||||
| AVCodecContext *avctx= av_malloc(sizeof(AVCodecContext)); | AVCodecContext *avctx= av_malloc(sizeof(AVCodecContext)); | ||||
| if(avctx==NULL) return NULL; | if(avctx==NULL) return NULL; | ||||
| @@ -115,7 +115,8 @@ void av_fast_padded_mallocz(void *ptr, unsigned int *size, size_t min_size) | |||||
| /* encoder management */ | /* encoder management */ | ||||
| static AVCodec *first_avcodec = NULL; | static AVCodec *first_avcodec = NULL; | ||||
| AVCodec *av_codec_next(AVCodec *c){ | |||||
| AVCodec *av_codec_next(const AVCodec *c) | |||||
| { | |||||
| if(c) return c->next; | if(c) return c->next; | ||||
| else return first_avcodec; | else return first_avcodec; | ||||
| } | } | ||||
| @@ -131,12 +132,12 @@ static void avcodec_init(void) | |||||
| ff_dsputil_static_init(); | ff_dsputil_static_init(); | ||||
| } | } | ||||
| int av_codec_is_encoder(AVCodec *codec) | |||||
| int av_codec_is_encoder(const AVCodec *codec) | |||||
| { | { | ||||
| return codec && (codec->encode || codec->encode2); | return codec && (codec->encode || codec->encode2); | ||||
| } | } | ||||
| int av_codec_is_decoder(AVCodec *codec) | |||||
| int av_codec_is_decoder(const AVCodec *codec) | |||||
| { | { | ||||
| return codec && codec->decode; | return codec && codec->decode; | ||||
| } | } | ||||
| @@ -750,7 +751,7 @@ int attribute_align_arg avcodec_open(AVCodecContext *avctx, AVCodec *codec) | |||||
| } | } | ||||
| #endif | #endif | ||||
| int attribute_align_arg avcodec_open2(AVCodecContext *avctx, AVCodec *codec, AVDictionary **options) | |||||
| int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options) | |||||
| { | { | ||||
| int ret = 0; | int ret = 0; | ||||
| AVDictionary *tmp = NULL; | AVDictionary *tmp = NULL; | ||||
| @@ -1888,7 +1889,7 @@ void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode) | |||||
| const char *codec_type; | const char *codec_type; | ||||
| const char *codec_name; | const char *codec_name; | ||||
| const char *profile = NULL; | const char *profile = NULL; | ||||
| AVCodec *p; | |||||
| const AVCodec *p; | |||||
| int bitrate; | int bitrate; | ||||
| AVRational display_aspect_ratio; | AVRational display_aspect_ratio; | ||||
| @@ -382,6 +382,21 @@ int ffurl_get_file_handle(URLContext *h) | |||||
| return h->prot->url_get_file_handle(h); | return h->prot->url_get_file_handle(h); | ||||
| } | } | ||||
| int ffurl_get_multi_file_handle(URLContext *h, int **handles, int *numhandles) | |||||
| { | |||||
| if (!h->prot->url_get_multi_file_handle) { | |||||
| if (!h->prot->url_get_file_handle) | |||||
| return AVERROR(ENOSYS); | |||||
| *handles = av_malloc(sizeof(*handles)); | |||||
| if (!*handles) | |||||
| return AVERROR(ENOMEM); | |||||
| *numhandles = 1; | |||||
| *handles[0] = h->prot->url_get_file_handle(h); | |||||
| return 0; | |||||
| } | |||||
| return h->prot->url_get_multi_file_handle(h, handles, numhandles); | |||||
| } | |||||
| int ffurl_shutdown(URLContext *h, int flags) | int ffurl_shutdown(URLContext *h, int flags) | ||||
| { | { | ||||
| if (!h->prot->url_shutdown) | if (!h->prot->url_shutdown) | ||||
| @@ -41,6 +41,8 @@ | |||||
| #include "libavutil/opt.h" | #include "libavutil/opt.h" | ||||
| #include "libavutil/timecode.h" | #include "libavutil/timecode.h" | ||||
| #define MAX_AUDIO_FRAME_SIZE 192000 // 1 second of 48khz 32bit audio | |||||
| struct DVMuxContext { | struct DVMuxContext { | ||||
| AVClass *av_class; | AVClass *av_class; | ||||
| const DVprofile* sys; /* current DV profile, e.g.: 525/60, 625/50 */ | const DVprofile* sys; /* current DV profile, e.g.: 525/60, 625/50 */ | ||||
| @@ -241,7 +243,7 @@ static int dv_assemble_frame(DVMuxContext *c, AVStream* st, | |||||
| for (i = 0; i < c->n_ast && st != c->ast[i]; i++); | for (i = 0; i < c->n_ast && st != c->ast[i]; i++); | ||||
| /* FIXME: we have to have more sensible approach than this one */ | /* FIXME: we have to have more sensible approach than this one */ | ||||
| if (av_fifo_size(c->audio_data[i]) + data_size >= 100*AVCODEC_MAX_AUDIO_FRAME_SIZE) | |||||
| if (av_fifo_size(c->audio_data[i]) + data_size >= 100*MAX_AUDIO_FRAME_SIZE) | |||||
| av_log(st->codec, AV_LOG_ERROR, "Can't process DV frame #%d. Insufficient video data or severe sync problem.\n", c->frames); | av_log(st->codec, AV_LOG_ERROR, "Can't process DV frame #%d. Insufficient video data or severe sync problem.\n", c->frames); | ||||
| av_fifo_generic_write(c->audio_data[i], data, data_size, NULL); | av_fifo_generic_write(c->audio_data[i], data, data_size, NULL); | ||||
| @@ -329,7 +331,7 @@ static DVMuxContext* dv_init_mux(AVFormatContext* s) | |||||
| c->start_time = ff_iso8601_to_unix_time(t->value); | c->start_time = ff_iso8601_to_unix_time(t->value); | ||||
| for (i=0; i < c->n_ast; i++) { | for (i=0; i < c->n_ast; i++) { | ||||
| if (c->ast[i] && !(c->audio_data[i]=av_fifo_alloc(100*AVCODEC_MAX_AUDIO_FRAME_SIZE))) { | |||||
| if (c->ast[i] && !(c->audio_data[i]=av_fifo_alloc(100*MAX_AUDIO_FRAME_SIZE))) { | |||||
| while (i > 0) { | while (i > 0) { | ||||
| i--; | i--; | ||||
| av_fifo_free(c->audio_data[i]); | av_fifo_free(c->audio_data[i]); | ||||
| @@ -28,6 +28,7 @@ | |||||
| #include "config.h" | #include "config.h" | ||||
| #include "rtmpdh.h" | #include "rtmpdh.h" | ||||
| #include "libavutil/random_seed.h" | |||||
| #define P1024 \ | #define P1024 \ | ||||
| "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ | "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ | ||||
| @@ -78,7 +79,14 @@ | |||||
| ret = (mpz_set_str(bn, buf, 16) == 0); \ | ret = (mpz_set_str(bn, buf, 16) == 0); \ | ||||
| } while (0) | } while (0) | ||||
| #define bn_modexp(bn, y, q, p) mpz_powm(bn, y, q, p) | #define bn_modexp(bn, y, q, p) mpz_powm(bn, y, q, p) | ||||
| #define bn_random(bn, num_bytes) mpz_random(bn, num_bytes); | |||||
| #define bn_random(bn, num_bytes) \ | |||||
| do { \ | |||||
| gmp_randstate_t rs; \ | |||||
| gmp_randinit_mt(rs); \ | |||||
| gmp_randseed_ui(rs, av_get_random_seed()); \ | |||||
| mpz_urandomb(bn, rs, num_bytes); \ | |||||
| gmp_randclear(rs); \ | |||||
| } while (0) | |||||
| #elif CONFIG_GCRYPT | #elif CONFIG_GCRYPT | ||||
| #define bn_new(bn) bn = gcry_mpi_new(1) | #define bn_new(bn) bn = gcry_mpi_new(1) | ||||
| #define bn_free(bn) gcry_mpi_release(bn) | #define bn_free(bn) gcry_mpi_release(bn) | ||||
| @@ -71,11 +71,6 @@ void ff_rtp_send_punch_packets(URLContext* rtp_handle); | |||||
| */ | */ | ||||
| int ff_rtp_check_and_send_back_rr(RTPDemuxContext *s, int count); | int ff_rtp_check_and_send_back_rr(RTPDemuxContext *s, int count); | ||||
| /** | |||||
| * Get the file handle for the RTCP socket. | |||||
| */ | |||||
| int ff_rtp_get_rtcp_file_handle(URLContext *h); | |||||
| // these statistics are used for rtcp receiver reports... | // these statistics are used for rtcp receiver reports... | ||||
| typedef struct { | typedef struct { | ||||
| uint16_t max_seq; ///< highest sequence number seen | uint16_t max_seq; ///< highest sequence number seen | ||||
| @@ -316,18 +316,27 @@ static int rtp_get_file_handle(URLContext *h) | |||||
| return s->rtp_fd; | return s->rtp_fd; | ||||
| } | } | ||||
| int ff_rtp_get_rtcp_file_handle(URLContext *h) { | |||||
| static int rtp_get_multi_file_handle(URLContext *h, int **handles, | |||||
| int *numhandles) | |||||
| { | |||||
| RTPContext *s = h->priv_data; | RTPContext *s = h->priv_data; | ||||
| return s->rtcp_fd; | |||||
| int *hs = *handles = av_malloc(sizeof(**handles) * 2); | |||||
| if (!hs) | |||||
| return AVERROR(ENOMEM); | |||||
| hs[0] = s->rtp_fd; | |||||
| hs[1] = s->rtcp_fd; | |||||
| *numhandles = 2; | |||||
| return 0; | |||||
| } | } | ||||
| URLProtocol ff_rtp_protocol = { | URLProtocol ff_rtp_protocol = { | ||||
| .name = "rtp", | |||||
| .url_open = rtp_open, | |||||
| .url_read = rtp_read, | |||||
| .url_write = rtp_write, | |||||
| .url_close = rtp_close, | |||||
| .url_get_file_handle = rtp_get_file_handle, | |||||
| .priv_data_size = sizeof(RTPContext), | |||||
| .flags = URL_PROTOCOL_FLAG_NETWORK, | |||||
| .name = "rtp", | |||||
| .url_open = rtp_open, | |||||
| .url_read = rtp_read, | |||||
| .url_write = rtp_write, | |||||
| .url_close = rtp_close, | |||||
| .url_get_file_handle = rtp_get_file_handle, | |||||
| .url_get_multi_file_handle = rtp_get_multi_file_handle, | |||||
| .priv_data_size = sizeof(RTPContext), | |||||
| .flags = URL_PROTOCOL_FLAG_NETWORK, | |||||
| }; | }; | ||||
| @@ -1690,6 +1690,7 @@ static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st, | |||||
| int n, i, ret, tcp_fd, timeout_cnt = 0; | int n, i, ret, tcp_fd, timeout_cnt = 0; | ||||
| int max_p = 0; | int max_p = 0; | ||||
| struct pollfd *p = rt->p; | struct pollfd *p = rt->p; | ||||
| int *fds = NULL, fdsnum, fdsidx; | |||||
| for (;;) { | for (;;) { | ||||
| if (ff_check_interrupt(&s->interrupt_callback)) | if (ff_check_interrupt(&s->interrupt_callback)) | ||||
| @@ -1707,10 +1708,21 @@ static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st, | |||||
| for (i = 0; i < rt->nb_rtsp_streams; i++) { | for (i = 0; i < rt->nb_rtsp_streams; i++) { | ||||
| rtsp_st = rt->rtsp_streams[i]; | rtsp_st = rt->rtsp_streams[i]; | ||||
| if (rtsp_st->rtp_handle) { | if (rtsp_st->rtp_handle) { | ||||
| p[max_p].fd = ffurl_get_file_handle(rtsp_st->rtp_handle); | |||||
| p[max_p++].events = POLLIN; | |||||
| p[max_p].fd = ff_rtp_get_rtcp_file_handle(rtsp_st->rtp_handle); | |||||
| p[max_p++].events = POLLIN; | |||||
| if (ret = ffurl_get_multi_file_handle(rtsp_st->rtp_handle, | |||||
| &fds, &fdsnum)) { | |||||
| av_log(s, AV_LOG_ERROR, "Unable to recover rtp ports\n"); | |||||
| return ret; | |||||
| } | |||||
| if (fdsnum != 2) { | |||||
| av_log(s, AV_LOG_ERROR, | |||||
| "Number of fds %d not supported\n", fdsnum); | |||||
| return AVERROR_INVALIDDATA; | |||||
| } | |||||
| for (fdsidx = 0; fdsidx < fdsnum; fdsidx++) { | |||||
| p[max_p].fd = fds[fdsidx]; | |||||
| p[max_p++].events = POLLIN; | |||||
| } | |||||
| av_free(fds); | |||||
| } | } | ||||
| } | } | ||||
| n = poll(p, max_p, POLL_TIMEOUT_MS); | n = poll(p, max_p, POLL_TIMEOUT_MS); | ||||
| @@ -23,7 +23,7 @@ | |||||
| #include "internal.h" | #include "internal.h" | ||||
| const AVCodecTag ff_swf_codec_tags[] = { | const AVCodecTag ff_swf_codec_tags[] = { | ||||
| { CODEC_ID_FLV1, 0x02 }, | |||||
| { CODEC_ID_VP6F, 0x04 }, | |||||
| { CODEC_ID_NONE, 0 }, | |||||
| { AV_CODEC_ID_FLV1, 0x02 }, | |||||
| { AV_CODEC_ID_VP6F, 0x04 }, | |||||
| { AV_CODEC_ID_NONE, 0 }, | |||||
| }; | }; | ||||
| @@ -24,12 +24,12 @@ | |||||
| #include "swf.h" | #include "swf.h" | ||||
| static const AVCodecTag swf_audio_codec_tags[] = { | static const AVCodecTag swf_audio_codec_tags[] = { | ||||
| { CODEC_ID_PCM_S16LE, 0x00 }, | |||||
| { CODEC_ID_ADPCM_SWF, 0x01 }, | |||||
| { CODEC_ID_MP3, 0x02 }, | |||||
| { CODEC_ID_PCM_S16LE, 0x03 }, | |||||
| // { CODEC_ID_NELLYMOSER, 0x06 }, | |||||
| { CODEC_ID_NONE, 0 }, | |||||
| { AV_CODEC_ID_PCM_S16LE, 0x00 }, | |||||
| { AV_CODEC_ID_ADPCM_SWF, 0x01 }, | |||||
| { AV_CODEC_ID_MP3, 0x02 }, | |||||
| { AV_CODEC_ID_PCM_S16LE, 0x03 }, | |||||
| // { AV_CODEC_ID_NELLYMOSER, 0x06 }, | |||||
| { AV_CODEC_ID_NONE, 0 }, | |||||
| }; | }; | ||||
| static int get_swf_tag(AVIOContext *pb, int *len_ptr) | static int get_swf_tag(AVIOContext *pb, int *len_ptr) | ||||
| @@ -81,6 +81,8 @@ typedef struct URLProtocol { | |||||
| int64_t (*url_read_seek)(URLContext *h, int stream_index, | int64_t (*url_read_seek)(URLContext *h, int stream_index, | ||||
| int64_t timestamp, int flags); | int64_t timestamp, int flags); | ||||
| int (*url_get_file_handle)(URLContext *h); | int (*url_get_file_handle)(URLContext *h); | ||||
| int (*url_get_multi_file_handle)(URLContext *h, int **handles, | |||||
| int *numhandles); | |||||
| int (*url_shutdown)(URLContext *h, int flags); | int (*url_shutdown)(URLContext *h, int flags); | ||||
| int priv_data_size; | int priv_data_size; | ||||
| const AVClass *priv_data_class; | const AVClass *priv_data_class; | ||||
| @@ -202,6 +204,13 @@ int64_t ffurl_size(URLContext *h); | |||||
| */ | */ | ||||
| int ffurl_get_file_handle(URLContext *h); | int ffurl_get_file_handle(URLContext *h); | ||||
| /** | |||||
| * Return the file descriptors associated with this URL. | |||||
| * | |||||
| * @return 0 on success or <0 on error. | |||||
| */ | |||||
| int ffurl_get_multi_file_handle(URLContext *h, int **handles, int *numhandles); | |||||
| /** | /** | ||||
| * Signal the URLContext that we are done reading or writing the stream. | * Signal the URLContext that we are done reading or writing the stream. | ||||
| * | * | ||||