* 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 |