diff --git a/doc/general.texi b/doc/general.texi index 7770046132..dd744f0641 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -863,11 +863,12 @@ performance on systems without hardware floating point support). @item ALSA @tab X @tab X @item BKTR @tab X @tab @item DV1394 @tab X @tab +@item Linux framebuffer @tab X @tab @item JACK @tab X @tab +@item LIBCDIO @tab X @item LIBDC1394 @tab X @tab @item OSS @tab X @tab X @item Pulseaudio @tab X @tab -@item Video4Linux @tab X @tab @item Video4Linux2 @tab X @tab @item VfW capture @tab X @tab @item X11 grabbing @tab X @tab diff --git a/ffmpeg.c b/ffmpeg.c index 4714b616a7..0a2f055ba5 100644 --- a/ffmpeg.c +++ b/ffmpeg.c @@ -2651,32 +2651,35 @@ static int transcode_init(OutputFile *output_files, int nb_output_files, break; } /* two pass mode */ - if (codec->codec_id != CODEC_ID_H264 && - (codec->flags & (CODEC_FLAG_PASS1 | CODEC_FLAG_PASS2))) { + if (codec->flags & (CODEC_FLAG_PASS1 | CODEC_FLAG_PASS2)) { char logfilename[1024]; FILE *f; snprintf(logfilename, sizeof(logfilename), "%s-%d.log", pass_logfilename_prefix ? pass_logfilename_prefix : DEFAULT_PASS_LOGFILENAME_PREFIX, i); - if (codec->flags & CODEC_FLAG_PASS2) { - char *logbuffer; - size_t logbuffer_size; - if (cmdutils_read_file(logfilename, &logbuffer, &logbuffer_size) < 0) { - av_log(NULL, AV_LOG_FATAL, "Error reading log file '%s' for pass-2 encoding\n", - logfilename); - exit_program(1); + if (!strcmp(ost->enc->name, "libx264")) { + av_dict_set(&ost->opts, "stats", logfilename, AV_DICT_DONT_OVERWRITE); + } else { + if (codec->flags & CODEC_FLAG_PASS2) { + char *logbuffer; + size_t logbuffer_size; + if (cmdutils_read_file(logfilename, &logbuffer, &logbuffer_size) < 0) { + av_log(NULL, AV_LOG_FATAL, "Error reading log file '%s' for pass-2 encoding\n", + logfilename); + exit_program(1); + } + codec->stats_in = logbuffer; } - codec->stats_in = logbuffer; - } - if (codec->flags & CODEC_FLAG_PASS1) { - f = fopen(logfilename, "wb"); - if (!f) { - av_log(NULL, AV_LOG_FATAL, "Cannot write log file '%s' for pass-1 encoding: %s\n", - logfilename, strerror(errno)); - exit_program(1); + if (codec->flags & CODEC_FLAG_PASS1) { + f = fopen(logfilename, "wb"); + if (!f) { + av_log(NULL, AV_LOG_FATAL, "Cannot write log file '%s' for pass-1 encoding: %s\n", + logfilename, strerror(errno)); + exit_program(1); + } + ost->logfile = f; } - ost->logfile = f; } } } diff --git a/libavcodec/dfa.c b/libavcodec/dfa.c index 97c0954422..2e68976c1f 100644 --- a/libavcodec/dfa.c +++ b/libavcodec/dfa.c @@ -21,7 +21,6 @@ */ #include "avcodec.h" -#include "libavutil/intreadwrite.h" #include "bytestream.h" #include "libavutil/lzo.h" // for av_memcpy_backptr @@ -45,19 +44,16 @@ static av_cold int dfa_decode_init(AVCodecContext *avctx) return 0; } -static int decode_copy(uint8_t *frame, int width, int height, - const uint8_t *src, const uint8_t *src_end) +static int decode_copy(GetByteContext *gb, uint8_t *frame, int width, int height) { const int size = width * height; - if (src_end - src < size) + if (bytestream2_get_buffer(gb, frame, size) != size) return -1; - bytestream_get_buffer(&src, frame, size); return 0; } -static int decode_tsw1(uint8_t *frame, int width, int height, - const uint8_t *src, const uint8_t *src_end) +static int decode_tsw1(GetByteContext *gb, uint8_t *frame, int width, int height) { const uint8_t *frame_start = frame; const uint8_t *frame_end = frame + width * height; @@ -65,24 +61,24 @@ static int decode_tsw1(uint8_t *frame, int width, int height, int v, count, segments; unsigned offset; - segments = bytestream_get_le32(&src); - offset = bytestream_get_le32(&src); + segments = bytestream2_get_le32(gb); + offset = bytestream2_get_le32(gb); if (segments == 0 && offset == frame_end - frame) return 0; // skip frame if (frame_end - frame <= offset) return -1; frame += offset; while (segments--) { + if (bytestream2_get_bytes_left(gb) < 2) + return -1; if (mask == 0x10000) { - if (src >= src_end) - return -1; - bitbuf = bytestream_get_le16(&src); + bitbuf = bytestream2_get_le16u(gb); mask = 1; } - if (src_end - src < 2 || frame_end - frame < 2) + if (frame_end - frame < 2) return -1; if (bitbuf & mask) { - v = bytestream_get_le16(&src); + v = bytestream2_get_le16(gb); offset = (v & 0x1FFF) << 1; count = ((v >> 13) + 2) << 1; if (frame - frame_start < offset || frame_end - frame < count) @@ -90,8 +86,8 @@ static int decode_tsw1(uint8_t *frame, int width, int height, av_memcpy_backptr(frame, offset, count); frame += count; } else { - *frame++ = *src++; - *frame++ = *src++; + *frame++ = bytestream2_get_byte(gb); + *frame++ = bytestream2_get_byte(gb); } mask <<= 1; } @@ -99,26 +95,25 @@ static int decode_tsw1(uint8_t *frame, int width, int height, return 0; } -static int decode_dsw1(uint8_t *frame, int width, int height, - const uint8_t *src, const uint8_t *src_end) +static int decode_dsw1(GetByteContext *gb, uint8_t *frame, int width, int height) { const uint8_t *frame_start = frame; const uint8_t *frame_end = frame + width * height; int mask = 0x10000, bitbuf = 0; int v, offset, count, segments; - segments = bytestream_get_le16(&src); + segments = bytestream2_get_le16(gb); while (segments--) { + if (bytestream2_get_bytes_left(gb) < 2) + return -1; if (mask == 0x10000) { - if (src >= src_end) - return -1; - bitbuf = bytestream_get_le16(&src); + bitbuf = bytestream2_get_le16u(gb); mask = 1; } - if (src_end - src < 2 || frame_end - frame < 2) + if (frame_end - frame < 2) return -1; if (bitbuf & mask) { - v = bytestream_get_le16(&src); + v = bytestream2_get_le16(gb); offset = (v & 0x1FFF) << 1; count = ((v >> 13) + 2) << 1; if (frame - frame_start < offset || frame_end - frame < count) @@ -128,10 +123,10 @@ static int decode_dsw1(uint8_t *frame, int width, int height, frame[v] = frame[v - offset]; frame += count; } else if (bitbuf & (mask << 1)) { - frame += bytestream_get_le16(&src); + frame += bytestream2_get_le16(gb); } else { - *frame++ = *src++; - *frame++ = *src++; + *frame++ = bytestream2_get_byte(gb); + *frame++ = bytestream2_get_byte(gb); } mask <<= 2; } @@ -139,26 +134,25 @@ static int decode_dsw1(uint8_t *frame, int width, int height, return 0; } -static int decode_dds1(uint8_t *frame, int width, int height, - const uint8_t *src, const uint8_t *src_end) +static int decode_dds1(GetByteContext *gb, uint8_t *frame, int width, int height) { const uint8_t *frame_start = frame; const uint8_t *frame_end = frame + width * height; int mask = 0x10000, bitbuf = 0; int i, v, offset, count, segments; - segments = bytestream_get_le16(&src); + segments = bytestream2_get_le16(gb); while (segments--) { + if (bytestream2_get_bytes_left(gb) < 2) + return -1; if (mask == 0x10000) { - if (src >= src_end) - return -1; - bitbuf = bytestream_get_le16(&src); + bitbuf = bytestream2_get_le16u(gb); mask = 1; } - if (src_end - src < 2 || frame_end - frame < 2) + if (frame_end - frame < 2) return -1; if (bitbuf & mask) { - v = bytestream_get_le16(&src); + v = bytestream2_get_le16(gb); offset = (v & 0x1FFF) << 2; count = ((v >> 13) + 2) << 1; if (frame - frame_start < offset || frame_end - frame < count*2 + width) @@ -170,13 +164,13 @@ static int decode_dds1(uint8_t *frame, int width, int height, frame += 2; } } else if (bitbuf & (mask << 1)) { - frame += bytestream_get_le16(&src) * 2; + frame += bytestream2_get_le16(gb) * 2; } else { frame[0] = frame[1] = - frame[width] = frame[width + 1] = *src++; + frame[width] = frame[width + 1] = bytestream2_get_byte(gb); frame += 2; frame[0] = frame[1] = - frame[width] = frame[width + 1] = *src++; + frame[width] = frame[width + 1] = bytestream2_get_byte(gb); frame += 2; } mask <<= 2; @@ -185,40 +179,40 @@ static int decode_dds1(uint8_t *frame, int width, int height, return 0; } -static int decode_bdlt(uint8_t *frame, int width, int height, - const uint8_t *src, const uint8_t *src_end) +static int decode_bdlt(GetByteContext *gb, uint8_t *frame, int width, int height) { uint8_t *line_ptr; int count, lines, segments; - count = bytestream_get_le16(&src); + count = bytestream2_get_le16(gb); if (count >= height) return -1; frame += width * count; - lines = bytestream_get_le16(&src); - if (count + lines > height || src >= src_end) + lines = bytestream2_get_le16(gb); + if (count + lines > height) return -1; while (lines--) { + if (bytestream2_get_bytes_left(gb) < 1) + return -1; line_ptr = frame; frame += width; - segments = *src++; + segments = bytestream2_get_byteu(gb); while (segments--) { - if (src_end - src < 3) + if (frame - line_ptr <= bytestream2_peek_byte(gb)) return -1; - if (frame - line_ptr <= *src) - return -1; - line_ptr += *src++; - count = (int8_t)*src++; + line_ptr += bytestream2_get_byte(gb); + count = (int8_t)bytestream2_get_byte(gb); if (count >= 0) { - if (frame - line_ptr < count || src_end - src < count) + if (frame - line_ptr < count) + return -1; + if (bytestream2_get_buffer(gb, line_ptr, count) != count) return -1; - bytestream_get_buffer(&src, line_ptr, count); } else { count = -count; - if (frame - line_ptr < count || src >= src_end) + if (frame - line_ptr < count) return -1; - memset(line_ptr, *src++, count); + memset(line_ptr, bytestream2_get_byte(gb), count); } line_ptr += count; } @@ -227,49 +221,49 @@ static int decode_bdlt(uint8_t *frame, int width, int height, return 0; } -static int decode_wdlt(uint8_t *frame, int width, int height, - const uint8_t *src, const uint8_t *src_end) +static int decode_wdlt(GetByteContext *gb, uint8_t *frame, int width, int height) { const uint8_t *frame_end = frame + width * height; uint8_t *line_ptr; int count, i, v, lines, segments; - lines = bytestream_get_le16(&src); - if (lines > height || src >= src_end) + lines = bytestream2_get_le16(gb); + if (lines > height) return -1; while (lines--) { - segments = bytestream_get_le16(&src); + if (bytestream2_get_bytes_left(gb) < 2) + return -1; + segments = bytestream2_get_le16u(gb); while ((segments & 0xC000) == 0xC000) { unsigned delta = -((int16_t)segments * width); if (frame_end - frame <= delta) return -1; frame += delta; - segments = bytestream_get_le16(&src); + segments = bytestream2_get_le16(gb); } if (segments & 0x8000) { frame[width - 1] = segments & 0xFF; - segments = bytestream_get_le16(&src); + segments = bytestream2_get_le16(gb); } line_ptr = frame; frame += width; while (segments--) { - if (src_end - src < 2) + if (frame - line_ptr <= bytestream2_peek_byte(gb)) return -1; - if (frame - line_ptr <= *src) - return -1; - line_ptr += *src++; - count = (int8_t)*src++; + line_ptr += bytestream2_get_byte(gb); + count = (int8_t)bytestream2_get_byte(gb); if (count >= 0) { - if (frame - line_ptr < count*2 || src_end - src < count*2) + if (frame - line_ptr < count * 2) + return -1; + if (bytestream2_get_buffer(gb, line_ptr, count * 2) != count * 2) return -1; - bytestream_get_buffer(&src, line_ptr, count*2); line_ptr += count * 2; } else { count = -count; - if (frame - line_ptr < count*2 || src_end - src < 2) + if (frame - line_ptr < count * 2) return -1; - v = bytestream_get_le16(&src); + v = bytestream2_get_le16(gb); for (i = 0; i < count; i++) bytestream_put_le16(&line_ptr, v); } @@ -279,22 +273,19 @@ static int decode_wdlt(uint8_t *frame, int width, int height, return 0; } -static int decode_unk6(uint8_t *frame, int width, int height, - const uint8_t *src, const uint8_t *src_end) +static int decode_unk6(GetByteContext *gb, uint8_t *frame, int width, int height) { return -1; } -static int decode_blck(uint8_t *frame, int width, int height, - const uint8_t *src, const uint8_t *src_end) +static int decode_blck(GetByteContext *gb, uint8_t *frame, int width, int height) { memset(frame, 0, width * height); return 0; } -typedef int (*chunk_decoder)(uint8_t *frame, int width, int height, - const uint8_t *src, const uint8_t *src_end); +typedef int (*chunk_decoder)(GetByteContext *gb, uint8_t *frame, int width, int height); static const chunk_decoder decoder[8] = { decode_copy, decode_tsw1, decode_bdlt, decode_wdlt, @@ -310,9 +301,8 @@ static int dfa_decode_frame(AVCodecContext *avctx, AVPacket *avpkt) { DfaContext *s = avctx->priv_data; + GetByteContext gb; const uint8_t *buf = avpkt->data; - const uint8_t *buf_end = avpkt->data + avpkt->size; - const uint8_t *tmp_buf; uint32_t chunk_type, chunk_size; uint8_t *dst; int ret; @@ -326,27 +316,22 @@ static int dfa_decode_frame(AVCodecContext *avctx, return ret; } - while (buf < buf_end) { - chunk_size = AV_RL32(buf + 4); - chunk_type = AV_RL32(buf + 8); - buf += 12; - if (buf_end - buf < chunk_size) { - av_log(avctx, AV_LOG_ERROR, "Chunk size is too big (%d bytes)\n", chunk_size); - return -1; - } + bytestream2_init(&gb, avpkt->data, avpkt->size); + while (bytestream2_get_bytes_left(&gb) > 0) { + bytestream2_skip(&gb, 4); + chunk_size = bytestream2_get_le32(&gb); + chunk_type = bytestream2_get_le32(&gb); if (!chunk_type) break; if (chunk_type == 1) { pal_elems = FFMIN(chunk_size / 3, 256); - tmp_buf = buf; for (i = 0; i < pal_elems; i++) { - s->pal[i] = bytestream_get_be24(&tmp_buf) << 2; + s->pal[i] = bytestream2_get_be24(&gb) << 2; s->pal[i] |= 0xFF << 24 | (s->pal[i] >> 6) & 0x30303; } s->pic.palette_has_changed = 1; } else if (chunk_type <= 9) { - if (decoder[chunk_type - 2](s->frame_buf, avctx->width, avctx->height, - buf, buf + chunk_size)) { + if (decoder[chunk_type - 2](&gb, s->frame_buf, avctx->width, avctx->height)) { av_log(avctx, AV_LOG_ERROR, "Error decoding %s chunk\n", chunk_name[chunk_type - 2]); return -1; diff --git a/libavcodec/h264.c b/libavcodec/h264.c index 7f09154128..2cb56028de 100644 --- a/libavcodec/h264.c +++ b/libavcodec/h264.c @@ -3967,10 +3967,10 @@ static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size){ break; case NAL_SPS: init_get_bits(&s->gb, ptr, bit_length); - if(ff_h264_decode_seq_parameter_set(h) < 0 && (h->is_avc ? (nalsize != consumed) && nalsize : 1)){ + if (ff_h264_decode_seq_parameter_set(h) < 0 && (h->is_avc ? (nalsize != consumed) && nalsize : 1)){ av_log(h->s.avctx, AV_LOG_DEBUG, "SPS decoding failure, trying alternative mode\n"); if(h->is_avc) av_assert0(next_avc - buf_index + consumed == nalsize); - init_get_bits(&s->gb, &buf[buf_index + 1 - consumed], 8*(next_avc - buf_index + consumed)); + init_get_bits(&s->gb, &buf[buf_index + 1 - consumed], 8*(next_avc - buf_index + consumed - 1)); ff_h264_decode_seq_parameter_set(h); } diff --git a/libavcodec/h264_direct.c b/libavcodec/h264_direct.c index 263832d829..ce395a3c56 100644 --- a/libavcodec/h264_direct.c +++ b/libavcodec/h264_direct.c @@ -254,7 +254,7 @@ static void pred_spatial_direct_motion(H264Context * const h, int *mb_type){ mb_type_col[1] = h->ref_list[1][0].f.mb_type[mb_xy + s->mb_stride]; b8_stride = 2+4*s->mb_stride; b4_stride *= 6; - if(IS_INTERLACED(mb_type_col[0]) != IS_INTERLACED(mb_type_col[1])){ + if (IS_INTERLACED(mb_type_col[0]) != IS_INTERLACED(mb_type_col[1])) { mb_type_col[0] &= ~MB_TYPE_INTERLACED; mb_type_col[1] &= ~MB_TYPE_INTERLACED; } @@ -444,6 +444,10 @@ static void pred_temp_direct_motion(H264Context * const h, int *mb_type){ mb_type_col[1] = h->ref_list[1][0].f.mb_type[mb_xy + s->mb_stride]; b8_stride = 2+4*s->mb_stride; b4_stride *= 6; + if (IS_INTERLACED(mb_type_col[0]) != IS_INTERLACED(mb_type_col[1])) { + mb_type_col[0] &= ~MB_TYPE_INTERLACED; + mb_type_col[1] &= ~MB_TYPE_INTERLACED; + } sub_mb_type = MB_TYPE_16x16|MB_TYPE_P0L0|MB_TYPE_P0L1|MB_TYPE_DIRECT2; /* B_SUB_8x8 */ diff --git a/libavcodec/h264_ps.c b/libavcodec/h264_ps.c index e56a7160e1..9c39af1f17 100644 --- a/libavcodec/h264_ps.c +++ b/libavcodec/h264_ps.c @@ -251,9 +251,10 @@ static inline int decode_vui_parameters(H264Context *h, SPS *sps){ return -1; } } - if(get_bits_left(&s->gb) < 0){ + + if (get_bits_left(&s->gb) < 0) { av_log(h->s.avctx, AV_LOG_ERROR, "Overread VUI by %d bits\n", -get_bits_left(&s->gb)); - return -1; + return AVERROR_INVALIDDATA; } return 0; diff --git a/libavcodec/libx264.c b/libavcodec/libx264.c index 3d503dbfc7..fa9188debf 100644 --- a/libavcodec/libx264.c +++ b/libavcodec/libx264.c @@ -43,7 +43,6 @@ typedef struct X264Context { char *profile; char *level; int fastfirstpass; - char *stats; char *wpredp; char *x264opts; float crf; @@ -70,6 +69,7 @@ typedef struct X264Context { char *partitions; int direct_pred; int slice_max_size; + char *stats; } X264Context; static void X264_log(void *p, int level, const char *fmt, va_list args) @@ -323,8 +323,6 @@ static av_cold int X264_init(AVCodecContext *avctx) x4->params.rc.f_rf_constant_max = x4->crf_max; } - OPT_STR("stats", x4->stats); - if (avctx->rc_buffer_size && avctx->rc_initial_buffer_occupancy && (avctx->rc_initial_buffer_occupancy <= avctx->rc_buffer_size)) { x4->params.rc.f_vbv_buffer_init = @@ -399,6 +397,7 @@ static av_cold int X264_init(AVCodecContext *avctx) PARSE_X264_OPT("psy-rd", psy_rd); PARSE_X264_OPT("deblock", deblock); PARSE_X264_OPT("partitions", partitions); + PARSE_X264_OPT("stats", stats); if (x4->psy >= 0) x4->params.analyse.b_psy = x4->psy; if (x4->rc_lookahead >= 0) @@ -592,7 +591,8 @@ static const AVOption options[] = { { "spatial", NULL, 0, AV_OPT_TYPE_CONST, { X264_DIRECT_PRED_SPATIAL }, 0, 0, VE, "direct-pred" }, { "temporal", NULL, 0, AV_OPT_TYPE_CONST, { X264_DIRECT_PRED_TEMPORAL }, 0, 0, VE, "direct-pred" }, { "auto", NULL, 0, AV_OPT_TYPE_CONST, { X264_DIRECT_PRED_AUTO }, 0, 0, VE, "direct-pred" }, - { "slice-max-size","Constant quantization parameter rate control method",OFFSET(slice_max_size), AV_OPT_TYPE_INT, {-1 }, -1, INT_MAX, VE }, + { "slice-max-size","Limit the size of each slice in bytes", OFFSET(slice_max_size),AV_OPT_TYPE_INT, {-1 }, -1, INT_MAX, VE }, + { "stats", "Filename for 2 pass stats", OFFSET(stats), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE }, { NULL }, }; diff --git a/libavformat/http.c b/libavformat/http.c index 8922a74441..2589a8ffb9 100644 --- a/libavformat/http.c +++ b/libavformat/http.c @@ -96,7 +96,7 @@ static int http_open_cnx(URLContext *h) char auth[1024], proxyauth[1024] = ""; char path1[1024]; char buf[1024], urlbuf[1024]; - int port, use_proxy, err, location_changed = 0, redirects = 0; + int port, use_proxy, err, location_changed = 0, redirects = 0, attempts = 0; HTTPAuthType cur_auth_type, cur_proxy_auth_type; HTTPContext *s = h->priv_data; URLContext *hd = NULL; @@ -148,16 +148,18 @@ static int http_open_cnx(URLContext *h) cur_proxy_auth_type = s->auth_state.auth_type; if (http_connect(h, path, local_path, hoststr, auth, proxyauth, &location_changed) < 0) goto fail; + attempts++; if (s->http_code == 401) { - if (cur_auth_type == HTTP_AUTH_NONE && s->auth_state.auth_type != HTTP_AUTH_NONE) { + if ((cur_auth_type == HTTP_AUTH_NONE || s->auth_state.stale) && + s->auth_state.auth_type != HTTP_AUTH_NONE && attempts < 4) { ffurl_close(hd); goto redo; } else goto fail; } if (s->http_code == 407) { - if (cur_proxy_auth_type == HTTP_AUTH_NONE && - s->proxy_auth_state.auth_type != HTTP_AUTH_NONE) { + if ((cur_proxy_auth_type == HTTP_AUTH_NONE || s->proxy_auth_state.stale) && + s->proxy_auth_state.auth_type != HTTP_AUTH_NONE && attempts < 4) { ffurl_close(hd); goto redo; } else @@ -169,6 +171,10 @@ static int http_open_cnx(URLContext *h) ffurl_close(hd); if (redirects++ >= MAX_REDIRECTS) return AVERROR(EIO); + /* Restart the authentication process with the new target, which + * might use a different auth mechanism. */ + memset(&s->auth_state, 0, sizeof(s->auth_state)); + attempts = 0; location_changed = 0; goto redo; } @@ -602,7 +608,7 @@ static int http_proxy_open(URLContext *h, const char *uri, int flags) char hostname[1024], hoststr[1024]; char auth[1024], pathbuf[1024], *path; char line[1024], lower_url[100]; - int port, ret = 0; + int port, ret = 0, attempts = 0; HTTPAuthType cur_auth_type; char *authstr; @@ -669,8 +675,10 @@ redo: break; s->line_count++; } - if (s->http_code == 407 && cur_auth_type == HTTP_AUTH_NONE && - s->proxy_auth_state.auth_type != HTTP_AUTH_NONE) { + attempts++; + if (s->http_code == 407 && + (cur_auth_type == HTTP_AUTH_NONE || s->proxy_auth_state.stale) && + s->proxy_auth_state.auth_type != HTTP_AUTH_NONE && attempts < 2) { ffurl_close(s->hd); s->hd = NULL; goto redo; diff --git a/libavformat/httpauth.c b/libavformat/httpauth.c index ba31c1a9aa..86cdac7f07 100644 --- a/libavformat/httpauth.c +++ b/libavformat/httpauth.c @@ -57,6 +57,9 @@ static void handle_digest_params(HTTPAuthState *state, const char *key, } else if (!strncmp(key, "qop=", key_len)) { *dest = digest->qop; *dest_len = sizeof(digest->qop); + } else if (!strncmp(key, "stale=", key_len)) { + *dest = digest->stale; + *dest_len = sizeof(digest->stale); } } @@ -93,6 +96,7 @@ void ff_http_auth_handle_header(HTTPAuthState *state, const char *key, state->auth_type <= HTTP_AUTH_BASIC) { state->auth_type = HTTP_AUTH_BASIC; state->realm[0] = 0; + state->stale = 0; ff_parse_key_value(p, (ff_parse_key_val_cb) handle_basic_params, state); } else if (av_stristart(value, "Digest ", &p) && @@ -100,10 +104,13 @@ void ff_http_auth_handle_header(HTTPAuthState *state, const char *key, state->auth_type = HTTP_AUTH_DIGEST; memset(&state->digest_params, 0, sizeof(DigestParams)); state->realm[0] = 0; + state->stale = 0; ff_parse_key_value(p, (ff_parse_key_val_cb) handle_digest_params, state); choose_qop(state->digest_params.qop, sizeof(state->digest_params.qop)); + if (!av_strcasecmp(state->digest_params.stale, "true")) + state->stale = 1; } } else if (!strcmp(key, "Authentication-Info")) { ff_parse_key_value(value, (ff_parse_key_val_cb) handle_digest_update, @@ -237,6 +244,9 @@ char *ff_http_auth_create_response(HTTPAuthState *state, const char *auth, { char *authstr = NULL; + /* Clear the stale flag, we assume the auth is ok now. It is reset + * by the server headers if there's a new issue. */ + state->stale = 0; if (!auth || !strchr(auth, ':')) return NULL; diff --git a/libavformat/httpauth.h b/libavformat/httpauth.h index ebab3fca29..62dd25e637 100644 --- a/libavformat/httpauth.h +++ b/libavformat/httpauth.h @@ -41,6 +41,9 @@ typedef struct { char opaque[300]; /**< A server-specified string that should be * included in authentication responses, not * included in the actual digest calculation. */ + char stale[10]; /**< The server indicated that the auth was ok, + * but needs to be redone with a new, non-stale + * nonce. */ int nc; /**< Nonce count, the number of earlier replies * where this particular nonce has been used. */ } DigestParams; @@ -62,6 +65,10 @@ typedef struct { * The parameters specifiec to digest authentication. */ DigestParams digest_params; + /** + * Auth ok, but needs to be resent with a new nonce. + */ + int stale; } HTTPAuthState; void ff_http_auth_handle_header(HTTPAuthState *state, const char *key, diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c index ac2196a925..b28fb519cb 100644 --- a/libavformat/rtsp.c +++ b/libavformat/rtsp.c @@ -1122,7 +1122,7 @@ int ff_rtsp_send_cmd_with_content(AVFormatContext *s, { RTSPState *rt = s->priv_data; HTTPAuthType cur_auth_type; - int ret; + int ret, attempts = 0; retry: cur_auth_type = rt->auth_state.auth_type; @@ -1133,9 +1133,11 @@ retry: if ((ret = ff_rtsp_read_reply(s, reply, content_ptr, 0, method) ) < 0) return ret; + attempts++; - if (reply->status_code == 401 && cur_auth_type == HTTP_AUTH_NONE && - rt->auth_state.auth_type != HTTP_AUTH_NONE) + if (reply->status_code == 401 && + (cur_auth_type == HTTP_AUTH_NONE || rt->auth_state.stale) && + rt->auth_state.auth_type != HTTP_AUTH_NONE && attempts < 2) goto retry; if (reply->status_code > 400){ diff --git a/libavformat/rtspdec.c b/libavformat/rtspdec.c index f95cf8cc93..15005bb9be 100644 --- a/libavformat/rtspdec.c +++ b/libavformat/rtspdec.c @@ -335,7 +335,8 @@ retry: rt->packets++; /* send dummy request to keep TCP connection alive */ - if ((av_gettime() - rt->last_cmd_time) / 1000000 >= rt->timeout / 2) { + if ((av_gettime() - rt->last_cmd_time) / 1000000 >= rt->timeout / 2 || + rt->auth_state.stale) { if (rt->server_type == RTSP_SERVER_WMS || (rt->server_type != RTSP_SERVER_REAL && rt->get_parameter_supported)) { @@ -343,6 +344,10 @@ retry: } else { ff_rtsp_send_cmd_async(s, "OPTIONS", "*", NULL); } + /* The stale flag should be reset when creating the auth response in + * ff_rtsp_send_cmd_async, but reset it here just in case we never + * called the auth code (if we didn't have any credentials set). */ + rt->auth_state.stale = 0; } return 0; diff --git a/tests/fate/wavpack.mak b/tests/fate/wavpack.mak index 2807b26e95..bf18954877 100644 --- a/tests/fate/wavpack.mak +++ b/tests/fate/wavpack.mak @@ -1,87 +1,90 @@ # Lossless -FATE_TESTS += fate-wavpack-lossless-float +FATE_WAVPACK += fate-wavpack-lossless-float fate-wavpack-lossless-float: CMD = md5 -i $(SAMPLES)/wavpack/lossless/32bit_float-partial.wv -f f32le -FATE_TESTS += fate-wavpack-lossless-8bit +FATE_WAVPACK += fate-wavpack-lossless-8bit fate-wavpack-lossless-8bit: CMD = md5 -i $(SAMPLES)/wavpack/lossless/8bit-partial.wv -f s8 -FATE_TESTS += fate-wavpack-lossless-12bit +FATE_WAVPACK += fate-wavpack-lossless-12bit fate-wavpack-lossless-12bit: CMD = md5 -i $(SAMPLES)/wavpack/lossless/12bit-partial.wv -f s16le -FATE_TESTS += fate-wavpack-lossless-16bit +FATE_WAVPACK += fate-wavpack-lossless-16bit fate-wavpack-lossless-16bit: CMD = md5 -i $(SAMPLES)/wavpack/lossless/16bit-partial.wv -f s16le -FATE_TESTS += fate-wavpack-lossless-24bit +FATE_WAVPACK += fate-wavpack-lossless-24bit fate-wavpack-lossless-24bit: CMD = md5 -i $(SAMPLES)/wavpack/lossless/24bit-partial.wv -f s24le -FATE_TESTS += fate-wavpack-lossless-32bit +FATE_WAVPACK += fate-wavpack-lossless-32bit fate-wavpack-lossless-32bit: CMD = md5 -i $(SAMPLES)/wavpack/lossless/32bit_int-partial.wv -f s32le # Lossy -FATE_TESTS += fate-wavpack-lossy-float +FATE_WAVPACK += fate-wavpack-lossy-float fate-wavpack-lossy-float: CMD = md5 -i $(SAMPLES)/wavpack/lossy/2.0_32-bit_float.wv -f f32le -FATE_TESTS += fate-wavpack-lossy-8bit +FATE_WAVPACK += fate-wavpack-lossy-8bit fate-wavpack-lossy-8bit: CMD = md5 -i $(SAMPLES)/wavpack/lossy/4.0_8-bit.wv -f s8 -FATE_TESTS += fate-wavpack-lossy-16bit +FATE_WAVPACK += fate-wavpack-lossy-16bit fate-wavpack-lossy-16bit: CMD = md5 -i $(SAMPLES)/wavpack/lossy/4.0_16-bit.wv -f s16le -FATE_TESTS += fate-wavpack-lossy-24bit +FATE_WAVPACK += fate-wavpack-lossy-24bit fate-wavpack-lossy-24bit: CMD = md5 -i $(SAMPLES)/wavpack/lossy/4.0_24-bit.wv -f s24le -FATE_TESTS += fate-wavpack-lossy-32bit +FATE_WAVPACK += fate-wavpack-lossy-32bit fate-wavpack-lossy-32bit: CMD = md5 -i $(SAMPLES)/wavpack/lossy/4.0_32-bit_int.wv -f s32le # Channel configurations -FATE_TESTS += fate-wavpack-channels-monofloat +FATE_WAVPACK += fate-wavpack-channels-monofloat fate-wavpack-channels-monofloat: CMD = md5 -i $(SAMPLES)/wavpack/num_channels/mono_float-partial.wv -f f32le -FATE_TESTS += fate-wavpack-channels-monoint +FATE_WAVPACK += fate-wavpack-channels-monoint fate-wavpack-channels-monoint: CMD = md5 -i $(SAMPLES)/wavpack/num_channels/mono_16bit_int.wv -f s16le -FATE_TESTS += fate-wavpack-channels-4.0 +FATE_WAVPACK += fate-wavpack-channels-4.0 fate-wavpack-channels-4.0: CMD = md5 -i $(SAMPLES)/wavpack/num_channels/edward_4.0_16bit-partial.wv -f s16le -FATE_TESTS += fate-wavpack-channels-5.1 +FATE_WAVPACK += fate-wavpack-channels-5.1 fate-wavpack-channels-5.1: CMD = md5 -i $(SAMPLES)/wavpack/num_channels/panslab_sample_5.1_16bit-partial.wv -f s16le -FATE_TESTS += fate-wavpack-channels-6.1 +FATE_WAVPACK += fate-wavpack-channels-6.1 fate-wavpack-channels-6.1: CMD = md5 -i $(SAMPLES)/wavpack/num_channels/eva_2.22_6.1_16bit-partial.wv -f s16le -FATE_TESTS += fate-wavpack-channels-7.1 +FATE_WAVPACK += fate-wavpack-channels-7.1 fate-wavpack-channels-7.1: CMD = md5 -i $(SAMPLES)/wavpack/num_channels/panslab_sample_7.1_16bit-partial.wv -f s16le # Speed modes -FATE_TESTS += fate-wavpack-speed-default +FATE_WAVPACK += fate-wavpack-speed-default fate-wavpack-speed-default: CMD = md5 -i $(SAMPLES)/wavpack/speed_modes/default-partial.wv -f s16le -FATE_TESTS += fate-wavpack-speed-fast +FATE_WAVPACK += fate-wavpack-speed-fast fate-wavpack-speed-fast: CMD = md5 -i $(SAMPLES)/wavpack/speed_modes/fast-partial.wv -f s16le -FATE_TESTS += fate-wavpack-speed-high +FATE_WAVPACK += fate-wavpack-speed-high fate-wavpack-speed-high: CMD = md5 -i $(SAMPLES)/wavpack/speed_modes/high-partial.wv -f s16le -FATE_TESTS += fate-wavpack-speed-vhigh +FATE_WAVPACK += fate-wavpack-speed-vhigh fate-wavpack-speed-vhigh: CMD = md5 -i $(SAMPLES)/wavpack/speed_modes/vhigh-partial.wv -f s16le # Special Cases -FATE_TESTS += fate-wavpack-cuesheet +FATE_WAVPACK += fate-wavpack-cuesheet fate-wavpack-cuesheet: CMD = md5 -i $(SAMPLES)/wavpack/special/cue_sheet.wv -f s16le -FATE_TESTS += fate-wavpack-zerolsbs +FATE_WAVPACK += fate-wavpack-zerolsbs fate-wavpack-zerolsbs: CMD = md5 -i $(SAMPLES)/wavpack/special/zero_lsbs.wv -f s16le -FATE_TESTS += fate-wavpack-clipping +FATE_WAVPACK += fate-wavpack-clipping fate-wavpack-clipping: CMD = md5 -i $(SAMPLES)/wavpack/special/clipping.wv -f s16le -FATE_TESTS += fate-wavpack-falsestereo +FATE_WAVPACK += fate-wavpack-falsestereo fate-wavpack-falsestereo: CMD = md5 -i $(SAMPLES)/wavpack/special/false_stereo.wv -f s16le -FATE_TESTS += fate-wavpack-matroskamode +FATE_WAVPACK += fate-wavpack-matroskamode fate-wavpack-matroskamode: CMD = md5 -i $(SAMPLES)/wavpack/special/matroska_mode.mka -f s16le + +FATE_TESTS += $(FATE_WAVPACK) +fate-wavpack: $(FATE_WAVPACK)