* qatar/master: (22 commits) configure: add check for w32threads to enable it automatically rtmp: do not hardcode invoke numbers cinepack: return non-generic errors fate-lavf-ts: use -mpegts_transport_stream_id option. Add an APIchanges entry and a minor bump for avio changes. avio: Mark the old interrupt callback mechanism as deprecated avplay: Set the new interrupt callback avconv: Set new interrupt callbacks for all AVFormatContexts, use avio_open2() everywhere cinepak: remove redundant coordinate checks cinepak: check strip_size cinepak, simplify, use AV_RB24() cinepak: simplify, use FFMIN() cinepak: Fix division by zero, ask for sample if encoded_buf_size is 0 applehttp: Fix seeking in streams not starting at DTS=0 http: Don't use the normal http proxy mechanism for https tls: Handle connection via a http proxy http: Reorder two code blocks http: Add a new protocol for opening connections via http proxies http: Split out the non-chunked buffer reading part from http_read segafilm: add support for raw videos ... Conflicts: avconv.c configure doc/APIchanges libavcodec/cinepak.c libavformat/applehttp.c libavformat/version.h tests/lavf-regression.sh tests/ref/lavf/ts Merged-by: Michael Niedermayer <michaelni@gmx.at>tags/n0.9
| @@ -588,12 +588,14 @@ static int read_key(void) | |||
| return -1; | |||
| } | |||
| static int decode_interrupt_cb(void) | |||
| static int decode_interrupt_cb(void *ctx) | |||
| { | |||
| q_pressed += read_key() == 'q'; | |||
| return q_pressed > 1; | |||
| } | |||
| static const AVIOInterruptCB int_cb = { decode_interrupt_cb, NULL }; | |||
| void exit_program(int ret) | |||
| { | |||
| int i; | |||
| @@ -2336,6 +2338,7 @@ static int transcode_init(OutputFile *output_files, | |||
| /* open files and write file headers */ | |||
| for (i = 0; i < nb_output_files; i++) { | |||
| os = output_files[i].ctx; | |||
| os->interrupt_callback = int_cb; | |||
| if (avformat_write_header(os, &output_files[i].opts) < 0) { | |||
| snprintf(error, sizeof(error), "Could not write header for output file #%d (incorrect codec parameters ?)", i); | |||
| ret = AVERROR(EINVAL); | |||
| @@ -3010,7 +3013,7 @@ static void dump_attachment(AVStream *st, const char *filename) | |||
| assert_file_overwrite(filename); | |||
| if ((ret = avio_open (&out, filename, AVIO_FLAG_WRITE)) < 0) { | |||
| if ((ret = avio_open2(&out, filename, AVIO_FLAG_WRITE, &int_cb, NULL)) < 0) { | |||
| av_log(NULL, AV_LOG_FATAL, "Could not open file %s for writing.\n", | |||
| filename); | |||
| exit_program(1); | |||
| @@ -3068,6 +3071,7 @@ static int opt_input_file(OptionsContext *o, const char *opt, const char *filena | |||
| av_dict_set(&format_opts, "pixel_format", o->frame_pix_fmts[o->nb_frame_pix_fmts - 1].u.str, 0); | |||
| ic->flags |= AVFMT_FLAG_NONBLOCK; | |||
| ic->interrupt_callback = int_cb; | |||
| /* open the input file with generic libav function */ | |||
| err = avformat_open_input(&ic, filename, file_iformat, &format_opts); | |||
| @@ -3197,12 +3201,12 @@ static int get_preset_file_2(const char *preset_name, const char *codec_name, AV | |||
| if (codec_name) { | |||
| snprintf(filename, sizeof(filename), "%s%s/%s-%s.avpreset", base[i], | |||
| i != 1 ? "" : "/.avconv", codec_name, preset_name); | |||
| ret = avio_open(s, filename, AVIO_FLAG_READ); | |||
| ret = avio_open2(s, filename, AVIO_FLAG_READ, &int_cb, NULL); | |||
| } | |||
| if (ret) { | |||
| snprintf(filename, sizeof(filename), "%s%s/%s.avpreset", base[i], | |||
| i != 1 ? "" : "/.avconv", preset_name); | |||
| ret = avio_open(s, filename, AVIO_FLAG_READ); | |||
| ret = avio_open2(s, filename, AVIO_FLAG_READ, &int_cb, NULL); | |||
| } | |||
| } | |||
| return ret; | |||
| @@ -3588,8 +3592,9 @@ static int copy_chapters(InputFile *ifile, OutputFile *ofile, int copy_metadata) | |||
| static int read_ffserver_streams(OptionsContext *o, AVFormatContext *s, const char *filename) | |||
| { | |||
| int i, err; | |||
| AVFormatContext *ic = NULL; | |||
| AVFormatContext *ic = avformat_alloc_context(); | |||
| ic->interrupt_callback = int_cb; | |||
| err = avformat_open_input(&ic, filename, NULL, NULL); | |||
| if (err < 0) | |||
| return err; | |||
| @@ -3638,6 +3643,7 @@ static void opt_output_file(void *optctx, const char *filename) | |||
| } | |||
| file_oformat= oc->oformat; | |||
| oc->interrupt_callback = int_cb; | |||
| if (!strcmp(file_oformat->name, "ffm") && | |||
| av_strstart(filename, "http:", NULL)) { | |||
| @@ -3729,7 +3735,7 @@ static void opt_output_file(void *optctx, const char *filename) | |||
| const char *p; | |||
| int64_t len; | |||
| if ((err = avio_open(&pb, o->attachments[i], AVIO_FLAG_READ)) < 0) { | |||
| if ((err = avio_open2(&pb, o->attachments[i], AVIO_FLAG_READ, &int_cb, NULL)) < 0) { | |||
| av_log(NULL, AV_LOG_FATAL, "Could not open attachment file %s.\n", | |||
| o->attachments[i]); | |||
| exit_program(1); | |||
| @@ -3779,7 +3785,9 @@ static void opt_output_file(void *optctx, const char *filename) | |||
| assert_file_overwrite(filename); | |||
| /* open the file */ | |||
| if ((err = avio_open(&oc->pb, filename, AVIO_FLAG_WRITE)) < 0) { | |||
| if ((err = avio_open2(&oc->pb, filename, AVIO_FLAG_WRITE, | |||
| &oc->interrupt_callback, | |||
| &output_files[nb_output_files - 1].opts)) < 0) { | |||
| print_error(filename, err); | |||
| exit_program(1); | |||
| } | |||
| @@ -4350,12 +4358,6 @@ int main(int argc, char **argv) | |||
| av_register_all(); | |||
| avformat_network_init(); | |||
| #if HAVE_ISATTY | |||
| if(isatty(STDIN_FILENO)) | |||
| avio_set_interrupt_cb(decode_interrupt_cb); | |||
| #endif | |||
| show_banner(); | |||
| /* parse options */ | |||
| parse_options(&o, argc, argv, options, opt_output_file); | |||
| @@ -2583,7 +2583,6 @@ case $target_os in | |||
| disable network | |||
| else | |||
| target_os=mingw32 | |||
| enable_weak w32threads | |||
| fi | |||
| LIBTARGET=i386 | |||
| if enabled x86_64; then | |||
| @@ -2999,6 +2998,10 @@ if ! disabled vda; then | |||
| fi | |||
| fi | |||
| if ! disabled w32threads && ! enabled pthreads; then | |||
| check_func _beginthreadex && enable w32threads | |||
| fi | |||
| # check for some common methods of building with pthread support | |||
| # do this before the optional library checks as some of them require pthreads | |||
| if ! disabled pthreads && ! enabled w32threads && ! enabled os2threads; then | |||
| @@ -19,6 +19,16 @@ API changes, most recent first: | |||
| 2011-10-20 - b35e9e1 - lavu 51.22.0 | |||
| Add av_strtok() to avstring.h. | |||
| 2011-11-13 - lavf 53.15.0 | |||
| New interrupt callback API, allowing per-AVFormatContext/AVIOContext | |||
| interrupt callbacks. | |||
| 6aa0b98 Add AVIOInterruptCB struct and the interrupt_callback field to | |||
| AVFormatContext. | |||
| 1dee0ac Add avio_open2() with additional parameters. Those are | |||
| an interrupt callback and an options AVDictionary. | |||
| This will allow passing AVOptions to protocols after lavf | |||
| 54.0. | |||
| 2011-11-xx - xxxxxxx - lavu 51.16.0 | |||
| Add av_timegm() | |||
| @@ -635,11 +635,13 @@ static int read_key(void) | |||
| return -1; | |||
| } | |||
| static int decode_interrupt_cb(void) | |||
| static int decode_interrupt_cb(void *ctx) | |||
| { | |||
| return received_nb_signals > 1; | |||
| } | |||
| static const AVIOInterruptCB int_cb = { decode_interrupt_cb, NULL }; | |||
| void av_noreturn exit_program(int ret) | |||
| { | |||
| int i; | |||
| @@ -2403,6 +2405,7 @@ static int transcode_init(OutputFile *output_files, int nb_output_files, | |||
| /* open files and write file headers */ | |||
| for (i = 0; i < nb_output_files; i++) { | |||
| os = output_files[i].ctx; | |||
| os->interrupt_callback = int_cb; | |||
| if (avformat_write_header(os, &output_files[i].opts) < 0) { | |||
| snprintf(error, sizeof(error), "Could not write header for output file #%d (incorrect codec parameters ?)", i); | |||
| ret = AVERROR(EINVAL); | |||
| @@ -2495,7 +2498,6 @@ static int transcode(OutputFile *output_files, int nb_output_files, | |||
| if (!using_stdin) { | |||
| av_log(NULL, AV_LOG_INFO, "Press [q] to stop, [?] for help\n"); | |||
| avio_set_interrupt_cb(decode_interrupt_cb); | |||
| } | |||
| timer_start = av_gettime(); | |||
| @@ -3243,7 +3245,7 @@ static void dump_attachment(AVStream *st, const char *filename) | |||
| assert_file_overwrite(filename); | |||
| if ((ret = avio_open (&out, filename, AVIO_FLAG_WRITE)) < 0) { | |||
| if ((ret = avio_open2(&out, filename, AVIO_FLAG_WRITE, &int_cb, NULL)) < 0) { | |||
| av_log(NULL, AV_LOG_FATAL, "Could not open file %s for writing.\n", | |||
| filename); | |||
| exit_program(1); | |||
| @@ -3307,6 +3309,7 @@ static int opt_input_file(OptionsContext *o, const char *opt, const char *filena | |||
| ic->subtitle_codec_id= subtitle_codec_name ? | |||
| find_codec_or_die(subtitle_codec_name, AVMEDIA_TYPE_SUBTITLE, 0)->id : CODEC_ID_NONE; | |||
| ic->flags |= AVFMT_FLAG_NONBLOCK; | |||
| ic->interrupt_callback = int_cb; | |||
| if (loop_input) { | |||
| av_log(NULL, AV_LOG_WARNING, "-loop_input is deprecated, use -loop 1\n"); | |||
| @@ -3438,12 +3441,12 @@ static int get_preset_file_2(const char *preset_name, const char *codec_name, AV | |||
| if (codec_name) { | |||
| snprintf(filename, sizeof(filename), "%s%s/%s-%s.avpreset", base[i], | |||
| i != 1 ? "" : "/.avconv", codec_name, preset_name); | |||
| ret = avio_open(s, filename, AVIO_FLAG_READ); | |||
| ret = avio_open2(s, filename, AVIO_FLAG_READ, &int_cb, NULL); | |||
| } | |||
| if (ret) { | |||
| snprintf(filename, sizeof(filename), "%s%s/%s.avpreset", base[i], | |||
| i != 1 ? "" : "/.avconv", preset_name); | |||
| ret = avio_open(s, filename, AVIO_FLAG_READ); | |||
| ret = avio_open2(s, filename, AVIO_FLAG_READ, &int_cb, NULL); | |||
| } | |||
| } | |||
| return ret; | |||
| @@ -3856,8 +3859,9 @@ static int copy_chapters(InputFile *ifile, OutputFile *ofile, int copy_metadata) | |||
| static int read_ffserver_streams(OptionsContext *o, AVFormatContext *s, const char *filename) | |||
| { | |||
| int i, err; | |||
| AVFormatContext *ic = NULL; | |||
| AVFormatContext *ic = avformat_alloc_context(); | |||
| ic->interrupt_callback = int_cb; | |||
| err = avformat_open_input(&ic, filename, NULL, NULL); | |||
| if (err < 0) | |||
| return err; | |||
| @@ -3908,6 +3912,7 @@ static void opt_output_file(void *optctx, const char *filename) | |||
| exit_program(1); | |||
| } | |||
| file_oformat= oc->oformat; | |||
| oc->interrupt_callback = int_cb; | |||
| if (!strcmp(file_oformat->name, "ffm") && | |||
| av_strstart(filename, "http:", NULL)) { | |||
| @@ -4019,7 +4024,7 @@ static void opt_output_file(void *optctx, const char *filename) | |||
| const char *p; | |||
| int64_t len; | |||
| if ((err = avio_open(&pb, o->attachments[i], AVIO_FLAG_READ)) < 0) { | |||
| if ((err = avio_open2(&pb, o->attachments[i], AVIO_FLAG_READ, &int_cb, NULL)) < 0) { | |||
| av_log(NULL, AV_LOG_FATAL, "Could not open attachment file %s.\n", | |||
| o->attachments[i]); | |||
| exit_program(1); | |||
| @@ -4069,7 +4074,9 @@ static void opt_output_file(void *optctx, const char *filename) | |||
| assert_file_overwrite(filename); | |||
| /* open the file */ | |||
| if ((err = avio_open(&oc->pb, filename, AVIO_FLAG_WRITE)) < 0) { | |||
| if ((err = avio_open2(&oc->pb, filename, AVIO_FLAG_WRITE, | |||
| &oc->interrupt_callback, | |||
| &output_files[nb_output_files - 1].opts)) < 0) { | |||
| print_error(filename, err); | |||
| exit_program(1); | |||
| } | |||
| @@ -4725,12 +4732,6 @@ int main(int argc, char **argv) | |||
| av_register_all(); | |||
| avformat_network_init(); | |||
| #if HAVE_ISATTY | |||
| if(isatty(STDIN_FILENO)) | |||
| avio_set_interrupt_cb(decode_interrupt_cb); | |||
| #endif | |||
| show_banner(); | |||
| term_init(); | |||
| @@ -2414,7 +2414,7 @@ static void stream_component_close(VideoState *is, int stream_index) | |||
| variable instead of a thread local variable */ | |||
| static VideoState *global_video_state; | |||
| static int decode_interrupt_cb(void) | |||
| static int decode_interrupt_cb(void *ctx) | |||
| { | |||
| return (global_video_state && global_video_state->abort_request); | |||
| } | |||
| @@ -2439,8 +2439,9 @@ static int read_thread(void *arg) | |||
| is->subtitle_stream = -1; | |||
| global_video_state = is; | |||
| avio_set_interrupt_cb(decode_interrupt_cb); | |||
| ic = avformat_alloc_context(); | |||
| ic->interrupt_callback.callback = decode_interrupt_cb; | |||
| err = avformat_open_input(&ic, is->filename, is->iformat, &format_opts); | |||
| if (err < 0) { | |||
| print_error(is->filename, err); | |||
| @@ -147,7 +147,7 @@ static int cinepak_decode_vectors (CinepakContext *s, cvid_strip *strip, | |||
| for (x=strip->x1; x < strip->x2; x+=4) { | |||
| if ((chunk_id & 0x01) && !(mask >>= 1)) { | |||
| if ((data + 4) > eod) | |||
| return -1; | |||
| return AVERROR_INVALIDDATA; | |||
| flag = AV_RB32 (data); | |||
| data += 4; | |||
| @@ -157,7 +157,7 @@ static int cinepak_decode_vectors (CinepakContext *s, cvid_strip *strip, | |||
| if (!(chunk_id & 0x01) || (flag & mask)) { | |||
| if (!(chunk_id & 0x02) && !(mask >>= 1)) { | |||
| if ((data + 4) > eod) | |||
| return -1; | |||
| return AVERROR_INVALIDDATA; | |||
| flag = AV_RB32 (data); | |||
| data += 4; | |||
| @@ -166,7 +166,7 @@ static int cinepak_decode_vectors (CinepakContext *s, cvid_strip *strip, | |||
| if ((chunk_id & 0x02) || (~flag & mask)) { | |||
| if (data >= eod) | |||
| return -1; | |||
| return AVERROR_INVALIDDATA; | |||
| codebook = &strip->v1_codebook[*data++]; | |||
| s->frame.data[0][iy[0] + 0] = codebook->y0; | |||
| @@ -207,7 +207,7 @@ static int cinepak_decode_vectors (CinepakContext *s, cvid_strip *strip, | |||
| } else if (flag & mask) { | |||
| if ((data + 4) > eod) | |||
| return -1; | |||
| return AVERROR_INVALIDDATA; | |||
| codebook = &strip->v4_codebook[*data++]; | |||
| s->frame.data[0][iy[0] + 0] = codebook->y0; | |||
| @@ -269,16 +269,16 @@ static int cinepak_decode_strip (CinepakContext *s, | |||
| int chunk_id, chunk_size; | |||
| /* coordinate sanity checks */ | |||
| if (strip->x2 > s->width || | |||
| strip->y2 > s->height || | |||
| if (strip->x2 > s->width || | |||
| strip->y2 > s->height || | |||
| strip->x1 >= strip->x2 || strip->y1 >= strip->y2) | |||
| return -1; | |||
| return AVERROR_INVALIDDATA; | |||
| while ((data + 4) <= eod) { | |||
| chunk_id = data[0]; | |||
| chunk_size = AV_RB24 (&data[1]) - 4; | |||
| if(chunk_size < 0) | |||
| return -1; | |||
| return AVERROR_INVALIDDATA; | |||
| data += 4; | |||
| chunk_size = ((data + chunk_size) > eod) ? (eod - data) : chunk_size; | |||
| @@ -311,7 +311,7 @@ static int cinepak_decode_strip (CinepakContext *s, | |||
| data += chunk_size; | |||
| } | |||
| return -1; | |||
| return AVERROR_INVALIDDATA; | |||
| } | |||
| static int cinepak_decode (CinepakContext *s) | |||
| @@ -322,7 +322,7 @@ static int cinepak_decode (CinepakContext *s) | |||
| int encoded_buf_size; | |||
| if (s->size < 10) | |||
| return -1; | |||
| return AVERROR_INVALIDDATA; | |||
| frame_flags = s->data[0]; | |||
| num_strips = AV_RB16 (&s->data[8]); | |||
| @@ -330,9 +330,9 @@ static int cinepak_decode (CinepakContext *s) | |||
| /* if this is the first frame, check for deviant Sega FILM data */ | |||
| if (s->sega_film_skip_bytes == -1) { | |||
| if (!encoded_buf_size){ | |||
| if (!encoded_buf_size) { | |||
| av_log_ask_for_sample(s->avctx, "encoded_buf_size is 0"); | |||
| return -1; | |||
| return AVERROR_INVALIDDATA; | |||
| } | |||
| if (encoded_buf_size != s->size && (s->size % encoded_buf_size) != 0) { | |||
| /* If the encoded frame size differs from the frame size as indicated | |||
| @@ -363,7 +363,7 @@ static int cinepak_decode (CinepakContext *s) | |||
| for (i=0; i < num_strips; i++) { | |||
| if ((s->data + 12) > eod) | |||
| return -1; | |||
| return AVERROR_INVALIDDATA; | |||
| s->strips[i].id = s->data[0]; | |||
| s->strips[i].y1 = y0; | |||
| @@ -375,8 +375,8 @@ static int cinepak_decode (CinepakContext *s) | |||
| s->frame.key_frame = 1; | |||
| strip_size = AV_RB24 (&s->data[1]) - 12; | |||
| if(strip_size < 0) | |||
| return -1; | |||
| if (strip_size < 0) | |||
| return AVERROR_INVALIDDATA; | |||
| s->data += 12; | |||
| strip_size = ((s->data + strip_size) > eod) ? (eod - s->data) : strip_size; | |||
| @@ -427,7 +427,7 @@ static int cinepak_decode_frame(AVCodecContext *avctx, | |||
| AVPacket *avpkt) | |||
| { | |||
| const uint8_t *buf = avpkt->data; | |||
| int buf_size = avpkt->size; | |||
| int ret = 0, buf_size = avpkt->size; | |||
| CinepakContext *s = avctx->priv_data; | |||
| s->data = buf; | |||
| @@ -436,9 +436,9 @@ static int cinepak_decode_frame(AVCodecContext *avctx, | |||
| s->frame.reference = 3; | |||
| s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | | |||
| FF_BUFFER_HINTS_REUSABLE; | |||
| if (avctx->reget_buffer(avctx, &s->frame)) { | |||
| if ((ret = avctx->reget_buffer(avctx, &s->frame))) { | |||
| av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n"); | |||
| return -1; | |||
| return ret; | |||
| } | |||
| if (s->palette_video) { | |||
| @@ -259,6 +259,7 @@ void av_register_all(void) | |||
| REGISTER_PROTOCOL (FILE, file); | |||
| REGISTER_PROTOCOL (GOPHER, gopher); | |||
| REGISTER_PROTOCOL (HTTP, http); | |||
| REGISTER_PROTOCOL (HTTPPROXY, httpproxy); | |||
| REGISTER_PROTOCOL (HTTPS, https); | |||
| REGISTER_PROTOCOL (MMSH, mmsh); | |||
| REGISTER_PROTOCOL (MMST, mmst); | |||
| @@ -644,7 +644,8 @@ static int applehttp_read_seek(AVFormatContext *s, int stream_index, | |||
| for (i = 0; i < c->n_variants; i++) { | |||
| /* Reset reading */ | |||
| struct variant *var = c->variants[i]; | |||
| int64_t pos = av_rescale_rnd(c->first_timestamp, 1, stream_index >= 0 ? | |||
| int64_t pos = c->first_timestamp == AV_NOPTS_VALUE ? 0 : | |||
| av_rescale_rnd(c->first_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); | |||
| @@ -83,9 +83,11 @@ const AVClass ffurl_context_class = { | |||
| }; | |||
| /*@}*/ | |||
| static int default_interrupt_cb(void); | |||
| #if FF_API_OLD_INTERRUPT_CB | |||
| static int default_interrupt_cb(void); | |||
| int (*url_interrupt_cb)(void) = default_interrupt_cb; | |||
| #endif | |||
| URLProtocol *av_protocol_next(URLProtocol *p) | |||
| { | |||
| @@ -444,6 +446,7 @@ int ffurl_get_file_handle(URLContext *h) | |||
| return h->prot->url_get_file_handle(h); | |||
| } | |||
| #if FF_API_OLD_INTERRUPT_CB | |||
| static int default_interrupt_cb(void) | |||
| { | |||
| return 0; | |||
| @@ -455,13 +458,18 @@ void avio_set_interrupt_cb(int (*interrupt_cb)(void)) | |||
| interrupt_cb = default_interrupt_cb; | |||
| url_interrupt_cb = interrupt_cb; | |||
| } | |||
| #endif | |||
| int ff_check_interrupt(AVIOInterruptCB *cb) | |||
| { | |||
| int ret; | |||
| if (cb && cb->callback && (ret = cb->callback(cb->opaque))) | |||
| return ret; | |||
| #if FF_API_OLD_INTERRUPT_CB | |||
| return url_interrupt_cb(); | |||
| #else | |||
| return 0; | |||
| #endif | |||
| } | |||
| #if FF_API_OLD_AVIO | |||
| @@ -386,13 +386,17 @@ attribute_deprecated int url_exist(const char *url); | |||
| */ | |||
| int avio_check(const char *url, int flags); | |||
| #if FF_API_OLD_INTERRUPT_CB | |||
| /** | |||
| * The callback is called in blocking functions to test regulary if | |||
| * asynchronous interruption is needed. AVERROR_EXIT is returned | |||
| * in this case by the interrupted function. 'NULL' means no interrupt | |||
| * callback is given. | |||
| * @deprecated Use interrupt_callback in AVFormatContext/avio_open2 | |||
| * instead. | |||
| */ | |||
| void avio_set_interrupt_cb(int (*interrupt_cb)(void)); | |||
| attribute_deprecated void avio_set_interrupt_cb(int (*interrupt_cb)(void)); | |||
| #endif | |||
| /** | |||
| * Allocate and initialize an AVIOContext for buffered I/O. It must be later | |||
| @@ -110,6 +110,15 @@ static int http_open_cnx(URLContext *h) | |||
| path1, sizeof(path1), s->location); | |||
| ff_url_join(hoststr, sizeof(hoststr), NULL, NULL, hostname, port, NULL); | |||
| if (!strcmp(proto, "https")) { | |||
| lower_proto = "tls"; | |||
| use_proxy = 0; | |||
| if (port < 0) | |||
| port = 443; | |||
| } | |||
| if (port < 0) | |||
| port = 80; | |||
| if (path1[0] == '\0') | |||
| path = "/"; | |||
| else | |||
| @@ -124,13 +133,6 @@ static int http_open_cnx(URLContext *h) | |||
| av_url_split(NULL, 0, proxyauth, sizeof(proxyauth), | |||
| hostname, sizeof(hostname), &port, NULL, 0, proxy_path); | |||
| } | |||
| if (!strcmp(proto, "https")) { | |||
| lower_proto = "tls"; | |||
| if (port < 0) | |||
| port = 443; | |||
| } | |||
| if (port < 0) | |||
| port = 80; | |||
| ff_url_join(buf, sizeof(buf), lower_proto, NULL, hostname, port, NULL); | |||
| err = ffurl_open(&hd, buf, AVIO_FLAG_READ_WRITE, | |||
| @@ -413,10 +415,33 @@ static int http_connect(URLContext *h, const char *path, const char *local_path, | |||
| } | |||
| static int http_read(URLContext *h, uint8_t *buf, int size) | |||
| static int http_buf_read(URLContext *h, uint8_t *buf, int size) | |||
| { | |||
| HTTPContext *s = h->priv_data; | |||
| int len; | |||
| /* read bytes from input buffer first */ | |||
| len = s->buf_end - s->buf_ptr; | |||
| if (len > 0) { | |||
| if (len > size) | |||
| len = size; | |||
| memcpy(buf, s->buf_ptr, len); | |||
| s->buf_ptr += len; | |||
| } else { | |||
| if (!s->willclose && s->filesize >= 0 && s->off >= s->filesize) | |||
| return AVERROR_EOF; | |||
| len = ffurl_read(s->hd, buf, size); | |||
| } | |||
| if (len > 0) { | |||
| s->off += len; | |||
| if (s->chunksize > 0) | |||
| s->chunksize -= len; | |||
| } | |||
| return len; | |||
| } | |||
| static int http_read(URLContext *h, uint8_t *buf, int size) | |||
| { | |||
| HTTPContext *s = h->priv_data; | |||
| if (s->chunksize >= 0) { | |||
| if (!s->chunksize) { | |||
| @@ -439,24 +464,7 @@ static int http_read(URLContext *h, uint8_t *buf, int size) | |||
| } | |||
| size = FFMIN(size, s->chunksize); | |||
| } | |||
| /* read bytes from input buffer first */ | |||
| len = s->buf_end - s->buf_ptr; | |||
| if (len > 0) { | |||
| if (len > size) | |||
| len = size; | |||
| memcpy(buf, s->buf_ptr, len); | |||
| s->buf_ptr += len; | |||
| } else { | |||
| if (!s->willclose && s->filesize >= 0 && s->off >= s->filesize) | |||
| return AVERROR_EOF; | |||
| len = ffurl_read(s->hd, buf, size); | |||
| } | |||
| if (len > 0) { | |||
| s->off += len; | |||
| if (s->chunksize > 0) | |||
| s->chunksize -= len; | |||
| } | |||
| return len; | |||
| return http_buf_read(h, buf, size); | |||
| } | |||
| /* used only when posting data */ | |||
| @@ -572,3 +580,118 @@ URLProtocol ff_https_protocol = { | |||
| .priv_data_class = &https_context_class, | |||
| }; | |||
| #endif | |||
| #if CONFIG_HTTPPROXY_PROTOCOL | |||
| static int http_proxy_close(URLContext *h) | |||
| { | |||
| HTTPContext *s = h->priv_data; | |||
| if (s->hd) | |||
| ffurl_close(s->hd); | |||
| return 0; | |||
| } | |||
| static int http_proxy_open(URLContext *h, const char *uri, int flags) | |||
| { | |||
| HTTPContext *s = h->priv_data; | |||
| char hostname[1024], hoststr[1024]; | |||
| char auth[1024], pathbuf[1024], *path; | |||
| char line[1024], lower_url[100]; | |||
| int port, ret = 0; | |||
| HTTPAuthType cur_auth_type; | |||
| char *authstr; | |||
| h->is_streamed = 1; | |||
| av_url_split(NULL, 0, auth, sizeof(auth), hostname, sizeof(hostname), &port, | |||
| pathbuf, sizeof(pathbuf), uri); | |||
| ff_url_join(hoststr, sizeof(hoststr), NULL, NULL, hostname, port, NULL); | |||
| path = pathbuf; | |||
| if (*path == '/') | |||
| path++; | |||
| ff_url_join(lower_url, sizeof(lower_url), "tcp", NULL, hostname, port, | |||
| NULL); | |||
| redo: | |||
| ret = ffurl_open(&s->hd, lower_url, AVIO_FLAG_READ_WRITE, | |||
| &h->interrupt_callback, NULL); | |||
| if (ret < 0) | |||
| return ret; | |||
| authstr = ff_http_auth_create_response(&s->proxy_auth_state, auth, | |||
| path, "CONNECT"); | |||
| snprintf(s->buffer, sizeof(s->buffer), | |||
| "CONNECT %s HTTP/1.1\r\n" | |||
| "Host: %s\r\n" | |||
| "Connection: close\r\n" | |||
| "%s%s" | |||
| "\r\n", | |||
| path, | |||
| hoststr, | |||
| authstr ? "Proxy-" : "", authstr ? authstr : ""); | |||
| av_freep(&authstr); | |||
| if ((ret = ffurl_write(s->hd, s->buffer, strlen(s->buffer))) < 0) | |||
| goto fail; | |||
| s->buf_ptr = s->buffer; | |||
| s->buf_end = s->buffer; | |||
| s->line_count = 0; | |||
| s->filesize = -1; | |||
| cur_auth_type = s->proxy_auth_state.auth_type; | |||
| for (;;) { | |||
| int new_loc; | |||
| // Note: This uses buffering, potentially reading more than the | |||
| // HTTP header. If tunneling a protocol where the server starts | |||
| // the conversation, we might buffer part of that here, too. | |||
| // Reading that requires using the proper ffurl_read() function | |||
| // on this URLContext, not using the fd directly (as the tls | |||
| // protocol does). This shouldn't be an issue for tls though, | |||
| // since the client starts the conversation there, so there | |||
| // is no extra data that we might buffer up here. | |||
| if (http_get_line(s, line, sizeof(line)) < 0) { | |||
| ret = AVERROR(EIO); | |||
| goto fail; | |||
| } | |||
| av_dlog(h, "header='%s'\n", line); | |||
| ret = process_line(h, line, s->line_count, &new_loc); | |||
| if (ret < 0) | |||
| goto fail; | |||
| if (ret == 0) | |||
| break; | |||
| s->line_count++; | |||
| } | |||
| if (s->http_code == 407 && cur_auth_type == HTTP_AUTH_NONE && | |||
| s->proxy_auth_state.auth_type != HTTP_AUTH_NONE) { | |||
| ffurl_close(s->hd); | |||
| s->hd = NULL; | |||
| goto redo; | |||
| } | |||
| if (s->http_code < 400) | |||
| return 0; | |||
| ret = AVERROR(EIO); | |||
| fail: | |||
| http_proxy_close(h); | |||
| return ret; | |||
| } | |||
| static int http_proxy_write(URLContext *h, const uint8_t *buf, int size) | |||
| { | |||
| HTTPContext *s = h->priv_data; | |||
| return ffurl_write(s->hd, buf, size); | |||
| } | |||
| URLProtocol ff_httpproxy_protocol = { | |||
| .name = "httpproxy", | |||
| .url_open = http_proxy_open, | |||
| .url_read = http_buf_read, | |||
| .url_write = http_proxy_write, | |||
| .url_close = http_proxy_close, | |||
| .url_get_file_handle = http_get_file_handle, | |||
| .priv_data_size = sizeof(HTTPContext), | |||
| }; | |||
| #endif | |||
| @@ -74,6 +74,7 @@ typedef struct RTMPContext { | |||
| int skip_bytes; ///< number of bytes to skip from the input FLV stream in the next write call | |||
| uint8_t flv_header[11]; ///< partial incoming flv packet header | |||
| int flv_header_bytes; ///< number of initialized bytes in flv_header | |||
| int nb_invokes; ///< keeps track of invoke messages | |||
| } RTMPContext; | |||
| #define PLAYER_KEY_OPEN_PART_LEN 30 ///< length of partial key used for first client digest signing | |||
| @@ -166,7 +167,7 @@ static void gen_release_stream(URLContext *s, RTMPContext *rt) | |||
| av_log(s, AV_LOG_DEBUG, "Releasing stream...\n"); | |||
| p = pkt.data; | |||
| ff_amf_write_string(&p, "releaseStream"); | |||
| ff_amf_write_number(&p, 2.0); | |||
| ff_amf_write_number(&p, ++rt->nb_invokes); | |||
| ff_amf_write_null(&p); | |||
| ff_amf_write_string(&p, rt->playpath); | |||
| @@ -189,7 +190,7 @@ static void gen_fcpublish_stream(URLContext *s, RTMPContext *rt) | |||
| av_log(s, AV_LOG_DEBUG, "FCPublish stream...\n"); | |||
| p = pkt.data; | |||
| ff_amf_write_string(&p, "FCPublish"); | |||
| ff_amf_write_number(&p, 3.0); | |||
| ff_amf_write_number(&p, ++rt->nb_invokes); | |||
| ff_amf_write_null(&p); | |||
| ff_amf_write_string(&p, rt->playpath); | |||
| @@ -212,7 +213,7 @@ static void gen_fcunpublish_stream(URLContext *s, RTMPContext *rt) | |||
| av_log(s, AV_LOG_DEBUG, "UnPublishing stream...\n"); | |||
| p = pkt.data; | |||
| ff_amf_write_string(&p, "FCUnpublish"); | |||
| ff_amf_write_number(&p, 5.0); | |||
| ff_amf_write_number(&p, ++rt->nb_invokes); | |||
| ff_amf_write_null(&p); | |||
| ff_amf_write_string(&p, rt->playpath); | |||
| @@ -234,7 +235,7 @@ static void gen_create_stream(URLContext *s, RTMPContext *rt) | |||
| p = pkt.data; | |||
| ff_amf_write_string(&p, "createStream"); | |||
| ff_amf_write_number(&p, rt->is_input ? 3.0 : 4.0); | |||
| ff_amf_write_number(&p, ++rt->nb_invokes); | |||
| ff_amf_write_null(&p); | |||
| ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]); | |||
| @@ -429,7 +429,7 @@ static void finalize_packet(RTPDemuxContext *s, AVPacket *pkt, uint32_t timestam | |||
| if (timestamp == RTP_NOTS_VALUE) | |||
| return; | |||
| if (s->last_rtcp_ntp_time != AV_NOPTS_VALUE) { | |||
| if (s->last_rtcp_ntp_time != AV_NOPTS_VALUE && s->ic->nb_streams > 1) { | |||
| int64_t addend; | |||
| int delta_timestamp; | |||
| @@ -444,7 +444,13 @@ static void finalize_packet(RTPDemuxContext *s, AVPacket *pkt, uint32_t timestam | |||
| if (!s->base_timestamp) | |||
| s->base_timestamp = timestamp; | |||
| pkt->pts = s->range_start_offset + timestamp - s->base_timestamp; | |||
| /* assume that the difference is INT32_MIN < x < INT32_MAX, but allow the first timestamp to exceed INT32_MAX */ | |||
| if (!s->timestamp) | |||
| s->unwrapped_timestamp += timestamp; | |||
| else | |||
| s->unwrapped_timestamp += (int32_t)(timestamp - s->timestamp); | |||
| s->timestamp = timestamp; | |||
| pkt->pts = s->unwrapped_timestamp + s->range_start_offset - s->base_timestamp; | |||
| } | |||
| static int rtp_parse_packet_internal(RTPDemuxContext *s, AVPacket *pkt, | |||
| @@ -151,6 +151,7 @@ struct RTPDemuxContext { | |||
| uint32_t timestamp; | |||
| uint32_t base_timestamp; | |||
| uint32_t cur_timestamp; | |||
| int64_t unwrapped_timestamp; | |||
| int64_t range_start_offset; | |||
| int max_payload_size; | |||
| struct MpegTSContext *ts; /* only used for MP2T payloads */ | |||
| @@ -52,6 +52,8 @@ static int rtsp_read_play(AVFormatContext *s) | |||
| rtpctx->last_rtcp_ntp_time = AV_NOPTS_VALUE; | |||
| rtpctx->first_rtcp_ntp_time = AV_NOPTS_VALUE; | |||
| rtpctx->base_timestamp = 0; | |||
| rtpctx->timestamp = 0; | |||
| rtpctx->unwrapped_timestamp = 0; | |||
| rtpctx->rtcp_ts_offset = 0; | |||
| } | |||
| } | |||
| @@ -34,6 +34,7 @@ | |||
| #define FDSC_TAG MKBETAG('F', 'D', 'S', 'C') | |||
| #define STAB_TAG MKBETAG('S', 'T', 'A', 'B') | |||
| #define CVID_TAG MKBETAG('c', 'v', 'i', 'd') | |||
| #define RAW_TAG MKBETAG('r', 'a', 'w', ' ') | |||
| typedef struct { | |||
| int stream; | |||
| @@ -129,8 +130,11 @@ static int film_read_header(AVFormatContext *s, | |||
| if (AV_RB32(&scratch[8]) == CVID_TAG) { | |||
| film->video_type = CODEC_ID_CINEPAK; | |||
| } else | |||
| } else if (AV_RB32(&scratch[8]) == RAW_TAG) { | |||
| film->video_type = CODEC_ID_RAWVIDEO; | |||
| } else { | |||
| film->video_type = CODEC_ID_NONE; | |||
| } | |||
| /* initialize the decoder streams */ | |||
| if (film->video_type) { | |||
| @@ -143,6 +147,15 @@ static int film_read_header(AVFormatContext *s, | |||
| st->codec->codec_tag = 0; /* no fourcc */ | |||
| st->codec->width = AV_RB32(&scratch[16]); | |||
| st->codec->height = AV_RB32(&scratch[12]); | |||
| if (film->video_type == CODEC_ID_RAWVIDEO) { | |||
| if (scratch[20] == 24) { | |||
| st->codec->pix_fmt = PIX_FMT_RGB24; | |||
| } else { | |||
| av_log(s, AV_LOG_ERROR, "raw video is using unhandled %dbpp\n", scratch[20]); | |||
| return -1; | |||
| } | |||
| } | |||
| } | |||
| if (film->audio_type) { | |||
| @@ -111,9 +111,15 @@ static int tls_open(URLContext *h, const char *uri, int flags) | |||
| char buf[200], host[200]; | |||
| int numerichost = 0; | |||
| struct addrinfo hints = { 0 }, *ai = NULL; | |||
| const char *proxy_path; | |||
| int use_proxy; | |||
| ff_tls_init(); | |||
| proxy_path = getenv("http_proxy"); | |||
| use_proxy = (proxy_path != NULL) && !getenv("no_proxy") && | |||
| av_strstart(proxy_path, "http://", NULL); | |||
| av_url_split(NULL, 0, NULL, 0, host, sizeof(host), &port, NULL, 0, uri); | |||
| ff_url_join(buf, sizeof(buf), "tcp", NULL, host, port, NULL); | |||
| @@ -123,6 +129,17 @@ static int tls_open(URLContext *h, const char *uri, int flags) | |||
| freeaddrinfo(ai); | |||
| } | |||
| if (use_proxy) { | |||
| char proxy_host[200], proxy_auth[200], dest[200]; | |||
| int proxy_port; | |||
| av_url_split(NULL, 0, proxy_auth, sizeof(proxy_auth), | |||
| proxy_host, sizeof(proxy_host), &proxy_port, NULL, 0, | |||
| proxy_path); | |||
| ff_url_join(dest, sizeof(dest), NULL, NULL, host, port, NULL); | |||
| ff_url_join(buf, sizeof(buf), "httpproxy", proxy_auth, proxy_host, | |||
| proxy_port, "/%s", dest); | |||
| } | |||
| ret = ffurl_open(&c->tcp, buf, AVIO_FLAG_READ_WRITE, | |||
| &h->interrupt_callback, NULL); | |||
| if (ret) | |||
| @@ -24,7 +24,7 @@ | |||
| #include "libavutil/avutil.h" | |||
| #define LIBAVFORMAT_VERSION_MAJOR 53 | |||
| #define LIBAVFORMAT_VERSION_MINOR 20 | |||
| #define LIBAVFORMAT_VERSION_MINOR 21 | |||
| #define LIBAVFORMAT_VERSION_MICRO 0 | |||
| #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ | |||
| @@ -113,5 +113,8 @@ | |||
| #ifndef FF_API_REORDER_PRIVATE | |||
| #define FF_API_REORDER_PRIVATE (LIBAVFORMAT_VERSION_MAJOR < 54) | |||
| #endif | |||
| #ifndef FF_API_OLD_INTERRUPT_CB | |||
| #define FF_API_OLD_INTERRUPT_CB (LIBAVFORMAT_VERSION_MAJOR < 54) | |||
| #endif | |||
| #endif /* AVFORMAT_VERSION_H */ | |||
| @@ -71,7 +71,7 @@ do_lavf mxf_d10 "-ar 48000 -ac 2 -r 25 -s 720x576 -vf pad=720:608:0:32 -vcodec m | |||
| fi | |||
| if [ -n "$do_ts" ] ; then | |||
| do_lavf ts "-ab 64k" | |||
| do_lavf ts "-ab 64k -mpegts_transport_stream_id 42" | |||
| fi | |||
| if [ -n "$do_swf" ] ; then | |||
| @@ -1,3 +1,3 @@ | |||
| 151774afed45b19da9b7e83613a1e72b *./tests/data/lavf/lavf.ts | |||
| 024f0cdd4c51a158b2a38b901d2ed2e5 *./tests/data/lavf/lavf.ts | |||
| 406644 ./tests/data/lavf/lavf.ts | |||
| ./tests/data/lavf/lavf.ts CRC=0x133216c1 | |||