diff --git a/libavcodec/aaccoder.c b/libavcodec/aaccoder.c index f08b34b823..60be5ef47d 100644 --- a/libavcodec/aaccoder.c +++ b/libavcodec/aaccoder.c @@ -110,7 +110,7 @@ static av_always_inline float quantize_and_encode_band_cost_template( const float IQ = ff_aac_pow2sf_tab[200 + scale_idx - SCALE_ONE_POS + SCALE_DIV_512]; const float Q = ff_aac_pow2sf_tab[200 - scale_idx + SCALE_ONE_POS - SCALE_DIV_512]; const float CLIPPED_ESCAPE = 165140.0f*IQ; - int i, j, k; + int i, j; float cost = 0; const int dim = BT_PAIR ? 2 : 4; int resbits = 0; @@ -149,10 +149,10 @@ static av_always_inline float quantize_and_encode_band_cost_template( curbits = ff_aac_spectral_bits[cb-1][curidx]; vec = &ff_aac_codebook_vectors[cb-1][curidx*dim]; if (BT_UNSIGNED) { - for (k = 0; k < dim; k++) { - float t = fabsf(in[i+k]); + for (j = 0; j < dim; j++) { + float t = fabsf(in[i+j]); float di; - if (BT_ESC && vec[k] == 64.0f) { //FIXME: slow + if (BT_ESC && vec[j] == 64.0f) { //FIXME: slow if (t >= CLIPPED_ESCAPE) { di = t - CLIPPED_ESCAPE; curbits += 21; @@ -162,15 +162,15 @@ static av_always_inline float quantize_and_encode_band_cost_template( curbits += av_log2(c)*2 - 4 + 1; } } else { - di = t - vec[k]*IQ; + di = t - vec[j]*IQ; } - if (vec[k] != 0.0f) + if (vec[j] != 0.0f) curbits++; rd += di*di; } } else { - for (k = 0; k < dim; k++) { - float di = in[i+k] - vec[k]*IQ; + for (j = 0; j < dim; j++) { + float di = in[i+j] - vec[j]*IQ; rd += di*di; } } diff --git a/libavcodec/ac3dsp.c b/libavcodec/ac3dsp.c index ec0b82d4fc..0b5b501a27 100644 --- a/libavcodec/ac3dsp.c +++ b/libavcodec/ac3dsp.c @@ -19,6 +19,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/avassert.h" #include "avcodec.h" #include "ac3.h" #include "ac3dsp.h" @@ -149,6 +150,27 @@ static int ac3_compute_mantissa_size_c(int mant_cnt[5], uint8_t *bap, return bits; } +static void ac3_extract_exponents_c(uint8_t *exp, int32_t *coef, int nb_coefs) +{ + int i; + + for (i = 0; i < nb_coefs; i++) { + int e; + int v = abs(coef[i]); + if (v == 0) + e = 24; + else { + e = 23 - av_log2(v); + if (e >= 24) { + e = 24; + coef[i] = 0; + } + av_assert2(e >= 0); + } + exp[i] = e; + } +} + av_cold void ff_ac3dsp_init(AC3DSPContext *c, int bit_exact) { c->ac3_exponent_min = ac3_exponent_min_c; @@ -158,6 +180,7 @@ av_cold void ff_ac3dsp_init(AC3DSPContext *c, int bit_exact) c->float_to_fixed24 = float_to_fixed24_c; c->bit_alloc_calc_bap = ac3_bit_alloc_calc_bap_c; c->compute_mantissa_size = ac3_compute_mantissa_size_c; + c->extract_exponents = ac3_extract_exponents_c; if (ARCH_ARM) ff_ac3dsp_init_arm(c, bit_exact); diff --git a/libavcodec/ac3dsp.h b/libavcodec/ac3dsp.h index 08680f382d..878c802187 100644 --- a/libavcodec/ac3dsp.h +++ b/libavcodec/ac3dsp.h @@ -105,6 +105,8 @@ typedef struct AC3DSPContext { * Calculate the number of bits needed to encode a set of mantissas. */ int (*compute_mantissa_size)(int mant_cnt[5], uint8_t *bap, int nb_coefs); + + void (*extract_exponents)(uint8_t *exp, int32_t *coef, int nb_coefs); } AC3DSPContext; void ff_ac3dsp_init (AC3DSPContext *c, int bit_exact); diff --git a/libavcodec/ac3enc.c b/libavcodec/ac3enc.c index 5f2868f5e6..1c353b6a43 100644 --- a/libavcodec/ac3enc.c +++ b/libavcodec/ac3enc.c @@ -329,6 +329,36 @@ static const int64_t ac3_channel_layouts[] = { }; +/** + * LUT to select the bandwidth code based on the bit rate, sample rate, and + * number of full-bandwidth channels. + * bandwidth_tab[fbw_channels-1][sample rate code][bit rate code] + */ +static const uint8_t ac3_bandwidth_tab[5][3][19] = { +// 32 40 48 56 64 80 96 112 128 160 192 224 256 320 384 448 512 576 640 + + { { 0, 0, 0, 12, 16, 32, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48 }, + { 0, 0, 0, 16, 20, 36, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56 }, + { 0, 0, 0, 32, 40, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60 } }, + + { { 0, 0, 0, 0, 0, 0, 0, 20, 24, 32, 48, 48, 48, 48, 48, 48, 48, 48, 48 }, + { 0, 0, 0, 0, 0, 0, 4, 24, 28, 36, 56, 56, 56, 56, 56, 56, 56, 56, 56 }, + { 0, 0, 0, 0, 0, 0, 20, 44, 52, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60 } }, + + { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 24, 32, 40, 48, 48, 48, 48, 48, 48 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 4, 20, 28, 36, 44, 56, 56, 56, 56, 56, 56 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 20, 40, 48, 60, 60, 60, 60, 60, 60, 60, 60 } }, + + { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 24, 32, 48, 48, 48, 48, 48, 48 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 28, 36, 56, 56, 56, 56, 56, 56 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 48, 60, 60, 60, 60, 60, 60, 60 } }, + + { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 20, 32, 40, 48, 48, 48, 48 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 24, 36, 44, 56, 56, 56, 56 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 44, 60, 60, 60, 60, 60, 60 } } +}; + + /** * Adjust the frame size to make the average bit rate match the target bit rate. * This is only needed for 11025, 22050, and 44100 sample rates. @@ -532,28 +562,13 @@ static av_cold void exponent_init(AC3EncodeContext *s) */ static void extract_exponents(AC3EncodeContext *s) { - int blk, ch, i; + int blk, ch; for (ch = 0; ch < s->channels; ch++) { for (blk = 0; blk < AC3_MAX_BLOCKS; blk++) { AC3Block *block = &s->blocks[blk]; - uint8_t *exp = block->exp[ch]; - int32_t *coef = block->fixed_coef[ch]; - for (i = 0; i < AC3_MAX_COEFS; i++) { - int e; - int v = abs(coef[i]); - if (v == 0) - e = 24; - else { - e = 23 - av_log2(v); - if (e >= 24) { - e = 24; - coef[i] = 0; - } - av_assert2(e >= 0); - } - exp[i] = e; - } + s->ac3dsp.extract_exponents(block->exp[ch], block->fixed_coef[ch], + AC3_MAX_COEFS); } } } @@ -2095,9 +2110,7 @@ static av_cold void set_bandwidth(AC3EncodeContext *s) bw_code = av_clip((fbw_coeffs - 73) / 3, 0, 60); } else { /* use default bandwidth setting */ - /* XXX: should compute the bandwidth according to the frame - size, so that we avoid annoying high frequency artifacts */ - bw_code = 50; + bw_code = ac3_bandwidth_tab[s->fbw_channels-1][s->bit_alloc.sr_code][s->frame_size_code/2]; } /* set number of coefficients for each channel */ diff --git a/libavformat/applehttp.c b/libavformat/applehttp.c index 8a6b232e51..639cfcdce4 100644 --- a/libavformat/applehttp.c +++ b/libavformat/applehttp.c @@ -30,6 +30,9 @@ #include "avformat.h" #include "internal.h" #include +#include "avio_internal.h" + +#define INITIAL_BUFFER_SIZE 32768 /* * An apple http stream consists of a playlist with media segment files, @@ -56,26 +59,31 @@ struct segment { struct variant { int bandwidth; char url[MAX_URL_SIZE]; - AVIOContext *pb; + AVIOContext pb; + uint8_t* read_buffer; + URLContext *input; + AVFormatContext *parent; + int index; AVFormatContext *ctx; AVPacket pkt; int stream_offset; + int finished; + int target_duration; int start_seq_no; int n_segments; struct segment **segments; - int needed; + int needed, cur_needed; + int cur_seq_no; + int64_t last_load_time; }; typedef struct AppleHTTPContext { - int target_duration; - int finished; int n_variants; struct variant **variants; int cur_seq_no; - int64_t last_load_time; - int64_t last_packet_dts; - int max_start_seq, min_end_seq; + int end_of_segment; + int first_packet; } AppleHTTPContext; static int read_chomp_line(AVIOContext *s, char *buf, int maxlen) @@ -102,8 +110,9 @@ static void free_variant_list(AppleHTTPContext *c) struct variant *var = c->variants[i]; free_segment_list(var); av_free_packet(&var->pkt); - if (var->pb) - avio_close(var->pb); + av_free(var->pb.buffer); + if (var->input) + url_close(var->input); if (var->ctx) { var->ctx->pb = NULL; av_close_input_file(var->ctx); @@ -170,9 +179,10 @@ static int parse_playlist(AppleHTTPContext *c, const char *url, goto fail; } - if (var) + if (var) { free_segment_list(var); - c->finished = 0; + var->finished = 0; + } while (!url_feof(in)) { read_chomp_line(in, line, sizeof(line)); if (av_strstart(line, "#EXT-X-STREAM-INF:", &ptr)) { @@ -182,7 +192,14 @@ static int parse_playlist(AppleHTTPContext *c, const char *url, &info); bandwidth = atoi(info.bandwidth); } else if (av_strstart(line, "#EXT-X-TARGETDURATION:", &ptr)) { - c->target_duration = atoi(ptr); + if (!var) { + var = new_variant(c, 0, url, NULL); + if (!var) { + ret = AVERROR(ENOMEM); + goto fail; + } + } + var->target_duration = atoi(ptr); } else if (av_strstart(line, "#EXT-X-MEDIA-SEQUENCE:", &ptr)) { if (!var) { var = new_variant(c, 0, url, NULL); @@ -193,7 +210,8 @@ static int parse_playlist(AppleHTTPContext *c, const char *url, } var->start_seq_no = atoi(ptr); } else if (av_strstart(line, "#EXT-X-ENDLIST", &ptr)) { - c->finished = 1; + if (var) + var->finished = 1; } else if (av_strstart(line, "#EXTINF:", &ptr)) { is_segment = 1; duration = atoi(ptr); @@ -229,7 +247,8 @@ static int parse_playlist(AppleHTTPContext *c, const char *url, } } } - c->last_load_time = av_gettime(); + if (var) + var->last_load_time = av_gettime(); fail: if (close_in) @@ -237,6 +256,71 @@ fail: return ret; } +static int read_data(void *opaque, uint8_t *buf, int buf_size) +{ + struct variant *v = opaque; + AppleHTTPContext *c = v->parent->priv_data; + int ret, i; + +restart: + if (!v->input) { +reload: + /* If this is a live stream and target_duration has elapsed since + * the last playlist reload, reload the variant playlists now. */ + if (!v->finished && + av_gettime() - v->last_load_time >= v->target_duration*1000000 && + (ret = parse_playlist(c, v->url, v, NULL)) < 0) + return ret; + if (v->cur_seq_no < v->start_seq_no) { + av_log(NULL, AV_LOG_WARNING, + "skipping %d segments ahead, expired from playlists\n", + v->start_seq_no - v->cur_seq_no); + v->cur_seq_no = v->start_seq_no; + } + if (v->cur_seq_no >= v->start_seq_no + v->n_segments) { + if (v->finished) + return AVERROR_EOF; + while (av_gettime() - v->last_load_time < + v->target_duration*1000000) { + if (url_interrupt_cb()) + return AVERROR_EXIT; + usleep(100*1000); + } + /* Enough time has elapsed since the last reload */ + goto reload; + } + + ret = url_open(&v->input, + v->segments[v->cur_seq_no - v->start_seq_no]->url, + URL_RDONLY); + if (ret < 0) + return ret; + } + ret = url_read(v->input, buf, buf_size); + if (ret > 0) + return ret; + if (ret < 0 && ret != AVERROR_EOF) + return ret; + url_close(v->input); + v->input = NULL; + v->cur_seq_no++; + + c->end_of_segment = 1; + c->cur_seq_no = v->cur_seq_no; + + v->needed = 0; + for (i = v->stream_offset; i < v->stream_offset + v->ctx->nb_streams; i++) { + if (v->parent->streams[i]->discard < AVDISCARD_ALL) + v->needed = 1; + } + if (!v->needed) { + av_log(v->parent, AV_LOG_INFO, "No longer receiving variant %d\n", + v->index); + return AVERROR_EOF; + } + goto restart; +} + static int applehttp_read_header(AVFormatContext *s, AVFormatParameters *ap) { AppleHTTPContext *c = s->priv_data; @@ -268,27 +352,42 @@ static int applehttp_read_header(AVFormatContext *s, AVFormatParameters *ap) /* If this isn't a live stream, calculate the total duration of the * stream. */ - if (c->finished) { + if (c->variants[0]->finished) { int64_t duration = 0; for (i = 0; i < c->variants[0]->n_segments; i++) duration += c->variants[0]->segments[i]->duration; s->duration = duration * AV_TIME_BASE; } - c->min_end_seq = INT_MAX; /* Open the demuxer for each variant */ for (i = 0; i < c->n_variants; i++) { struct variant *v = c->variants[i]; + AVInputFormat *in_fmt = NULL; if (v->n_segments == 0) continue; - c->max_start_seq = FFMAX(c->max_start_seq, v->start_seq_no); - c->min_end_seq = FFMIN(c->min_end_seq, v->start_seq_no + - v->n_segments); - ret = av_open_input_file(&v->ctx, v->segments[0]->url, NULL, 0, NULL); + + v->index = i; + v->needed = 1; + v->parent = s; + + /* If this is a live stream with more than 3 segments, start at the + * third last segment. */ + v->cur_seq_no = v->start_seq_no; + if (!v->finished && v->n_segments > 3) + v->cur_seq_no = v->start_seq_no + v->n_segments - 3; + + v->read_buffer = av_malloc(INITIAL_BUFFER_SIZE); + ffio_init_context(&v->pb, v->read_buffer, INITIAL_BUFFER_SIZE, 0, v, + read_data, NULL, NULL); + v->pb.seekable = 0; + ret = av_probe_input_buffer(&v->pb, &in_fmt, v->segments[0]->url, + NULL, 0, 0); + if (ret < 0) + goto fail; + ret = av_open_input_stream(&v->ctx, &v->pb, v->segments[0]->url, + in_fmt, NULL); if (ret < 0) goto fail; - avio_close(v->ctx->pb); - v->ctx->pb = NULL; v->stream_offset = stream_offset; /* Create new AVStreams for each stream in this variant */ for (j = 0; j < v->ctx->nb_streams; j++) { @@ -301,13 +400,8 @@ static int applehttp_read_header(AVFormatContext *s, AVFormatParameters *ap) } stream_offset += v->ctx->nb_streams; } - c->last_packet_dts = AV_NOPTS_VALUE; - c->cur_seq_no = c->max_start_seq; - /* If this is a live stream with more than 3 segments, start at the - * third last segment. */ - if (!c->finished && c->min_end_seq - c->max_start_seq > 3) - c->cur_seq_no = c->min_end_seq - 2; + c->first_packet = 1; return 0; fail: @@ -315,98 +409,61 @@ fail: return ret; } -static int open_variant(AppleHTTPContext *c, struct variant *var, int skip) +static int recheck_discard_flags(AVFormatContext *s, int first) { - int ret; + AppleHTTPContext *c = s->priv_data; + int i, changed = 0; - if (c->cur_seq_no < var->start_seq_no) { - av_log(NULL, AV_LOG_WARNING, - "seq %d not available in variant %s, skipping\n", - var->start_seq_no, var->url); - return 0; + /* Check if any new streams are needed */ + for (i = 0; i < c->n_variants; i++) + c->variants[i]->cur_needed = 0;; + + for (i = 0; i < s->nb_streams; i++) { + AVStream *st = s->streams[i]; + struct variant *var = c->variants[s->streams[i]->id]; + if (st->discard < AVDISCARD_ALL) + var->cur_needed = 1; } - if (c->cur_seq_no - var->start_seq_no >= var->n_segments) - return c->finished ? AVERROR_EOF : 0; - ret = avio_open(&var->pb, - var->segments[c->cur_seq_no - var->start_seq_no]->url, - URL_RDONLY); - if (ret < 0) - return ret; - var->ctx->pb = var->pb; - /* If this is a new segment in parallel with another one already opened, - * skip ahead so they're all at the same dts. */ - if (skip && c->last_packet_dts != AV_NOPTS_VALUE) { - while (1) { - ret = av_read_frame(var->ctx, &var->pkt); - if (ret < 0) { - if (ret == AVERROR_EOF) { - reset_packet(&var->pkt); - return 0; - } - return ret; - } - if (var->pkt.dts >= c->last_packet_dts) - break; - av_free_packet(&var->pkt); + for (i = 0; i < c->n_variants; i++) { + struct variant *v = c->variants[i]; + if (v->cur_needed && !v->needed) { + v->needed = 1; + changed = 1; + v->cur_seq_no = c->cur_seq_no; + v->pb.eof_reached = 0; + av_log(s, AV_LOG_INFO, "Now receiving variant %d\n", i); + } else if (first && !v->cur_needed && v->needed) { + if (v->input) + url_close(v->input); + v->input = NULL; + v->needed = 0; + changed = 1; + av_log(s, AV_LOG_INFO, "No longer receiving variant %d\n", i); } } - return 0; + return changed; } static int applehttp_read_packet(AVFormatContext *s, AVPacket *pkt) { AppleHTTPContext *c = s->priv_data; - int ret, i, minvariant = -1, first = 1, needed = 0, changed = 0, - variants = 0; + int ret, i, minvariant = -1; - /* Recheck the discard flags - which streams are desired at the moment */ - for (i = 0; i < c->n_variants; i++) - c->variants[i]->needed = 0; - for (i = 0; i < s->nb_streams; i++) { - AVStream *st = s->streams[i]; - struct variant *var = c->variants[s->streams[i]->id]; - if (st->discard < AVDISCARD_ALL) { - var->needed = 1; - needed++; - } - /* Copy the discard flag to the chained demuxer, to indicate which - * streams are desired. */ - var->ctx->streams[i - var->stream_offset]->discard = st->discard; + if (c->first_packet) { + recheck_discard_flags(s, 1); + c->first_packet = 0; } - if (!needed) - return AVERROR_EOF; + start: + c->end_of_segment = 0; for (i = 0; i < c->n_variants; i++) { struct variant *var = c->variants[i]; - /* Close unneeded streams, open newly requested streams */ - if (var->pb && !var->needed) { - av_log(s, AV_LOG_DEBUG, - "Closing variant stream %d, no longer needed\n", i); - av_free_packet(&var->pkt); - reset_packet(&var->pkt); - avio_close(var->pb); - var->pb = NULL; - changed = 1; - } else if (!var->pb && var->needed) { - if (first) - av_log(s, AV_LOG_DEBUG, "Opening variant stream %d\n", i); - if (first && !c->finished) - if ((ret = parse_playlist(c, var->url, var, NULL)) < 0) - return ret; - ret = open_variant(c, var, first); - if (ret < 0) - return ret; - changed = 1; - } - /* Count the number of open variants */ - if (var->pb) - variants++; /* Make sure we've got one buffered packet from each open variant * stream */ - if (var->pb && !var->pkt.data) { + if (var->needed && !var->pkt.data) { ret = av_read_frame(var->ctx, &var->pkt); if (ret < 0) { - if (!url_feof(var->pb)) + if (!url_feof(&var->pb)) return ret; reset_packet(&var->pkt); } @@ -418,70 +475,18 @@ start: minvariant = i; } } - if (first && changed) - av_log(s, AV_LOG_INFO, "Receiving %d variant streams\n", variants); + if (c->end_of_segment) { + if (recheck_discard_flags(s, 0)) + goto start; + } /* If we got a packet, return it */ if (minvariant >= 0) { *pkt = c->variants[minvariant]->pkt; pkt->stream_index += c->variants[minvariant]->stream_offset; reset_packet(&c->variants[minvariant]->pkt); - c->last_packet_dts = pkt->dts; return 0; } - /* No more packets - eof reached in all variant streams, close the - * current segments. */ - for (i = 0; i < c->n_variants; i++) { - struct variant *var = c->variants[i]; - if (var->pb) { - avio_close(var->pb); - var->pb = NULL; - } - } - /* Indicate that we're opening the next segment, not opening a new - * variant stream in parallel, so we shouldn't try to skip ahead. */ - first = 0; - c->cur_seq_no++; -reload: - if (!c->finished) { - /* If this is a live stream and target_duration has elapsed since - * the last playlist reload, reload the variant playlists now. */ - int64_t now = av_gettime(); - if (now - c->last_load_time >= c->target_duration*1000000) { - c->max_start_seq = 0; - c->min_end_seq = INT_MAX; - for (i = 0; i < c->n_variants; i++) { - struct variant *var = c->variants[i]; - if (var->needed) { - if ((ret = parse_playlist(c, var->url, var, NULL)) < 0) - return ret; - c->max_start_seq = FFMAX(c->max_start_seq, - var->start_seq_no); - c->min_end_seq = FFMIN(c->min_end_seq, - var->start_seq_no + var->n_segments); - } - } - } - } - if (c->cur_seq_no < c->max_start_seq) { - av_log(NULL, AV_LOG_WARNING, - "skipping %d segments ahead, expired from playlists\n", - c->max_start_seq - c->cur_seq_no); - c->cur_seq_no = c->max_start_seq; - } - /* If more segments exist, open the next one */ - if (c->cur_seq_no < c->min_end_seq) - goto start; - /* We've reached the end of the playlists - return eof if this is a - * non-live stream, wait until the next playlist reload if it is live. */ - if (c->finished) - return AVERROR_EOF; - while (av_gettime() - c->last_load_time < c->target_duration*1000000) { - if (url_interrupt_cb()) - return AVERROR_EXIT; - usleep(100*1000); - } - /* Enough time has elapsed since the last reload */ - goto reload; + return AVERROR_EOF; } static int applehttp_close(AVFormatContext *s) @@ -496,38 +501,40 @@ static int applehttp_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) { AppleHTTPContext *c = s->priv_data; - int64_t pos = 0; - int i; - struct variant *var = c->variants[0]; + int i, j, ret; - if ((flags & AVSEEK_FLAG_BYTE) || !c->finished) + if ((flags & AVSEEK_FLAG_BYTE) || !c->variants[0]->finished) return AVERROR(ENOSYS); - /* Reset the variants */ - c->last_packet_dts = AV_NOPTS_VALUE; + timestamp = av_rescale_rnd(timestamp, 1, stream_index >= 0 ? + s->streams[stream_index]->time_base.den : + AV_TIME_BASE, flags & AVSEEK_FLAG_BACKWARD ? + AV_ROUND_DOWN : AV_ROUND_UP); + ret = AVERROR(EIO); for (i = 0; i < c->n_variants; i++) { + /* Reset reading */ struct variant *var = c->variants[i]; - if (var->pb) { - avio_close(var->pb); - var->pb = NULL; + int64_t pos = 0; + if (var->input) { + url_close(var->input); + var->input = NULL; } av_free_packet(&var->pkt); reset_packet(&var->pkt); - } - - timestamp = av_rescale_rnd(timestamp, 1, stream_index >= 0 ? - s->streams[stream_index]->time_base.den : - AV_TIME_BASE, flags & AVSEEK_FLAG_BACKWARD ? - AV_ROUND_DOWN : AV_ROUND_UP); - /* Locate the segment that contains the target timestamp */ - for (i = 0; i < var->n_segments; i++) { - if (timestamp >= pos && timestamp < pos + var->segments[i]->duration) { - c->cur_seq_no = var->start_seq_no + i; - return 0; + var->pb.eof_reached = 0; + + /* Locate the segment that contains the target timestamp */ + for (j = 0; j < var->n_segments; j++) { + if (timestamp >= pos && + timestamp < pos + var->segments[j]->duration) { + var->cur_seq_no = var->start_seq_no + j; + ret = 0; + break; + } + pos += var->segments[j]->duration; } - pos += var->segments[i]->duration; } - return AVERROR(EIO); + return ret; } static int applehttp_probe(AVProbeData *p) diff --git a/libavformat/applehttpproto.c b/libavformat/applehttpproto.c index 630d02d3d6..6f42992c13 100644 --- a/libavformat/applehttpproto.c +++ b/libavformat/applehttpproto.c @@ -29,6 +29,7 @@ #include "libavutil/avstring.h" #include "avformat.h" #include "internal.h" +#include "url.h" #include /* @@ -240,12 +241,12 @@ static int applehttp_read(URLContext *h, uint8_t *buf, int size) start: if (s->seg_hd) { - ret = url_read(s->seg_hd, buf, size); + ret = ffurl_read(s->seg_hd, buf, size); if (ret > 0) return ret; } if (s->seg_hd) { - url_close(s->seg_hd); + ffurl_close(s->seg_hd); s->seg_hd = NULL; s->cur_seq_no++; } @@ -274,7 +275,7 @@ retry: } url = s->segments[s->cur_seq_no - s->start_seq_no]->url, av_log(NULL, AV_LOG_DEBUG, "opening %s\n", url); - ret = url_open(&s->seg_hd, url, URL_RDONLY); + ret = ffurl_open(&s->seg_hd, url, URL_RDONLY); if (ret < 0) { if (url_interrupt_cb()) return AVERROR_EXIT; @@ -291,7 +292,7 @@ static int applehttp_close(URLContext *h) free_segment_list(s); free_variant_list(s); - url_close(s->seg_hd); + ffurl_close(s->seg_hd); av_free(s); return 0; } diff --git a/libavformat/avio.c b/libavformat/avio.c index 491ebc1780..bae080b01c 100644 --- a/libavformat/avio.c +++ b/libavformat/avio.c @@ -29,6 +29,7 @@ #if CONFIG_NETWORK #include "network.h" #endif +#include "url.h" #if FF_API_URL_CLASS /** @name Logging context. */ @@ -136,20 +137,21 @@ static int url_alloc_for_protocol (URLContext **puc, struct URLProtocol *up, return err; } -int url_connect(URLContext* uc) +int ffurl_connect(URLContext* uc) { int err = uc->prot->url_open(uc, uc->filename, uc->flags); if (err) return err; uc->is_connected = 1; - //We must be careful here as url_seek() could be slow, for example for http + //We must be careful here as ffurl_seek() could be slow, for example for http if( (uc->flags & (URL_WRONLY | URL_RDWR)) || !strcmp(uc->prot->name, "file")) - if(!uc->is_streamed && url_seek(uc, 0, SEEK_SET) < 0) + if(!uc->is_streamed && ffurl_seek(uc, 0, SEEK_SET) < 0) uc->is_streamed= 1; return 0; } +#if FF_API_OLD_AVIO int url_open_protocol (URLContext **puc, struct URLProtocol *up, const char *filename, int flags) { @@ -158,21 +160,70 @@ int url_open_protocol (URLContext **puc, struct URLProtocol *up, ret = url_alloc_for_protocol(puc, up, filename, flags); if (ret) goto fail; - ret = url_connect(*puc); + ret = ffurl_connect(*puc); if (!ret) return 0; fail: - url_close(*puc); + ffurl_close(*puc); *puc = NULL; return ret; } +int url_alloc(URLContext **puc, const char *filename, int flags) +{ + return ffurl_alloc(puc, filename, flags); +} +int url_connect(URLContext* uc) +{ + return ffurl_connect(uc); +} +int url_open(URLContext **puc, const char *filename, int flags) +{ + return ffurl_open(puc, filename, flags); +} +int url_read(URLContext *h, unsigned char *buf, int size) +{ + return ffurl_read(h, buf, size); +} +int url_read_complete(URLContext *h, unsigned char *buf, int size) +{ + return ffurl_read_complete(h, buf, size); +} +int url_write(URLContext *h, const unsigned char *buf, int size) +{ + return ffurl_write(h, buf, size); +} +int64_t url_seek(URLContext *h, int64_t pos, int whence) +{ + return ffurl_seek(h, pos, whence); +} +int url_close(URLContext *h) +{ + return ffurl_close(h); +} +int64_t url_filesize(URLContext *h) +{ + return ffurl_size(h); +} +int url_get_file_handle(URLContext *h) +{ + return ffurl_get_file_handle(h); +} +int url_get_max_packet_size(URLContext *h) +{ + return h->max_packet_size; +} +void url_get_filename(URLContext *h, char *buf, int buf_size) +{ + av_strlcpy(buf, h->filename, buf_size); +} +#endif #define URL_SCHEME_CHARS \ "abcdefghijklmnopqrstuvwxyz" \ "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \ "0123456789+-." -int url_alloc(URLContext **puc, const char *filename, int flags) +int ffurl_alloc(URLContext **puc, const char *filename, int flags) { URLProtocol *up; char proto_str[128], proto_nested[128], *ptr; @@ -200,15 +251,15 @@ int url_alloc(URLContext **puc, const char *filename, int flags) return AVERROR(ENOENT); } -int url_open(URLContext **puc, const char *filename, int flags) +int ffurl_open(URLContext **puc, const char *filename, int flags) { - int ret = url_alloc(puc, filename, flags); + int ret = ffurl_alloc(puc, filename, flags); if (ret) return ret; - ret = url_connect(*puc); + ret = ffurl_connect(*puc); if (!ret) return 0; - url_close(*puc); + ffurl_close(*puc); *puc = NULL; return ret; } @@ -243,21 +294,21 @@ static inline int retry_transfer_wrapper(URLContext *h, unsigned char *buf, int return len; } -int url_read(URLContext *h, unsigned char *buf, int size) +int ffurl_read(URLContext *h, unsigned char *buf, int size) { if (h->flags & URL_WRONLY) return AVERROR(EIO); return retry_transfer_wrapper(h, buf, size, 1, h->prot->url_read); } -int url_read_complete(URLContext *h, unsigned char *buf, int size) +int ffurl_read_complete(URLContext *h, unsigned char *buf, int size) { if (h->flags & URL_WRONLY) return AVERROR(EIO); return retry_transfer_wrapper(h, buf, size, size, h->prot->url_read); } -int url_write(URLContext *h, const unsigned char *buf, int size) +int ffurl_write(URLContext *h, const unsigned char *buf, int size) { if (!(h->flags & (URL_WRONLY | URL_RDWR))) return AVERROR(EIO); @@ -268,7 +319,7 @@ int url_write(URLContext *h, const unsigned char *buf, int size) return retry_transfer_wrapper(h, buf, size, size, h->prot->url_write); } -int64_t url_seek(URLContext *h, int64_t pos, int whence) +int64_t ffurl_seek(URLContext *h, int64_t pos, int whence) { int64_t ret; @@ -278,10 +329,10 @@ int64_t url_seek(URLContext *h, int64_t pos, int whence) return ret; } -int url_close(URLContext *h) +int ffurl_close(URLContext *h) { int ret = 0; - if (!h) return 0; /* can happen when url_open fails */ + if (!h) return 0; /* can happen when ffurl_open fails */ if (h->is_connected && h->prot->url_close) ret = h->prot->url_close(h); @@ -297,45 +348,34 @@ int url_close(URLContext *h) int url_exist(const char *filename) { URLContext *h; - if (url_open(&h, filename, URL_RDONLY) < 0) + if (ffurl_open(&h, filename, URL_RDONLY) < 0) return 0; - url_close(h); + ffurl_close(h); return 1; } -int64_t url_filesize(URLContext *h) +int64_t ffurl_size(URLContext *h) { int64_t pos, size; - size= url_seek(h, 0, AVSEEK_SIZE); + size= ffurl_seek(h, 0, AVSEEK_SIZE); if(size<0){ - pos = url_seek(h, 0, SEEK_CUR); - if ((size = url_seek(h, -1, SEEK_END)) < 0) + pos = ffurl_seek(h, 0, SEEK_CUR); + if ((size = ffurl_seek(h, -1, SEEK_END)) < 0) return size; size++; - url_seek(h, pos, SEEK_SET); + ffurl_seek(h, pos, SEEK_SET); } return size; } -int url_get_file_handle(URLContext *h) +int ffurl_get_file_handle(URLContext *h) { if (!h->prot->url_get_file_handle) return -1; return h->prot->url_get_file_handle(h); } -int url_get_max_packet_size(URLContext *h) -{ - return h->max_packet_size; -} - -void url_get_filename(URLContext *h, char *buf, int buf_size) -{ - av_strlcpy(buf, h->filename, buf_size); -} - - static int default_interrupt_cb(void) { return 0; diff --git a/libavformat/avio.h b/libavformat/avio.h index 19b57b2261..080be91202 100644 --- a/libavformat/avio.h +++ b/libavformat/avio.h @@ -57,11 +57,13 @@ typedef struct URLContext { int is_connected; } URLContext; +#if FF_API_OLD_AVIO typedef struct URLPollEntry { URLContext *handle; int events; int revents; } URLPollEntry; +#endif /** * @defgroup open_modes URL open modes @@ -92,110 +94,27 @@ typedef struct URLPollEntry { typedef int URLInterruptCB(void); +#if FF_API_OLD_AVIO /** - * Create a URLContext for accessing to the resource indicated by - * url, and open it using the URLProtocol up. - * - * @param puc pointer to the location where, in case of success, the - * function puts the pointer to the created URLContext - * @param flags flags which control how the resource indicated by url - * is to be opened - * @return 0 in case of success, a negative value corresponding to an - * AVERROR code in case of failure - */ -int url_open_protocol (URLContext **puc, struct URLProtocol *up, - const char *url, int flags); - -/** - * Create a URLContext for accessing to the resource indicated by - * url, but do not initiate the connection yet. - * - * @param puc pointer to the location where, in case of success, the - * function puts the pointer to the created URLContext - * @param flags flags which control how the resource indicated by url - * is to be opened - * @return 0 in case of success, a negative value corresponding to an - * AVERROR code in case of failure - */ -int url_alloc(URLContext **h, const char *url, int flags); - -/** - * Connect an URLContext that has been allocated by url_alloc - */ -int url_connect(URLContext *h); - -/** - * Create an URLContext for accessing to the resource indicated by - * url, and open it. - * - * @param puc pointer to the location where, in case of success, the - * function puts the pointer to the created URLContext - * @param flags flags which control how the resource indicated by url - * is to be opened - * @return 0 in case of success, a negative value corresponding to an - * AVERROR code in case of failure - */ -int url_open(URLContext **h, const char *url, int flags); - -/** - * Read up to size bytes from the resource accessed by h, and store - * the read bytes in buf. - * - * @return The number of bytes actually read, or a negative value - * corresponding to an AVERROR code in case of error. A value of zero - * indicates that it is not possible to read more from the accessed - * resource (except if the value of the size argument is also zero). - */ -int url_read(URLContext *h, unsigned char *buf, int size); - -/** - * Read as many bytes as possible (up to size), calling the - * read function multiple times if necessary. - * This makes special short-read handling in applications - * unnecessary, if the return value is < size then it is - * certain there was either an error or the end of file was reached. - */ -int url_read_complete(URLContext *h, unsigned char *buf, int size); - -/** - * Write size bytes from buf to the resource accessed by h. - * - * @return the number of bytes actually written, or a negative value - * corresponding to an AVERROR code in case of failure - */ -int url_write(URLContext *h, const unsigned char *buf, int size); - -/** - * Passing this as the "whence" parameter to a seek function causes it to - * return the filesize without seeking anywhere. Supporting this is optional. - * If it is not supported then the seek function will return <0. - */ -#define AVSEEK_SIZE 0x10000 - -/** - * Change the position that will be used by the next read/write - * operation on the resource accessed by h. - * - * @param pos specifies the new position to set - * @param whence specifies how pos should be interpreted, it must be - * one of SEEK_SET (seek from the beginning), SEEK_CUR (seek from the - * current position), SEEK_END (seek from the end), or AVSEEK_SIZE - * (return the filesize of the requested resource, pos is ignored). - * @return a negative value corresponding to an AVERROR code in case - * of failure, or the resulting file position, measured in bytes from - * the beginning of the file. You can use this feature together with - * SEEK_CUR to read the current file position. - */ -int64_t url_seek(URLContext *h, int64_t pos, int whence); - -/** - * Close the resource accessed by the URLContext h, and free the - * memory used by it. - * - * @return a negative value if an error condition occurred, 0 - * otherwise + * @defgroup old_url_funcs Old url_* functions + * @deprecated use the buffered API based on AVIOContext instead + * @{ */ -int url_close(URLContext *h); +attribute_deprecated int url_open_protocol (URLContext **puc, struct URLProtocol *up, + const char *url, int flags); +attribute_deprecated int url_alloc(URLContext **h, const char *url, int flags); +attribute_deprecated int url_connect(URLContext *h); +attribute_deprecated int url_open(URLContext **h, const char *url, int flags); +attribute_deprecated int url_read(URLContext *h, unsigned char *buf, int size); +attribute_deprecated int url_read_complete(URLContext *h, unsigned char *buf, int size); +attribute_deprecated int url_write(URLContext *h, const unsigned char *buf, int size); +attribute_deprecated int64_t url_seek(URLContext *h, int64_t pos, int whence); +attribute_deprecated int url_close(URLContext *h); +attribute_deprecated int64_t url_filesize(URLContext *h); +attribute_deprecated int url_get_file_handle(URLContext *h); +attribute_deprecated int url_get_max_packet_size(URLContext *h); +attribute_deprecated void url_get_filename(URLContext *h, char *buf, int buf_size); +#endif /** * Return a non-zero value if the resource indicated by url @@ -203,38 +122,6 @@ int url_close(URLContext *h); */ int url_exist(const char *url); -/** - * Return the filesize of the resource accessed by h, AVERROR(ENOSYS) - * if the operation is not supported by h, or another negative value - * corresponding to an AVERROR error code in case of failure. - */ -int64_t url_filesize(URLContext *h); - -/** - * Return the file descriptor associated with this URL. For RTP, this - * will return only the RTP file descriptor, not the RTCP file descriptor. - * - * @return the file descriptor associated with this URL, or <0 on error. - */ -int url_get_file_handle(URLContext *h); - -/** - * Return the maximum packet size associated to packetized file - * handle. If the file is not packetized (stream like HTTP or file on - * disk), then 0 is returned. - * - * @param h file handle - * @return maximum packet size in bytes - */ -int url_get_max_packet_size(URLContext *h); - -/** - * Copy the filename of the resource accessed by h to buf. - * - * @param buf_size size in bytes of buf - */ -void url_get_filename(URLContext *h, char *buf, int buf_size); - /** * The callback is called in blocking functions to test regulary if * asynchronous interruption is needed. AVERROR_EXIT is returned @@ -243,8 +130,10 @@ void url_get_filename(URLContext *h, char *buf, int buf_size); */ void url_set_interrupt_cb(URLInterruptCB *interrupt_cb); +#if FF_API_OLD_AVIO /* not implemented */ -int url_poll(URLPollEntry *poll_table, int n, int timeout); +attribute_deprecated int url_poll(URLPollEntry *poll_table, int n, int timeout); +#endif /** * Pause and resume playing - only meaningful if using a network streaming @@ -273,14 +162,6 @@ int av_url_read_pause(URLContext *h, int pause); int64_t av_url_read_seek(URLContext *h, int stream_index, int64_t timestamp, int flags); -/** - * Oring this flag as into the "whence" parameter to a seek function causes it to - * seek by any means (like reopening and linear reading) or other normally unreasonble - * means that can be extreemly slow. - * This may be ignored by the seek code. - */ -#define AVSEEK_FORCE 0x20000 - #define URL_PROTOCOL_FLAG_NESTED_SCHEME 1 /*< The protocol name can be the first part of a nested protocol scheme */ typedef struct URLProtocol { @@ -334,6 +215,10 @@ int av_register_protocol2(URLProtocol *protocol, int size); #define AVIO_SEEKABLE_NORMAL 0x0001 /**< Seeking works like for a local file */ +/** + * @} + */ + /** * Bytestream IO Context. * New fields can be added to the end with minor version bumps. @@ -518,6 +403,21 @@ int avio_put_str(AVIOContext *s, const char *str); */ int avio_put_str16le(AVIOContext *s, const char *str); +/** + * Passing this as the "whence" parameter to a seek function causes it to + * return the filesize without seeking anywhere. Supporting this is optional. + * If it is not supported then the seek function will return <0. + */ +#define AVSEEK_SIZE 0x10000 + +/** + * Oring this flag as into the "whence" parameter to a seek function causes it to + * seek by any means (like reopening and linear reading) or other normally unreasonble + * means that can be extreemly slow. + * This may be ignored by the seek code. + */ +#define AVSEEK_FORCE 0x20000 + /** * fseek() equivalent for AVIOContext. * @return new position or AVERROR. diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.c index 152869bacd..14051cfc3d 100644 --- a/libavformat/aviobuf.c +++ b/libavformat/aviobuf.c @@ -25,6 +25,7 @@ #include "avio.h" #include "avio_internal.h" #include "internal.h" +#include "url.h" #include #define IO_BUFFER_SIZE 32768 @@ -836,7 +837,7 @@ int ffio_fdopen(AVIOContext **s, URLContext *h) uint8_t *buffer; int buffer_size, max_packet_size; - max_packet_size = url_get_max_packet_size(h); + max_packet_size = h->max_packet_size; if (max_packet_size) { buffer_size = max_packet_size; /* no need to bufferize more than one packet */ } else { @@ -854,7 +855,7 @@ int ffio_fdopen(AVIOContext **s, URLContext *h) if (ffio_init_context(*s, buffer, buffer_size, (h->flags & URL_WRONLY || h->flags & URL_RDWR), h, - url_read, url_write, url_seek) < 0) { + ffurl_read, ffurl_write, ffurl_seek) < 0) { av_free(buffer); av_freep(s); return AVERROR(EIO); @@ -953,12 +954,12 @@ int avio_open(AVIOContext **s, const char *filename, int flags) URLContext *h; int err; - err = url_open(&h, filename, flags); + err = ffurl_open(&h, filename, flags); if (err < 0) return err; err = ffio_fdopen(s, h); if (err < 0) { - url_close(h); + ffurl_close(h); return err; } return 0; @@ -970,7 +971,7 @@ int avio_close(AVIOContext *s) av_free(s->buffer); av_free(s); - return url_close(h); + return ffurl_close(h); } #if FF_API_OLD_AVIO diff --git a/libavformat/concat.c b/libavformat/concat.c index 365907912a..c066826bb8 100644 --- a/libavformat/concat.c +++ b/libavformat/concat.c @@ -24,6 +24,7 @@ #include "avformat.h" #include "libavutil/avstring.h" #include "libavutil/mem.h" +#include "url.h" #define AV_CAT_SEPARATOR "|" @@ -46,7 +47,7 @@ static av_cold int concat_close(URLContext *h) struct concat_nodes *nodes = data->nodes; for (i = 0; i != data->length; i++) - err |= url_close(nodes[i].uc); + err |= ffurl_close(nodes[i].uc); av_freep(&data->nodes); av_freep(&h->priv_data); @@ -100,12 +101,12 @@ static av_cold int concat_open(URLContext *h, const char *uri, int flags) uri += len + strspn(uri+len, AV_CAT_SEPARATOR); /* creating URLContext */ - if ((err = url_open(&uc, node_uri, flags)) < 0) + if ((err = ffurl_open(&uc, node_uri, flags)) < 0) break; /* creating size */ - if ((size = url_filesize(uc)) < 0) { - url_close(uc); + if ((size = ffurl_size(uc)) < 0) { + ffurl_close(uc); err = AVERROR(ENOSYS); break; } @@ -135,12 +136,12 @@ static int concat_read(URLContext *h, unsigned char *buf, int size) size_t i = data->current; while (size > 0) { - result = url_read(nodes[i].uc, buf, size); + result = ffurl_read(nodes[i].uc, buf, size); if (result < 0) return total ? total : result; if (!result) if (i + 1 == data->length || - url_seek(nodes[++i].uc, 0, SEEK_SET) < 0) + ffurl_seek(nodes[++i].uc, 0, SEEK_SET) < 0) break; total += result; buf += result; @@ -168,7 +169,7 @@ static int64_t concat_seek(URLContext *h, int64_t pos, int whence) /* get the absolute position */ for (i = 0; i != data->current; i++) pos += nodes[i].size; - pos += url_seek(nodes[i].uc, 0, SEEK_CUR); + pos += ffurl_seek(nodes[i].uc, 0, SEEK_CUR); whence = SEEK_SET; /* fall through with the absolute position */ case SEEK_SET: @@ -179,7 +180,7 @@ static int64_t concat_seek(URLContext *h, int64_t pos, int whence) return AVERROR(EINVAL); } - result = url_seek(nodes[i].uc, pos, whence); + result = ffurl_seek(nodes[i].uc, pos, whence); if (result >= 0) { data->current = i; while (i) diff --git a/libavformat/gopher.c b/libavformat/gopher.c index 767ec22a7c..85a9d965c4 100644 --- a/libavformat/gopher.c +++ b/libavformat/gopher.c @@ -26,6 +26,7 @@ #include "avformat.h" #include "internal.h" #include "network.h" +#include "url.h" typedef struct { URLContext *hd; @@ -34,7 +35,7 @@ typedef struct { static int gopher_write(URLContext *h, const uint8_t *buf, int size) { GopherContext *s = h->priv_data; - return url_write(s->hd, buf, size); + return ffurl_write(s->hd, buf, size); } static int gopher_connect(URLContext *h, const char *path) @@ -68,7 +69,7 @@ static int gopher_close(URLContext *h) { GopherContext *s = h->priv_data; if (s->hd) { - url_close(s->hd); + ffurl_close(s->hd); s->hd = NULL; } av_freep(&h->priv_data); @@ -99,7 +100,7 @@ static int gopher_open(URLContext *h, const char *uri, int flags) ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, NULL); s->hd = NULL; - err = url_open(&s->hd, buf, URL_RDWR); + err = ffurl_open(&s->hd, buf, URL_RDWR); if (err < 0) goto fail; @@ -114,7 +115,7 @@ static int gopher_open(URLContext *h, const char *uri, int flags) static int gopher_read(URLContext *h, uint8_t *buf, int size) { GopherContext *s = h->priv_data; - int len = url_read(s->hd, buf, size); + int len = ffurl_read(s->hd, buf, size); return len; } diff --git a/libavformat/http.c b/libavformat/http.c index 8c5b9431e6..8c6181417a 100644 --- a/libavformat/http.c +++ b/libavformat/http.c @@ -28,6 +28,7 @@ #include "http.h" #include "os_support.h" #include "httpauth.h" +#include "url.h" #include "libavutil/opt.h" /* XXX: POST protocol is not completely implemented because ffmpeg uses @@ -123,7 +124,7 @@ static int http_open_cnx(URLContext *h) port = 80; ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, NULL); - err = url_open(&hd, buf, URL_RDWR); + err = ffurl_open(&hd, buf, URL_RDWR); if (err < 0) goto fail; @@ -133,7 +134,7 @@ static int http_open_cnx(URLContext *h) goto fail; if (s->http_code == 401) { if (cur_auth_type == HTTP_AUTH_NONE && s->auth_state.auth_type != HTTP_AUTH_NONE) { - url_close(hd); + ffurl_close(hd); goto redo; } else goto fail; @@ -141,7 +142,7 @@ static int http_open_cnx(URLContext *h) if ((s->http_code == 301 || s->http_code == 302 || s->http_code == 303 || s->http_code == 307) && location_changed == 1) { /* url moved, get next */ - url_close(hd); + ffurl_close(hd); if (redirects++ >= MAX_REDIRECTS) return AVERROR(EIO); location_changed = 0; @@ -150,7 +151,7 @@ static int http_open_cnx(URLContext *h) return 0; fail: if (hd) - url_close(hd); + ffurl_close(hd); s->hd = NULL; return AVERROR(EIO); } @@ -170,7 +171,7 @@ static int http_getc(HTTPContext *s) { int len; if (s->buf_ptr >= s->buf_end) { - len = url_read(s->hd, s->buffer, BUFFER_SIZE); + len = ffurl_read(s->hd, s->buffer, BUFFER_SIZE); if (len < 0) { return AVERROR(EIO); } else if (len == 0) { @@ -332,7 +333,7 @@ static int http_connect(URLContext *h, const char *path, const char *hoststr, authstr ? authstr : ""); av_freep(&authstr); - if (url_write(s->hd, s->buffer, strlen(s->buffer)) < 0) + if (ffurl_write(s->hd, s->buffer, strlen(s->buffer)) < 0) return AVERROR(EIO); /* init input buffer */ @@ -406,7 +407,7 @@ static int http_read(URLContext *h, uint8_t *buf, int size) } else { if (!s->willclose && s->filesize >= 0 && s->off >= s->filesize) return AVERROR_EOF; - len = url_read(s->hd, buf, size); + len = ffurl_read(s->hd, buf, size); } if (len > 0) { s->off += len; @@ -426,7 +427,7 @@ static int http_write(URLContext *h, const uint8_t *buf, int size) if (s->chunksize == -1) { /* non-chunked data is sent without any special encoding */ - return url_write(s->hd, buf, size); + return ffurl_write(s->hd, buf, size); } /* silently ignore zero-size data since chunk encoding that would @@ -435,9 +436,9 @@ static int http_write(URLContext *h, const uint8_t *buf, int size) /* upload data using chunked encoding */ snprintf(temp, sizeof(temp), "%x\r\n", size); - if ((ret = url_write(s->hd, temp, strlen(temp))) < 0 || - (ret = url_write(s->hd, buf, size)) < 0 || - (ret = url_write(s->hd, crlf, sizeof(crlf) - 1)) < 0) + if ((ret = ffurl_write(s->hd, temp, strlen(temp))) < 0 || + (ret = ffurl_write(s->hd, buf, size)) < 0 || + (ret = ffurl_write(s->hd, crlf, sizeof(crlf) - 1)) < 0) return ret; } return size; @@ -451,12 +452,12 @@ static int http_close(URLContext *h) /* signal end of chunked encoding if used */ if ((h->flags & URL_WRONLY) && s->chunksize != -1) { - ret = url_write(s->hd, footer, sizeof(footer) - 1); + ret = ffurl_write(s->hd, footer, sizeof(footer) - 1); ret = ret > 0 ? 0 : ret; } if (s->hd) - url_close(s->hd); + ffurl_close(s->hd); return ret; } @@ -492,7 +493,7 @@ static int64_t http_seek(URLContext *h, int64_t off, int whence) s->off = old_off; return -1; } - url_close(old_hd); + ffurl_close(old_hd); return off; } @@ -500,7 +501,7 @@ static int http_get_file_handle(URLContext *h) { HTTPContext *s = h->priv_data; - return url_get_file_handle(s->hd); + return ffurl_get_file_handle(s->hd); } URLProtocol ff_http_protocol = { diff --git a/libavformat/md5proto.c b/libavformat/md5proto.c index c391dffedf..421808bb8a 100644 --- a/libavformat/md5proto.c +++ b/libavformat/md5proto.c @@ -25,6 +25,7 @@ #include "libavutil/error.h" #include "avformat.h" #include "avio.h" +#include "url.h" #define PRIV_SIZE 128 @@ -64,11 +65,11 @@ static int md5_close(URLContext *h) av_strstart(filename, "md5:", &filename); if (*filename) { - err = url_open(&out, filename, URL_WRONLY); + err = ffurl_open(&out, filename, URL_WRONLY); if (err) return err; - err = url_write(out, buf, i*2+1); - url_close(out); + err = ffurl_write(out, buf, i*2+1); + ffurl_close(out); } else { if (fwrite(buf, 1, i*2+1, stdout) < i*2+1) err = AVERROR(errno); diff --git a/libavformat/mmsh.c b/libavformat/mmsh.c index 257b973225..476596c78f 100644 --- a/libavformat/mmsh.c +++ b/libavformat/mmsh.c @@ -32,6 +32,7 @@ #include "mms.h" #include "asf.h" #include "http.h" +#include "url.h" #define CHUNK_HEADER_LENGTH 4 // 2bytes chunk type and 2bytes chunk length. #define EXT_HEADER_LENGTH 8 // 4bytes sequence, 2bytes useless and 2bytes chunk length. @@ -63,7 +64,7 @@ static int mmsh_close(URLContext *h) MMSHContext *mmsh = (MMSHContext *)h->priv_data; MMSContext *mms = &mmsh->mms; if (mms->mms_hd) - url_close(mms->mms_hd); + ffurl_close(mms->mms_hd); av_free(mms->streams); av_free(mms->asf_header); av_freep(&h->priv_data); @@ -78,7 +79,7 @@ static ChunkType get_chunk_header(MMSHContext *mmsh, int *len) ChunkType chunk_type; int chunk_len, res, ext_header_len; - res = url_read_complete(mms->mms_hd, chunk_header, CHUNK_HEADER_LENGTH); + res = ffurl_read_complete(mms->mms_hd, chunk_header, CHUNK_HEADER_LENGTH); if (res != CHUNK_HEADER_LENGTH) { av_log(NULL, AV_LOG_ERROR, "Read data packet header failed!\n"); return AVERROR(EIO); @@ -100,7 +101,7 @@ static ChunkType get_chunk_header(MMSHContext *mmsh, int *len) return AVERROR_INVALIDDATA; } - res = url_read_complete(mms->mms_hd, ext_header, ext_header_len); + res = ffurl_read_complete(mms->mms_hd, ext_header, ext_header_len); if (res != ext_header_len) { av_log(NULL, AV_LOG_ERROR, "Read ext header failed!\n"); return AVERROR(EIO); @@ -121,7 +122,7 @@ static int read_data_packet(MMSHContext *mmsh, const int len) len, sizeof(mms->in_buffer)); return AVERROR(EIO); } - res = url_read_complete(mms->mms_hd, mms->in_buffer, len); + res = ffurl_read_complete(mms->mms_hd, mms->in_buffer, len); av_dlog(NULL, "Data packet len = %d\n", len); if (res != len) { av_log(NULL, AV_LOG_ERROR, "Read data packet failed!\n"); @@ -173,7 +174,7 @@ static int get_http_header_data(MMSHContext *mmsh) len, mms->asf_header_size); return AVERROR(EIO); } - res = url_read_complete(mms->mms_hd, mms->asf_header, len); + res = ffurl_read_complete(mms->mms_hd, mms->asf_header, len); if (res != len) { av_log(NULL, AV_LOG_ERROR, "Recv asf header data len %d != expected len %d\n", res, len); @@ -196,7 +197,7 @@ static int get_http_header_data(MMSHContext *mmsh) len, sizeof(mms->in_buffer)); return AVERROR(EIO); } - res = url_read_complete(mms->mms_hd, mms->in_buffer, len); + res = ffurl_read_complete(mms->mms_hd, mms->in_buffer, len); if (res != len) { av_log(NULL, AV_LOG_ERROR, "Read other chunk type data failed!\n"); return AVERROR(EIO); @@ -232,7 +233,7 @@ static int mmsh_open(URLContext *h, const char *uri, int flags) port = 80; // default mmsh protocol port ff_url_join(httpname, sizeof(httpname), "http", NULL, host, port, path); - if (url_alloc(&mms->mms_hd, httpname, URL_RDONLY) < 0) { + if (ffurl_alloc(&mms->mms_hd, httpname, URL_RDONLY) < 0) { return AVERROR(EIO); } @@ -247,7 +248,7 @@ static int mmsh_open(URLContext *h, const char *uri, int flags) host, port, mmsh->request_seq++); ff_http_set_headers(mms->mms_hd, headers); - err = url_connect(mms->mms_hd); + err = ffurl_connect(mms->mms_hd); if (err) { goto fail; } @@ -258,9 +259,9 @@ static int mmsh_open(URLContext *h, const char *uri, int flags) } // close the socket and then reopen it for sending the second play request. - url_close(mms->mms_hd); + ffurl_close(mms->mms_hd); memset(headers, 0, sizeof(headers)); - if (url_alloc(&mms->mms_hd, httpname, URL_RDONLY) < 0) { + if (ffurl_alloc(&mms->mms_hd, httpname, URL_RDONLY) < 0) { return AVERROR(EIO); } stream_selection = av_mallocz(mms->stream_num * 19 + 1); @@ -293,7 +294,7 @@ static int mmsh_open(URLContext *h, const char *uri, int flags) av_dlog(NULL, "out_buffer is %s", headers); ff_http_set_headers(mms->mms_hd, headers); - err = url_connect(mms->mms_hd); + err = ffurl_connect(mms->mms_hd); if (err) { goto fail; } diff --git a/libavformat/mmst.c b/libavformat/mmst.c index e3af4bfbc6..89dd5b3c3c 100644 --- a/libavformat/mmst.c +++ b/libavformat/mmst.c @@ -35,6 +35,7 @@ #include "libavutil/intreadwrite.h" #include "libavcodec/bytestream.h" #include "network.h" +#include "url.h" #define LOCAL_ADDRESS 0xc0a80081 // FIXME get and use correct local ip address. #define LOCAL_PORT 1037 // as above. @@ -138,7 +139,7 @@ static int send_command_packet(MMSTContext *mmst) memset(mms->write_out_ptr, 0, exact_length - len); // write it out. - write_result= url_write(mms->mms_hd, mms->out_buffer, exact_length); + write_result= ffurl_write(mms->mms_hd, mms->out_buffer, exact_length); if(write_result != exact_length) { av_log(NULL, AV_LOG_ERROR, "Failed to write data of length %d: %d (%s)\n", @@ -240,7 +241,7 @@ static MMSSCPacketType get_tcp_server_response(MMSTContext *mmst) MMSSCPacketType packet_type= -1; MMSContext *mms = &mmst->mms; for(;;) { - read_result = url_read_complete(mms->mms_hd, mms->in_buffer, 8); + read_result = ffurl_read_complete(mms->mms_hd, mms->in_buffer, 8); if (read_result != 8) { if(read_result < 0) { av_log(NULL, AV_LOG_ERROR, @@ -260,7 +261,7 @@ static MMSSCPacketType get_tcp_server_response(MMSTContext *mmst) int length_remaining, hr; mmst->incoming_flags= mms->in_buffer[3]; - read_result= url_read_complete(mms->mms_hd, mms->in_buffer+8, 4); + read_result= ffurl_read_complete(mms->mms_hd, mms->in_buffer+8, 4); if(read_result != 4) { av_log(NULL, AV_LOG_ERROR, "Reading command packet length failed: %d (%s)\n", @@ -280,7 +281,7 @@ static MMSSCPacketType get_tcp_server_response(MMSTContext *mmst) length_remaining, sizeof(mms->in_buffer) - 12); return AVERROR_INVALIDDATA; } - read_result = url_read_complete(mms->mms_hd, mms->in_buffer + 12, + read_result = ffurl_read_complete(mms->mms_hd, mms->in_buffer + 12, length_remaining) ; if (read_result != length_remaining) { av_log(NULL, AV_LOG_ERROR, @@ -318,7 +319,7 @@ static MMSSCPacketType get_tcp_server_response(MMSTContext *mmst) } mms->remaining_in_len = length_remaining; mms->read_in_ptr = mms->in_buffer; - read_result= url_read_complete(mms->mms_hd, mms->in_buffer, length_remaining); + read_result= ffurl_read_complete(mms->mms_hd, mms->in_buffer, length_remaining); if(read_result != length_remaining) { av_log(NULL, AV_LOG_ERROR, "Failed to read packet data of size %d: %d (%s)\n", @@ -463,7 +464,7 @@ static int mms_close(URLContext *h) MMSContext *mms = &mmst->mms; if(mms->mms_hd) { send_close_packet(mmst); - url_close(mms->mms_hd); + ffurl_close(mms->mms_hd); } /* free all separately allocated pointers in mms */ @@ -522,7 +523,7 @@ static int mms_open(URLContext *h, const char *uri, int flags) // establish tcp connection. ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, mmst->host, port, NULL); - err = url_open(&mms->mms_hd, tcpname, URL_RDWR); + err = ffurl_open(&mms->mms_hd, tcpname, URL_RDWR); if (err) goto fail; diff --git a/libavformat/rtmppkt.c b/libavformat/rtmppkt.c index 58c3abe345..53c6a5fe19 100644 --- a/libavformat/rtmppkt.c +++ b/libavformat/rtmppkt.c @@ -25,6 +25,7 @@ #include "rtmppkt.h" #include "flv.h" +#include "url.h" void ff_amf_write_bool(uint8_t **dst, int val) { @@ -78,14 +79,14 @@ int ff_rtmp_packet_read(URLContext *h, RTMPPacket *p, enum RTMPPacketType type; int size = 0; - if (url_read(h, &hdr, 1) != 1) + if (ffurl_read(h, &hdr, 1) != 1) return AVERROR(EIO); size++; channel_id = hdr & 0x3F; if (channel_id < 2) { //special case for channel number >= 64 buf[1] = 0; - if (url_read_complete(h, buf, channel_id + 1) != channel_id + 1) + if (ffurl_read_complete(h, buf, channel_id + 1) != channel_id + 1) return AVERROR(EIO); size += channel_id + 1; channel_id = AV_RL16(buf) + 64; @@ -98,28 +99,28 @@ int ff_rtmp_packet_read(URLContext *h, RTMPPacket *p, if (hdr == RTMP_PS_ONEBYTE) { timestamp = prev_pkt[channel_id].ts_delta; } else { - if (url_read_complete(h, buf, 3) != 3) + if (ffurl_read_complete(h, buf, 3) != 3) return AVERROR(EIO); size += 3; timestamp = AV_RB24(buf); if (hdr != RTMP_PS_FOURBYTES) { - if (url_read_complete(h, buf, 3) != 3) + if (ffurl_read_complete(h, buf, 3) != 3) return AVERROR(EIO); size += 3; data_size = AV_RB24(buf); - if (url_read_complete(h, buf, 1) != 1) + if (ffurl_read_complete(h, buf, 1) != 1) return AVERROR(EIO); size++; type = buf[0]; if (hdr == RTMP_PS_TWELVEBYTES) { - if (url_read_complete(h, buf, 4) != 4) + if (ffurl_read_complete(h, buf, 4) != 4) return AVERROR(EIO); size += 4; extra = AV_RL32(buf); } } if (timestamp == 0xFFFFFF) { - if (url_read_complete(h, buf, 4) != 4) + if (ffurl_read_complete(h, buf, 4) != 4) return AVERROR(EIO); timestamp = AV_RB32(buf); } @@ -139,7 +140,7 @@ int ff_rtmp_packet_read(URLContext *h, RTMPPacket *p, prev_pkt[channel_id].extra = extra; while (data_size > 0) { int toread = FFMIN(data_size, chunk_size); - if (url_read_complete(h, p->data + offset, toread) != toread) { + if (ffurl_read_complete(h, p->data + offset, toread) != toread) { ff_rtmp_packet_destroy(p); return AVERROR(EIO); } @@ -147,7 +148,7 @@ int ff_rtmp_packet_read(URLContext *h, RTMPPacket *p, offset += chunk_size; size += chunk_size; if (data_size > 0) { - url_read_complete(h, &t, 1); //marker + ffurl_read_complete(h, &t, 1); //marker size++; if (t != (0xC0 + channel_id)) return -1; @@ -214,15 +215,15 @@ int ff_rtmp_packet_write(URLContext *h, RTMPPacket *pkt, } prev_pkt[pkt->channel_id].extra = pkt->extra; - url_write(h, pkt_hdr, p-pkt_hdr); + ffurl_write(h, pkt_hdr, p-pkt_hdr); size = p - pkt_hdr + pkt->data_size; while (off < pkt->data_size) { int towrite = FFMIN(chunk_size, pkt->data_size - off); - url_write(h, pkt->data + off, towrite); + ffurl_write(h, pkt->data + off, towrite); off += towrite; if (off < pkt->data_size) { uint8_t marker = 0xC0 | pkt->channel_id; - url_write(h, &marker, 1); + ffurl_write(h, &marker, 1); size++; } } diff --git a/libavformat/rtmpproto.c b/libavformat/rtmpproto.c index 748aab33cc..3309038b34 100644 --- a/libavformat/rtmpproto.c +++ b/libavformat/rtmpproto.c @@ -36,6 +36,7 @@ #include "flv.h" #include "rtmp.h" #include "rtmppkt.h" +#include "url.h" /* we can't use av_log() with URLContext yet... */ #if FF_API_URL_CLASS @@ -485,13 +486,13 @@ static int rtmp_handshake(URLContext *s, RTMPContext *rt) tosend[i] = av_lfg_get(&rnd) >> 24; client_pos = rtmp_handshake_imprint_with_digest(tosend + 1); - url_write(rt->stream, tosend, RTMP_HANDSHAKE_PACKET_SIZE + 1); - i = url_read_complete(rt->stream, serverdata, RTMP_HANDSHAKE_PACKET_SIZE + 1); + ffurl_write(rt->stream, tosend, RTMP_HANDSHAKE_PACKET_SIZE + 1); + i = ffurl_read_complete(rt->stream, serverdata, RTMP_HANDSHAKE_PACKET_SIZE + 1); if (i != RTMP_HANDSHAKE_PACKET_SIZE + 1) { av_log(LOG_CONTEXT, AV_LOG_ERROR, "Cannot read RTMP handshake response\n"); return -1; } - i = url_read_complete(rt->stream, clientdata, RTMP_HANDSHAKE_PACKET_SIZE); + i = ffurl_read_complete(rt->stream, clientdata, RTMP_HANDSHAKE_PACKET_SIZE); if (i != RTMP_HANDSHAKE_PACKET_SIZE) { av_log(LOG_CONTEXT, AV_LOG_ERROR, "Cannot read RTMP handshake response\n"); return -1; @@ -531,9 +532,9 @@ static int rtmp_handshake(URLContext *s, RTMPContext *rt) tosend + RTMP_HANDSHAKE_PACKET_SIZE - 32); // write reply back to the server - url_write(rt->stream, tosend, RTMP_HANDSHAKE_PACKET_SIZE); + ffurl_write(rt->stream, tosend, RTMP_HANDSHAKE_PACKET_SIZE); } else { - url_write(rt->stream, serverdata+1, RTMP_HANDSHAKE_PACKET_SIZE); + ffurl_write(rt->stream, serverdata+1, RTMP_HANDSHAKE_PACKET_SIZE); } return 0; @@ -785,7 +786,7 @@ static int rtmp_close(URLContext *h) gen_delete_stream(h, rt); av_freep(&rt->flv_data); - url_close(rt->stream); + ffurl_close(rt->stream); av_free(rt); return 0; } @@ -820,7 +821,7 @@ static int rtmp_open(URLContext *s, const char *uri, int flags) port = RTMP_DEFAULT_PORT; ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, NULL); - if (url_open(&rt->stream, buf, URL_RDWR) < 0) { + if (ffurl_open(&rt->stream, buf, URL_RDWR) < 0) { av_log(LOG_CONTEXT, AV_LOG_ERROR, "Cannot open connection %s\n", buf); goto fail; } @@ -887,7 +888,7 @@ static int rtmp_open(URLContext *s, const char *uri, int flags) rt->flv_off = 0; } - s->max_packet_size = url_get_max_packet_size(rt->stream); + s->max_packet_size = rt->stream->max_packet_size; s->is_streamed = 1; return 0; diff --git a/libavformat/rtpdec.c b/libavformat/rtpdec.c index ec266c6668..db728ad2cb 100644 --- a/libavformat/rtpdec.c +++ b/libavformat/rtpdec.c @@ -25,6 +25,7 @@ #include "libavcodec/get_bits.h" #include "avformat.h" #include "mpegts.h" +#include "url.h" #include #include @@ -325,8 +326,8 @@ int rtp_check_and_send_back_rr(RTPDemuxContext *s, int count) if ((len > 0) && buf) { int result; av_dlog(s->ic, "sending %d bytes of RR\n", len); - result= url_write(s->rtp_ctx, buf, len); - av_dlog(s->ic, "result from url_write: %d\n", result); + result= ffurl_write(s->rtp_ctx, buf, len); + av_dlog(s->ic, "result from ffurl_write: %d\n", result); av_free(buf); } return 0; @@ -351,7 +352,7 @@ void rtp_send_punch_packets(URLContext* rtp_handle) avio_flush(pb); len = avio_close_dyn_buf(pb, &buf); if ((len > 0) && buf) - url_write(rtp_handle, buf, len); + ffurl_write(rtp_handle, buf, len); av_free(buf); /* Send a minimal RTCP RR */ @@ -366,7 +367,7 @@ void rtp_send_punch_packets(URLContext* rtp_handle) avio_flush(pb); len = avio_close_dyn_buf(pb, &buf); if ((len > 0) && buf) - url_write(rtp_handle, buf, len); + ffurl_write(rtp_handle, buf, len); av_free(buf); } diff --git a/libavformat/rtpproto.c b/libavformat/rtpproto.c index 4b8d1db382..08f6c0a1e1 100644 --- a/libavformat/rtpproto.c +++ b/libavformat/rtpproto.c @@ -29,6 +29,7 @@ #include "avformat.h" #include "avio_internal.h" #include "rtpdec.h" +#include "url.h" #include #include @@ -189,7 +190,7 @@ static int rtp_open(URLContext *h, const char *uri, int flags) build_udp_url(buf, sizeof(buf), hostname, rtp_port, local_rtp_port, ttl, max_packet_size, connect); - if (url_open(&s->rtp_hd, buf, flags) < 0) + if (ffurl_open(&s->rtp_hd, buf, flags) < 0) goto fail; if (local_rtp_port>=0 && local_rtcp_port<0) local_rtcp_port = ff_udp_get_local_port(s->rtp_hd) + 1; @@ -197,23 +198,23 @@ static int rtp_open(URLContext *h, const char *uri, int flags) build_udp_url(buf, sizeof(buf), hostname, rtcp_port, local_rtcp_port, ttl, max_packet_size, connect); - if (url_open(&s->rtcp_hd, buf, flags) < 0) + if (ffurl_open(&s->rtcp_hd, buf, flags) < 0) goto fail; /* just to ease handle access. XXX: need to suppress direct handle access */ - s->rtp_fd = url_get_file_handle(s->rtp_hd); - s->rtcp_fd = url_get_file_handle(s->rtcp_hd); + s->rtp_fd = ffurl_get_file_handle(s->rtp_hd); + s->rtcp_fd = ffurl_get_file_handle(s->rtcp_hd); - h->max_packet_size = url_get_max_packet_size(s->rtp_hd); + h->max_packet_size = s->rtp_hd->max_packet_size; h->is_streamed = 1; return 0; fail: if (s->rtp_hd) - url_close(s->rtp_hd); + ffurl_close(s->rtp_hd); if (s->rtcp_hd) - url_close(s->rtcp_hd); + ffurl_close(s->rtcp_hd); av_free(s); return AVERROR(EIO); } @@ -296,7 +297,7 @@ static int rtp_write(URLContext *h, const uint8_t *buf, int size) hd = s->rtp_hd; } - ret = url_write(hd, buf, size); + ret = ffurl_write(hd, buf, size); #if 0 { struct timespec ts; @@ -312,8 +313,8 @@ static int rtp_close(URLContext *h) { RTPContext *s = h->priv_data; - url_close(s->rtp_hd); - url_close(s->rtcp_hd); + ffurl_close(s->rtp_hd); + ffurl_close(s->rtcp_hd); av_free(s); return 0; } diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c index 227c4ccd96..1eba0cbcfe 100644 --- a/libavformat/rtsp.c +++ b/libavformat/rtsp.c @@ -42,6 +42,7 @@ #include "rdt.h" #include "rtpdec_formats.h" #include "rtpenc_chain.h" +#include "url.h" //#define DEBUG //#define DEBUG_RTP_TCP @@ -508,7 +509,7 @@ void ff_rtsp_undo_setup(AVFormatContext *s) } rtsp_st->transport_priv = NULL; if (rtsp_st->rtp_handle) - url_close(rtsp_st->rtp_handle); + ffurl_close(rtsp_st->rtp_handle); rtsp_st->rtp_handle = NULL; } } @@ -817,7 +818,7 @@ void ff_rtsp_skip_packet(AVFormatContext *s) int ret, len, len1; uint8_t buf[1024]; - ret = url_read_complete(rt->rtsp_hd, buf, 3); + ret = ffurl_read_complete(rt->rtsp_hd, buf, 3); if (ret != 3) return; len = AV_RB16(buf + 1); @@ -829,7 +830,7 @@ void ff_rtsp_skip_packet(AVFormatContext *s) len1 = len; if (len1 > sizeof(buf)) len1 = sizeof(buf); - ret = url_read_complete(rt->rtsp_hd, buf, len1); + ret = ffurl_read_complete(rt->rtsp_hd, buf, len1); if (ret != len1) return; len -= len1; @@ -854,7 +855,7 @@ int ff_rtsp_read_reply(AVFormatContext *s, RTSPMessageHeader *reply, for (;;) { q = buf; for (;;) { - ret = url_read_complete(rt->rtsp_hd, &ch, 1); + ret = ffurl_read_complete(rt->rtsp_hd, &ch, 1); #ifdef DEBUG_RTP_TCP av_dlog(s, "ret=%d c=%02x [%c]\n", ret, ch, ch); #endif @@ -902,7 +903,7 @@ int ff_rtsp_read_reply(AVFormatContext *s, RTSPMessageHeader *reply, if (content_length > 0) { /* leave some room for a trailing '\0' (useful for simple parsing) */ content = av_malloc(content_length + 1); - (void)url_read_complete(rt->rtsp_hd, content, content_length); + ffurl_read_complete(rt->rtsp_hd, content, content_length); content[content_length] = '\0'; } if (content_ptr) @@ -982,14 +983,14 @@ static int ff_rtsp_send_cmd_with_content_async(AVFormatContext *s, av_dlog(s, "Sending:\n%s--\n", buf); - url_write(rt->rtsp_hd_out, out_buf, strlen(out_buf)); + ffurl_write(rt->rtsp_hd_out, out_buf, strlen(out_buf)); if (send_content_length > 0 && send_content) { if (rt->control_transport == RTSP_MODE_TUNNEL) { av_log(s, AV_LOG_ERROR, "tunneling of RTSP requests " "with content data not supported\n"); return AVERROR_PATCHWELCOME; } - url_write(rt->rtsp_hd_out, send_content, send_content_length); + ffurl_write(rt->rtsp_hd_out, send_content, send_content_length); } rt->last_cmd_time = av_gettime(); @@ -1115,14 +1116,14 @@ int ff_rtsp_make_setup_request(AVFormatContext *s, const char *host, int port, "?localport=%d", j); /* we will use two ports per rtp stream (rtp and rtcp) */ j += 2; - if (url_open(&rtsp_st->rtp_handle, buf, URL_RDWR) == 0) + if (ffurl_open(&rtsp_st->rtp_handle, buf, URL_RDWR) == 0) goto rtp_opened; } } #if 0 /* then try on any port */ - if (url_open(&rtsp_st->rtp_handle, "rtp://", URL_RDONLY) < 0) { + if (ffurl_open(&rtsp_st->rtp_handle, "rtp://", URL_RDONLY) < 0) { err = AVERROR_INVALIDDATA; goto fail; } @@ -1268,7 +1269,7 @@ int ff_rtsp_make_setup_request(AVFormatContext *s, const char *host, int port, namebuf, sizeof(namebuf), NULL, 0, NI_NUMERICHOST); ff_url_join(url, sizeof(url), "rtp", NULL, namebuf, port, "?ttl=%d", ttl); - if (url_open(&rtsp_st->rtp_handle, url, URL_RDWR) < 0) { + if (ffurl_open(&rtsp_st->rtp_handle, url, URL_RDWR) < 0) { err = AVERROR_INVALIDDATA; goto fail; } @@ -1296,8 +1297,8 @@ fail: void ff_rtsp_close_connections(AVFormatContext *s) { RTSPState *rt = s->priv_data; - if (rt->rtsp_hd_out != rt->rtsp_hd) url_close(rt->rtsp_hd_out); - url_close(rt->rtsp_hd); + if (rt->rtsp_hd_out != rt->rtsp_hd) ffurl_close(rt->rtsp_hd_out); + ffurl_close(rt->rtsp_hd); rt->rtsp_hd = rt->rtsp_hd_out = NULL; } @@ -1395,7 +1396,7 @@ redirect: av_get_random_seed(), av_get_random_seed()); /* GET requests */ - if (url_alloc(&rt->rtsp_hd, httpname, URL_RDONLY) < 0) { + if (ffurl_alloc(&rt->rtsp_hd, httpname, URL_RDONLY) < 0) { err = AVERROR(EIO); goto fail; } @@ -1410,13 +1411,13 @@ redirect: ff_http_set_headers(rt->rtsp_hd, headers); /* complete the connection */ - if (url_connect(rt->rtsp_hd)) { + if (ffurl_connect(rt->rtsp_hd)) { err = AVERROR(EIO); goto fail; } /* POST requests */ - if (url_alloc(&rt->rtsp_hd_out, httpname, URL_WRONLY) < 0 ) { + if (ffurl_alloc(&rt->rtsp_hd_out, httpname, URL_WRONLY) < 0 ) { err = AVERROR(EIO); goto fail; } @@ -1452,14 +1453,14 @@ redirect: ff_http_init_auth_state(rt->rtsp_hd_out, rt->rtsp_hd); /* complete the connection */ - if (url_connect(rt->rtsp_hd_out)) { + if (ffurl_connect(rt->rtsp_hd_out)) { err = AVERROR(EIO); goto fail; } } else { /* open the tcp connection */ ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, host, port, NULL); - if (url_open(&rt->rtsp_hd, tcpname, URL_RDWR) < 0) { + if (ffurl_open(&rt->rtsp_hd, tcpname, URL_RDWR) < 0) { err = AVERROR(EIO); goto fail; } @@ -1467,7 +1468,7 @@ redirect: } rt->seq = 0; - tcp_fd = url_get_file_handle(rt->rtsp_hd); + tcp_fd = ffurl_get_file_handle(rt->rtsp_hd); if (!getpeername(tcp_fd, (struct sockaddr*) &peer, &peer_len)) { getnameinfo((struct sockaddr*) &peer, peer_len, host, sizeof(host), NULL, 0, NI_NUMERICHOST); @@ -1570,7 +1571,7 @@ static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st, return AVERROR(EAGAIN); max_p = 0; if (rt->rtsp_hd) { - tcp_fd = url_get_file_handle(rt->rtsp_hd); + tcp_fd = ffurl_get_file_handle(rt->rtsp_hd); p[max_p].fd = tcp_fd; p[max_p++].events = POLLIN; } else { @@ -1579,7 +1580,7 @@ static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st, for (i = 0; i < rt->nb_rtsp_streams; i++) { rtsp_st = rt->rtsp_streams[i]; if (rtsp_st->rtp_handle) { - p[max_p].fd = url_get_file_handle(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 = rtp_get_rtcp_file_handle(rtsp_st->rtp_handle); p[max_p++].events = POLLIN; @@ -1593,7 +1594,7 @@ static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st, rtsp_st = rt->rtsp_streams[i]; if (rtsp_st->rtp_handle) { if (p[j].revents & POLLIN || p[j+1].revents & POLLIN) { - ret = url_read(rtsp_st->rtp_handle, buf, buf_size); + ret = ffurl_read(rtsp_st->rtp_handle, buf, buf_size); if (ret > 0) { *prtsp_st = rtsp_st; return ret; @@ -1806,7 +1807,7 @@ static int sdp_read_header(AVFormatContext *s, AVFormatParameters *ap) namebuf, rtsp_st->sdp_port, "?localport=%d&ttl=%d", rtsp_st->sdp_port, rtsp_st->sdp_ttl); - if (url_open(&rtsp_st->rtp_handle, url, URL_RDWR) < 0) { + if (ffurl_open(&rtsp_st->rtp_handle, url, URL_RDWR) < 0) { err = AVERROR_INVALIDDATA; goto fail; } @@ -1862,12 +1863,12 @@ static int rtp_read_header(AVFormatContext *s, if (!ff_network_init()) return AVERROR(EIO); - ret = url_open(&in, s->filename, URL_RDONLY); + ret = ffurl_open(&in, s->filename, URL_RDONLY); if (ret) goto fail; while (1) { - ret = url_read(in, recvbuf, sizeof(recvbuf)); + ret = ffurl_read(in, recvbuf, sizeof(recvbuf)); if (ret == AVERROR(EAGAIN)) continue; if (ret < 0) @@ -1886,8 +1887,8 @@ static int rtp_read_header(AVFormatContext *s, payload_type = recvbuf[1] & 0x7f; break; } - getsockname(url_get_file_handle(in), (struct sockaddr*) &addr, &addrlen); - url_close(in); + getsockname(ffurl_get_file_handle(in), (struct sockaddr*) &addr, &addrlen); + ffurl_close(in); in = NULL; memset(&codec, 0, sizeof(codec)); @@ -1926,7 +1927,7 @@ static int rtp_read_header(AVFormatContext *s, fail: if (in) - url_close(in); + ffurl_close(in); ff_network_close(); return ret; } diff --git a/libavformat/rtspdec.c b/libavformat/rtspdec.c index 4150008179..5833a5209a 100644 --- a/libavformat/rtspdec.c +++ b/libavformat/rtspdec.c @@ -28,6 +28,7 @@ #include "os_support.h" #include "rtsp.h" #include "rdt.h" +#include "url.h" //#define DEBUG //#define DEBUG_RTP_TCP @@ -200,7 +201,7 @@ redo: if (rt->state != RTSP_STATE_STREAMING) return 0; } - ret = url_read_complete(rt->rtsp_hd, buf, 3); + ret = ffurl_read_complete(rt->rtsp_hd, buf, 3); if (ret != 3) return -1; id = buf[0]; @@ -211,7 +212,7 @@ redo: if (len > buf_size || len < 12) goto redo; /* get the data */ - ret = url_read_complete(rt->rtsp_hd, buf, len); + ret = ffurl_read_complete(rt->rtsp_hd, buf, len); if (ret != len) return -1; if (rt->transport == RTSP_TRANSPORT_RDT && diff --git a/libavformat/rtspenc.c b/libavformat/rtspenc.c index 7f788f6f9a..865697fb95 100644 --- a/libavformat/rtspenc.c +++ b/libavformat/rtspenc.c @@ -32,6 +32,7 @@ #include "avio_internal.h" #include "libavutil/intreadwrite.h" #include "libavutil/avstring.h" +#include "url.h" #define SDP_MAX_SIZE 16384 @@ -158,7 +159,7 @@ static int tcp_write_packet(AVFormatContext *s, RTSPStream *rtsp_st) interleave_header[0] = '$'; interleave_header[1] = id; AV_WB16(interleave_header + 2, packet_len); - url_write(rt->rtsp_hd_out, interleaved_packet, 4 + packet_len); + ffurl_write(rt->rtsp_hd_out, interleaved_packet, 4 + packet_len); ptr += packet_len; size -= packet_len; } @@ -172,7 +173,7 @@ static int rtsp_write_packet(AVFormatContext *s, AVPacket *pkt) RTSPState *rt = s->priv_data; RTSPStream *rtsp_st; int n; - struct pollfd p = {url_get_file_handle(rt->rtsp_hd), POLLIN, 0}; + struct pollfd p = {ffurl_get_file_handle(rt->rtsp_hd), POLLIN, 0}; AVFormatContext *rtpctx; int ret; diff --git a/libavformat/sapdec.c b/libavformat/sapdec.c index e3cdcea6a6..42507d34f1 100644 --- a/libavformat/sapdec.c +++ b/libavformat/sapdec.c @@ -26,6 +26,7 @@ #include "os_support.h" #include "internal.h" #include "avio_internal.h" +#include "url.h" #if HAVE_POLL_H #include #endif @@ -53,7 +54,7 @@ static int sap_read_close(AVFormatContext *s) if (sap->sdp_ctx) av_close_input_stream(sap->sdp_ctx); if (sap->ann_fd) - url_close(sap->ann_fd); + ffurl_close(sap->ann_fd); av_freep(&sap->sdp); ff_network_close(); return 0; @@ -84,7 +85,7 @@ static int sap_read_header(AVFormatContext *s, ff_url_join(url, sizeof(url), "udp", NULL, host, port, "?localport=%d", port); - ret = url_open(&sap->ann_fd, url, URL_RDONLY); + ret = ffurl_open(&sap->ann_fd, url, URL_RDONLY); if (ret) goto fail; @@ -92,7 +93,7 @@ static int sap_read_header(AVFormatContext *s, int addr_type, auth_len; int pos; - ret = url_read(sap->ann_fd, recvbuf, sizeof(recvbuf) - 1); + ret = ffurl_read(sap->ann_fd, recvbuf, sizeof(recvbuf) - 1); if (ret == AVERROR(EAGAIN)) continue; if (ret < 0) @@ -182,7 +183,7 @@ fail: static int sap_fetch_packet(AVFormatContext *s, AVPacket *pkt) { struct SAPState *sap = s->priv_data; - int fd = url_get_file_handle(sap->ann_fd); + int fd = ffurl_get_file_handle(sap->ann_fd); int n, ret; struct pollfd p = {fd, POLLIN, 0}; uint8_t recvbuf[1500]; @@ -194,7 +195,7 @@ static int sap_fetch_packet(AVFormatContext *s, AVPacket *pkt) n = poll(&p, 1, 0); if (n <= 0 || !(p.revents & POLLIN)) break; - ret = url_read(sap->ann_fd, recvbuf, sizeof(recvbuf)); + ret = ffurl_read(sap->ann_fd, recvbuf, sizeof(recvbuf)); if (ret >= 8) { uint16_t hash = AV_RB16(&recvbuf[2]); /* Should ideally check the source IP address, too */ diff --git a/libavformat/sapenc.c b/libavformat/sapenc.c index bc66adcd77..0569d790ce 100644 --- a/libavformat/sapenc.c +++ b/libavformat/sapenc.c @@ -28,6 +28,7 @@ #include "network.h" #include "os_support.h" #include "rtpenc_chain.h" +#include "url.h" struct SAPState { uint8_t *ann; @@ -53,12 +54,12 @@ static int sap_write_close(AVFormatContext *s) if (sap->last_time && sap->ann && sap->ann_fd) { sap->ann[0] |= 4; /* Session deletion*/ - url_write(sap->ann_fd, sap->ann, sap->ann_size); + ffurl_write(sap->ann_fd, sap->ann, sap->ann_size); } av_freep(&sap->ann); if (sap->ann_fd) - url_close(sap->ann_fd); + ffurl_close(sap->ann_fd); ff_network_close(); return 0; } @@ -145,7 +146,7 @@ static int sap_write_header(AVFormatContext *s) "?ttl=%d", ttl); if (!same_port) base_port += 2; - ret = url_open(&fd, url, URL_WRONLY); + ret = ffurl_open(&fd, url, URL_WRONLY); if (ret) { ret = AVERROR(EIO); goto fail; @@ -157,13 +158,13 @@ static int sap_write_header(AVFormatContext *s) ff_url_join(url, sizeof(url), "udp", NULL, announce_addr, port, "?ttl=%d&connect=1", ttl); - ret = url_open(&sap->ann_fd, url, URL_WRONLY); + ret = ffurl_open(&sap->ann_fd, url, URL_WRONLY); if (ret) { ret = AVERROR(EIO); goto fail; } - udp_fd = url_get_file_handle(sap->ann_fd); + udp_fd = ffurl_get_file_handle(sap->ann_fd); if (getsockname(udp_fd, (struct sockaddr*) &localaddr, &addrlen)) { ret = AVERROR(EIO); goto fail; @@ -217,7 +218,7 @@ static int sap_write_header(AVFormatContext *s) pos += strlen(&sap->ann[pos]); sap->ann_size = pos; - if (sap->ann_size > url_get_max_packet_size(sap->ann_fd)) { + if (sap->ann_size > sap->ann_fd->max_packet_size) { av_log(s, AV_LOG_ERROR, "Announcement too large to send in one " "packet\n"); goto fail; @@ -238,7 +239,7 @@ static int sap_write_packet(AVFormatContext *s, AVPacket *pkt) int64_t now = av_gettime(); if (!sap->last_time || now - sap->last_time > 5000000) { - int ret = url_write(sap->ann_fd, sap->ann, sap->ann_size); + int ret = ffurl_write(sap->ann_fd, sap->ann, sap->ann_size); /* Don't abort even if we get "Destination unreachable" */ if (ret < 0 && ret != AVERROR(ECONNREFUSED)) return ret; diff --git a/libavformat/url.h b/libavformat/url.h new file mode 100644 index 0000000000..2110129cb1 --- /dev/null +++ b/libavformat/url.h @@ -0,0 +1,129 @@ +/* + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * unbuffered private I/O API + */ + +#ifndef AVFORMAT_URL_H +#define AVFORMAT_URL_H + +#include "avio.h" + +/** + * Create a URLContext for accessing to the resource indicated by + * url, but do not initiate the connection yet. + * + * @param puc pointer to the location where, in case of success, the + * function puts the pointer to the created URLContext + * @param flags flags which control how the resource indicated by url + * is to be opened + * @return 0 in case of success, a negative value corresponding to an + * AVERROR code in case of failure + */ +int ffurl_alloc(URLContext **h, const char *url, int flags); + +/** + * Connect an URLContext that has been allocated by ffurl_alloc + */ +int ffurl_connect(URLContext *h); + +/** + * Create an URLContext for accessing to the resource indicated by + * url, and open it. + * + * @param puc pointer to the location where, in case of success, the + * function puts the pointer to the created URLContext + * @param flags flags which control how the resource indicated by url + * is to be opened + * @return 0 in case of success, a negative value corresponding to an + * AVERROR code in case of failure + */ +int ffurl_open(URLContext **h, const char *url, int flags); + +/** + * Read up to size bytes from the resource accessed by h, and store + * the read bytes in buf. + * + * @return The number of bytes actually read, or a negative value + * corresponding to an AVERROR code in case of error. A value of zero + * indicates that it is not possible to read more from the accessed + * resource (except if the value of the size argument is also zero). + */ +int ffurl_read(URLContext *h, unsigned char *buf, int size); + +/** + * Read as many bytes as possible (up to size), calling the + * read function multiple times if necessary. + * This makes special short-read handling in applications + * unnecessary, if the return value is < size then it is + * certain there was either an error or the end of file was reached. + */ +int ffurl_read_complete(URLContext *h, unsigned char *buf, int size); + +/** + * Write size bytes from buf to the resource accessed by h. + * + * @return the number of bytes actually written, or a negative value + * corresponding to an AVERROR code in case of failure + */ +int ffurl_write(URLContext *h, const unsigned char *buf, int size); + +/** + * Change the position that will be used by the next read/write + * operation on the resource accessed by h. + * + * @param pos specifies the new position to set + * @param whence specifies how pos should be interpreted, it must be + * one of SEEK_SET (seek from the beginning), SEEK_CUR (seek from the + * current position), SEEK_END (seek from the end), or AVSEEK_SIZE + * (return the filesize of the requested resource, pos is ignored). + * @return a negative value corresponding to an AVERROR code in case + * of failure, or the resulting file position, measured in bytes from + * the beginning of the file. You can use this feature together with + * SEEK_CUR to read the current file position. + */ +int64_t ffurl_seek(URLContext *h, int64_t pos, int whence); + +/** + * Close the resource accessed by the URLContext h, and free the + * memory used by it. + * + * @return a negative value if an error condition occurred, 0 + * otherwise + */ +int ffurl_close(URLContext *h); + +/** + * Return the filesize of the resource accessed by h, AVERROR(ENOSYS) + * if the operation is not supported by h, or another negative value + * corresponding to an AVERROR error code in case of failure. + */ +int64_t ffurl_size(URLContext *h); + +/** + * Return the file descriptor associated with this URL. For RTP, this + * will return only the RTP file descriptor, not the RTCP file descriptor. + * + * @return the file descriptor associated with this URL, or <0 on error. + */ +int ffurl_get_file_handle(URLContext *h); + +#endif //AVFORMAT_URL_H diff --git a/tests/ref/acodec/ac3_fixed b/tests/ref/acodec/ac3_fixed index ce1a8ec29e..a3032d0380 100644 --- a/tests/ref/acodec/ac3_fixed +++ b/tests/ref/acodec/ac3_fixed @@ -1,2 +1,2 @@ -408f47ee5a60866fc751f7bc2314cbd6 *./tests/data/acodec/ac3.rm +5ddb6d25dd117db29627f9d286153a7a *./tests/data/acodec/ac3.rm 98751 ./tests/data/acodec/ac3.rm diff --git a/tests/ref/lavf/rm b/tests/ref/lavf/rm index fbf3e0fbde..a85c7630b4 100644 --- a/tests/ref/lavf/rm +++ b/tests/ref/lavf/rm @@ -1,2 +1,2 @@ -da74fe749c2eb21bbead7de81d2f3078 *./tests/data/lavf/lavf.rm +a1c71456f21d5459d2824d75bbdcc80c *./tests/data/lavf/lavf.rm 346706 ./tests/data/lavf/lavf.rm diff --git a/tests/ref/seek/ac3_rm b/tests/ref/seek/ac3_rm index 7b7d5b0bf7..4705447293 100644 --- a/tests/ref/seek/ac3_rm +++ b/tests/ref/seek/ac3_rm @@ -5,7 +5,8 @@ ret:-1 st:-1 flags:1 ts: 1.894167 ret:-1 st: 0 flags:0 ts: 0.788000 ret: 0 st: 0 flags:1 ts:-0.317000 ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 271 size: 556 -ret:-1 st:-1 flags:0 ts: 2.576668 +ret: 0 st:-1 flags:0 ts: 2.576668 +ret: 0 st: 0 flags:1 dts: 2.577000 pts: 2.577000 pos: 42397 size: 558 ret:-1 st:-1 flags:1 ts: 1.470835 ret:-1 st: 0 flags:0 ts: 0.365000 ret: 0 st: 0 flags:1 ts:-0.741000 @@ -19,7 +20,8 @@ ret:-1 st:-1 flags:0 ts: 1.730004 ret:-1 st:-1 flags:1 ts: 0.624171 ret: 0 st: 0 flags:0 ts:-0.482000 ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 271 size: 556 -ret:-1 st: 0 flags:1 ts: 2.413000 +ret: 0 st: 0 flags:1 ts: 2.413000 +ret: 0 st: 0 flags:1 dts: 2.368000 pts: 2.368000 pos: 38981 size: 558 ret:-1 st:-1 flags:0 ts: 1.306672 ret:-1 st:-1 flags:1 ts: 0.200839 ret: 0 st: 0 flags:0 ts:-0.905000 @@ -28,7 +30,8 @@ ret:-1 st: 0 flags:1 ts: 1.989000 ret:-1 st:-1 flags:0 ts: 0.883340 ret: 0 st:-1 flags:1 ts:-0.222493 ret: 0 st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos: 271 size: 556 -ret:-1 st: 0 flags:0 ts: 2.672000 +ret: 0 st: 0 flags:0 ts: 2.672000 +ret: 0 st: 0 flags:1 dts: 2.821000 pts: 2.821000 pos: 46383 size: 556 ret:-1 st: 0 flags:1 ts: 1.566000 ret:-1 st:-1 flags:0 ts: 0.460008 ret: 0 st:-1 flags:1 ts:-0.645825