mirror of
https://git.ffmpeg.org/ffmpeg.git
synced 2026-01-13 09:35:27 +01:00
Compare commits
39 Commits
release/4.
...
n3.3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1968a1eef1 | ||
|
|
f4f3bf3c94 | ||
|
|
6557ea8e2b | ||
|
|
9d742f774a | ||
|
|
5e84c94f69 | ||
|
|
e90de50195 | ||
|
|
51ca6fda05 | ||
|
|
d1cae50a04 | ||
|
|
b51217381d | ||
|
|
f5f0b2f44c | ||
|
|
e9fc7a90ba | ||
|
|
414d11fff6 | ||
|
|
1830b0a6c7 | ||
|
|
0ed4f26cf2 | ||
|
|
69e35db80d | ||
|
|
af43c7092c | ||
|
|
ecdf52745f | ||
|
|
07e7ebf52d | ||
|
|
37589e6443 | ||
|
|
ad37fb86d7 | ||
|
|
4f325589f9 | ||
|
|
707d4c7fb5 | ||
|
|
c30d0ace65 | ||
|
|
0c188bc595 | ||
|
|
72e038acaf | ||
|
|
83e6a4a32b | ||
|
|
7182fbc471 | ||
|
|
0b4d87fad1 | ||
|
|
7034009f62 | ||
|
|
6c9574e490 | ||
|
|
37fcf089b4 | ||
|
|
f4400a92f5 | ||
|
|
a430ba9925 | ||
|
|
1833ec5334 | ||
|
|
c9c977be27 | ||
|
|
3c9e1b89a1 | ||
|
|
2ff93effb3 | ||
|
|
b1377b2d28 | ||
|
|
e0064df4ff |
@@ -1,7 +1,7 @@
|
||||
Entries are sorted chronologically from oldest to youngest within each release,
|
||||
releases are sorted from youngest to oldest.
|
||||
|
||||
version <next>:
|
||||
version 3.3:
|
||||
- CrystalHD decoder moved to new decode API
|
||||
- add internal ebur128 library, remove external libebur128 dependency
|
||||
- Pro-MPEG CoP #3-R2 FEC protocol
|
||||
@@ -22,6 +22,7 @@ version <next>:
|
||||
- threshold filter
|
||||
- midequalizer filter
|
||||
- Optimal Huffman tables for (M)JPEG encoding
|
||||
- VAAPI-accelerated MPEG-2 and VP8 encoding
|
||||
- FM Screen Capture Codec decoder
|
||||
- native Opus encoder
|
||||
- ScreenPressor decoder
|
||||
@@ -32,6 +33,7 @@ version <next>:
|
||||
- Removed the legacy X11 screen grabber, use XCB instead
|
||||
- MPEG-7 Video Signature filter
|
||||
- Removed asyncts filter (use af_aresample instead)
|
||||
- Intel QSV-accelerated VP8 video decoding
|
||||
|
||||
|
||||
version 3.2:
|
||||
@@ -119,7 +121,6 @@ version 3.1:
|
||||
- libutvideo wrapper removed
|
||||
- YUY2 Lossless Codec decoder
|
||||
- VideoToolbox H.264 encoder
|
||||
- VAAPI-accelerated MPEG-2 and VP8 encoding
|
||||
|
||||
|
||||
version 3.0:
|
||||
|
||||
15
RELEASE_NOTES
Normal file
15
RELEASE_NOTES
Normal file
@@ -0,0 +1,15 @@
|
||||
|
||||
┌────────────────────────────────────────┐
|
||||
│ RELEASE NOTES for FFmpeg 3.3 "Hilbert" │
|
||||
└────────────────────────────────────────┘
|
||||
|
||||
The FFmpeg Project proudly presents FFmpeg 3.3 "Hilbert", about 5
|
||||
months after the release of FFmpeg 3.2.
|
||||
|
||||
A complete Changelog is available at the root of the project, and the
|
||||
complete Git history on http://source.ffmpeg.org.
|
||||
|
||||
We hope you will like this release as much as we enjoyed working on it, and
|
||||
as usual, if you have any questions about it, or any FFmpeg related topic,
|
||||
feel free to join us on the #ffmpeg IRC channel (on irc.freenode.net) or ask
|
||||
on the mailing-lists.
|
||||
2
configure
vendored
2
configure
vendored
@@ -1513,6 +1513,7 @@ EXTERNAL_LIBRARY_GPL_LIST="
|
||||
"
|
||||
|
||||
EXTERNAL_LIBRARY_NONFREE_LIST="
|
||||
decklink
|
||||
libfdk_aac
|
||||
openssl
|
||||
"
|
||||
@@ -1536,7 +1537,6 @@ EXTERNAL_LIBRARY_LIST="
|
||||
$EXTERNAL_LIBRARY_GPLV3_LIST
|
||||
chromaprint
|
||||
crystalhd
|
||||
decklink
|
||||
gcrypt
|
||||
gnutls
|
||||
jni
|
||||
|
||||
@@ -15,11 +15,11 @@ libavutil: 2015-08-28
|
||||
|
||||
API changes, most recent first:
|
||||
|
||||
2017-03-31 - xxxxxxx - lavu 55.57.100 - spherical.h
|
||||
2017-03-31 - 9033e8723c - lavu 55.57.100 - spherical.h
|
||||
Add av_spherical_projection_name().
|
||||
Add av_spherical_from_name().
|
||||
|
||||
2017-03-30 - xxxxxxx - lavu 55.53.100 / 55.27.0 - hwcontext.h
|
||||
2017-03-30 - 4cda23f1f1 - lavu 55.53.100 / 55.27.0 - hwcontext.h
|
||||
Add av_hwframe_map() and associated AV_HWFRAME_MAP_* flags.
|
||||
Add av_hwframe_ctx_create_derived().
|
||||
|
||||
@@ -44,7 +44,7 @@ API changes, most recent first:
|
||||
Add AVCodecContext.hwaccel_flags field. This will control some hwaccels at
|
||||
a later point.
|
||||
|
||||
2017-03-21 - xxxxxxx - lavf 57.67.100 / 57.08.0 - avio.h
|
||||
2017-03-21 - fc9f14c7de - lavf 57.67.100 / 57.08.0 - avio.h
|
||||
Add AVIO_SEEKABLE_TIME flag.
|
||||
|
||||
2017-03-21 - d682ae70b4 - lavf 57.66.105, lavc 57.83.101 - avformat.h, avcodec.h
|
||||
@@ -52,7 +52,7 @@ API changes, most recent first:
|
||||
bump, and libavformat will behave as if it were always set.
|
||||
Deprecate av_packet_merge_side_data() and av_packet_split_side_data().
|
||||
|
||||
2016-03-20 - xxxxxxx - lavu 55.50.100 / 55.21.0 - imgutils.h
|
||||
2016-03-20 - 8200b16a9c - lavu 55.50.100 / 55.21.0 - imgutils.h
|
||||
Add av_image_copy_uc_from(), a version of av_image_copy() for copying
|
||||
from GPU mapped memory.
|
||||
|
||||
@@ -63,7 +63,7 @@ API changes, most recent first:
|
||||
Deprecate AVFilterGraph.resample_lavr_opts
|
||||
It's never been used by avfilter nor passed to anything.
|
||||
|
||||
2017-02-10 - xxxxxxx - lavu 55.48.100 / 55.33.0 - spherical.h
|
||||
2017-02-10 - 1b7ffddb3a - lavu 55.48.100 / 55.33.0 - spherical.h
|
||||
Add AV_SPHERICAL_EQUIRECTANGULAR_TILE, av_spherical_tile_bounds(),
|
||||
and projection-specific properties (bound_left, bound_top, bound_right,
|
||||
bound_bottom, padding) to AVSphericalMapping.
|
||||
@@ -83,7 +83,7 @@ API changes, most recent first:
|
||||
2017-02-11 - e3af49b14b - lavu 55.47.100 - frame.h
|
||||
Add AVFrame.opaque_ref.
|
||||
|
||||
2017-01-31 - xxxxxxx - lavu 55.46.100 / 55.20.0 - cpu.h
|
||||
2017-01-31 - 2eab48177d - lavu 55.46.100 / 55.20.0 - cpu.h
|
||||
Add AV_CPU_FLAG_SSSE3SLOW.
|
||||
|
||||
2017-01-24 - c4618f842a - lavu 55.45.100 - channel_layout.h
|
||||
@@ -96,20 +96,20 @@ API changes, most recent first:
|
||||
Deprecate struct vaapi_context and the vaapi.h installed header.
|
||||
Callers should set AVCodecContext.hw_frames_ctx instead.
|
||||
|
||||
2017-01-12 - dbe9dbed31 - lavfi 6.69.100- buffersink.h
|
||||
2017-01-12 - dbe9dbed31 - lavfi 6.69.100 - buffersink.h
|
||||
Add av_buffersink_get_*() functions.
|
||||
|
||||
2017-01-06 - 9488032e10 - lavf 57.62.100- avio.h
|
||||
2017-01-06 - 9488032e10 - lavf 57.62.100 - avio.h
|
||||
Add avio_get_dyn_buf()
|
||||
|
||||
2016-12-10 - xxxxxxx - lavu xx.xx.100- imgutils.h
|
||||
2016-12-10 - f542b152aa - lavu 55.43.100 - imgutils.h
|
||||
Add av_image_check_size2()
|
||||
|
||||
2016-xx-xx - xxxxxxx - lavc 57.67.100 / 57.29.0 - avcodec.h
|
||||
2016-12-07 - e7a6f8c972 - lavc 57.67.100 / 57.29.0 - avcodec.h
|
||||
Add AV_PKT_DATA_SPHERICAL packet side data to export AVSphericalMapping
|
||||
information from containers.
|
||||
|
||||
2016-xx-xx - xxxxxxx - lavu 55.42.100 / 55.30.0 - spherical.h
|
||||
2016-12-07 - 8f58ecc344 - lavu 55.42.100 / 55.30.0 - spherical.h
|
||||
Add AV_FRAME_DATA_SPHERICAL value, av_spherical_alloc() API and
|
||||
AVSphericalMapping type to export and describe spherical video properties.
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ PROJECT_NAME = FFmpeg
|
||||
# could be handy for archiving the generated documentation or if some version
|
||||
# control system is used.
|
||||
|
||||
PROJECT_NUMBER =
|
||||
PROJECT_NUMBER = 3.3
|
||||
|
||||
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
||||
# for a project that appears at the top of each page and should give viewer a
|
||||
|
||||
@@ -64,7 +64,7 @@ static int decode_write_frame(const char *outfilename, AVCodecContext *avctx,
|
||||
fflush(stdout);
|
||||
|
||||
/* the picture is allocated by the decoder, no need to free it */
|
||||
snprintf(buf, sizeof(buf), outfilename, *frame_count);
|
||||
snprintf(buf, sizeof(buf), "%s-%d", outfilename, *frame_count);
|
||||
pgm_save(frame->data[0], frame->linesize[0],
|
||||
frame->width, frame->height, buf);
|
||||
(*frame_count)++;
|
||||
|
||||
9
ffmpeg.c
9
ffmpeg.c
@@ -30,6 +30,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdatomic.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#if HAVE_IO_H
|
||||
@@ -319,7 +320,7 @@ void term_exit(void)
|
||||
|
||||
static volatile int received_sigterm = 0;
|
||||
static volatile int received_nb_signals = 0;
|
||||
static volatile int transcode_init_done = 0;
|
||||
static atomic_int transcode_init_done = ATOMIC_VAR_INIT(0);
|
||||
static volatile int ffmpeg_exited = 0;
|
||||
static int main_return_code = 0;
|
||||
|
||||
@@ -457,7 +458,7 @@ static int read_key(void)
|
||||
|
||||
static int decode_interrupt_cb(void *ctx)
|
||||
{
|
||||
return received_nb_signals > transcode_init_done;
|
||||
return received_nb_signals > atomic_load(&transcode_init_done);
|
||||
}
|
||||
|
||||
const AVIOInterruptCB int_cb = { decode_interrupt_cb, NULL };
|
||||
@@ -612,7 +613,7 @@ static void ffmpeg_cleanup(int ret)
|
||||
if (received_sigterm) {
|
||||
av_log(NULL, AV_LOG_INFO, "Exiting normally, received signal %d.\n",
|
||||
(int) received_sigterm);
|
||||
} else if (ret && transcode_init_done) {
|
||||
} else if (ret && atomic_load(&transcode_init_done)) {
|
||||
av_log(NULL, AV_LOG_INFO, "Conversion failed!\n");
|
||||
}
|
||||
term_exit();
|
||||
@@ -3758,7 +3759,7 @@ static int transcode_init(void)
|
||||
return ret;
|
||||
}
|
||||
|
||||
transcode_init_done = 1;
|
||||
atomic_store(&transcode_init_done, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -3442,8 +3442,6 @@ int main(int argc, char **argv)
|
||||
goto end;
|
||||
}
|
||||
#endif
|
||||
av_log_set_callback(log_callback);
|
||||
|
||||
av_log_set_flags(AV_LOG_SKIP_REPEATED);
|
||||
register_exit(ffprobe_cleanup);
|
||||
|
||||
@@ -3459,6 +3457,9 @@ int main(int argc, char **argv)
|
||||
show_banner(argc, argv, options);
|
||||
parse_options(NULL, argc, argv, options, opt_input_file);
|
||||
|
||||
if (do_show_log)
|
||||
av_log_set_callback(log_callback);
|
||||
|
||||
/* mark things to show, based on -show_entries */
|
||||
SET_DO_SHOW(CHAPTERS, chapters);
|
||||
SET_DO_SHOW(ERROR, error);
|
||||
|
||||
@@ -973,7 +973,8 @@ OBJS-$(CONFIG_AAC_ADTSTOASC_BSF) += aac_adtstoasc_bsf.o aacadtsdec.o \
|
||||
OBJS-$(CONFIG_CHOMP_BSF) += chomp_bsf.o
|
||||
OBJS-$(CONFIG_DUMP_EXTRADATA_BSF) += dump_extradata_bsf.o
|
||||
OBJS-$(CONFIG_DCA_CORE_BSF) += dca_core_bsf.o
|
||||
OBJS-$(CONFIG_EXTRACT_EXTRADATA_BSF) += extract_extradata_bsf.o
|
||||
OBJS-$(CONFIG_EXTRACT_EXTRADATA_BSF) += extract_extradata_bsf.o \
|
||||
h2645_parse.o
|
||||
OBJS-$(CONFIG_H264_MP4TOANNEXB_BSF) += h264_mp4toannexb_bsf.o
|
||||
OBJS-$(CONFIG_HEVC_MP4TOANNEXB_BSF) += hevc_mp4toannexb_bsf.o
|
||||
OBJS-$(CONFIG_IMX_DUMP_HEADER_BSF) += imx_dump_header_bsf.o
|
||||
|
||||
@@ -189,12 +189,12 @@ static void guess_palette(DVDSubContext* ctx,
|
||||
r = (((subtitle_color >> 16) & 0xff) * level) >> 8;
|
||||
g = (((subtitle_color >> 8) & 0xff) * level) >> 8;
|
||||
b = (((subtitle_color >> 0) & 0xff) * level) >> 8;
|
||||
rgba_palette[i] = b | (g << 8) | (r << 16) | ((alpha[i] * 17) << 24);
|
||||
rgba_palette[i] = b | (g << 8) | (r << 16) | ((alpha[i] * 17U) << 24);
|
||||
color_used[colormap[i]] = (i + 1);
|
||||
j++;
|
||||
} else {
|
||||
rgba_palette[i] = (rgba_palette[color_used[colormap[i]] - 1] & 0x00ffffff) |
|
||||
((alpha[i] * 17) << 24);
|
||||
((alpha[i] * 17U) << 24);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,6 +59,9 @@ int ff_h264_pred_weight_table(GetBitContext *gb, const SPS *sps,
|
||||
if (luma_weight_flag) {
|
||||
pwt->luma_weight[i][list][0] = get_se_golomb(gb);
|
||||
pwt->luma_weight[i][list][1] = get_se_golomb(gb);
|
||||
if ((int8_t)pwt->luma_weight[i][list][0] != pwt->luma_weight[i][list][0] ||
|
||||
(int8_t)pwt->luma_weight[i][list][1] != pwt->luma_weight[i][list][1])
|
||||
goto out_range_weight;
|
||||
if (pwt->luma_weight[i][list][0] != luma_def ||
|
||||
pwt->luma_weight[i][list][1] != 0) {
|
||||
pwt->use_weight = 1;
|
||||
@@ -76,6 +79,9 @@ int ff_h264_pred_weight_table(GetBitContext *gb, const SPS *sps,
|
||||
for (j = 0; j < 2; j++) {
|
||||
pwt->chroma_weight[i][list][j][0] = get_se_golomb(gb);
|
||||
pwt->chroma_weight[i][list][j][1] = get_se_golomb(gb);
|
||||
if ((int8_t)pwt->chroma_weight[i][list][j][0] != pwt->chroma_weight[i][list][j][0] ||
|
||||
(int8_t)pwt->chroma_weight[i][list][j][1] != pwt->chroma_weight[i][list][j][1])
|
||||
goto out_range_weight;
|
||||
if (pwt->chroma_weight[i][list][j][0] != chroma_def ||
|
||||
pwt->chroma_weight[i][list][j][1] != 0) {
|
||||
pwt->use_weight_chroma = 1;
|
||||
@@ -104,6 +110,9 @@ int ff_h264_pred_weight_table(GetBitContext *gb, const SPS *sps,
|
||||
}
|
||||
pwt->use_weight = pwt->use_weight || pwt->use_weight_chroma;
|
||||
return 0;
|
||||
out_range_weight:
|
||||
avpriv_request_sample(logctx, "Out of range weight\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -109,7 +109,6 @@ int ff_h264_ref_picture(H264Context *h, H264Picture *dst, H264Picture *src)
|
||||
dst->poc = src->poc;
|
||||
dst->frame_num = src->frame_num;
|
||||
dst->mmco_reset = src->mmco_reset;
|
||||
dst->pic_id = src->pic_id;
|
||||
dst->long_ref = src->long_ref;
|
||||
dst->mbaff = src->mbaff;
|
||||
dst->field_picture = src->field_picture;
|
||||
|
||||
@@ -1423,14 +1423,14 @@ static int h264_field_start(H264Context *h, const H264SliceContext *sl,
|
||||
* We have to do that before the "dummy" in-between frame allocation,
|
||||
* since that can modify h->cur_pic_ptr. */
|
||||
if (h->first_field) {
|
||||
int last_field = last_pic_structure == PICT_BOTTOM_FIELD;
|
||||
av_assert0(h->cur_pic_ptr);
|
||||
av_assert0(h->cur_pic_ptr->f->buf[0]);
|
||||
assert(h->cur_pic_ptr->reference != DELAYED_PIC_REF);
|
||||
|
||||
/* Mark old field/frame as completed */
|
||||
if (h->cur_pic_ptr->tf.owner == h->avctx) {
|
||||
ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX,
|
||||
last_pic_structure == PICT_BOTTOM_FIELD);
|
||||
if (h->cur_pic_ptr->tf.owner[last_field] == h->avctx) {
|
||||
ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX, last_field);
|
||||
}
|
||||
|
||||
/* figure out if we have a complementary field pair */
|
||||
@@ -1568,7 +1568,9 @@ static int h264_field_start(H264Context *h, const H264SliceContext *sl,
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
} else {
|
||||
int field = h->picture_structure == PICT_BOTTOM_FIELD;
|
||||
release_unused_pictures(h, 0);
|
||||
h->cur_pic_ptr->tf.owner[field] = h->avctx;
|
||||
}
|
||||
/* Some macroblocks can be accessed before they're available in case
|
||||
* of lost slices, MBAFF or threading. */
|
||||
@@ -1778,9 +1780,12 @@ static int h264_slice_header_parse(const H264Context *h, H264SliceContext *sl,
|
||||
}
|
||||
if ((pps->weighted_pred && sl->slice_type_nos == AV_PICTURE_TYPE_P) ||
|
||||
(pps->weighted_bipred_idc == 1 &&
|
||||
sl->slice_type_nos == AV_PICTURE_TYPE_B))
|
||||
ff_h264_pred_weight_table(&sl->gb, sps, sl->ref_count,
|
||||
sl->slice_type_nos == AV_PICTURE_TYPE_B)) {
|
||||
ret = ff_h264_pred_weight_table(&sl->gb, sps, sl->ref_count,
|
||||
sl->slice_type_nos, &sl->pwt, h->avctx);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
sl->explicit_ref_marking = 0;
|
||||
if (nal->ref_idc) {
|
||||
@@ -1886,7 +1891,8 @@ static int h264_slice_init(H264Context *h, H264SliceContext *sl,
|
||||
|
||||
if (sl->slice_type_nos == AV_PICTURE_TYPE_B && !sl->direct_spatial_mv_pred)
|
||||
ff_h264_direct_dist_scale_factor(h, sl);
|
||||
ff_h264_direct_ref_list_init(h, sl);
|
||||
if (!h->setup_finished)
|
||||
ff_h264_direct_ref_list_init(h, sl);
|
||||
|
||||
if (h->avctx->skip_loop_filter >= AVDISCARD_ALL ||
|
||||
(h->avctx->skip_loop_filter >= AVDISCARD_NONKEY &&
|
||||
|
||||
@@ -585,7 +585,7 @@ static int hls_slice_header(HEVCContext *s)
|
||||
}
|
||||
|
||||
/* 8.3.1 */
|
||||
if (s->temporal_id == 0 &&
|
||||
if (sh->first_slice_in_pic_flag && s->temporal_id == 0 &&
|
||||
s->nal_unit_type != HEVC_NAL_TRAIL_N &&
|
||||
s->nal_unit_type != HEVC_NAL_TSA_N &&
|
||||
s->nal_unit_type != HEVC_NAL_STSA_N &&
|
||||
@@ -2771,25 +2771,25 @@ static int decode_nal_unit(HEVCContext *s, const H2645NAL *nal)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (s->max_ra == INT_MAX) {
|
||||
if (s->nal_unit_type == HEVC_NAL_CRA_NUT || IS_BLA(s)) {
|
||||
s->max_ra = s->poc;
|
||||
if (s->sh.first_slice_in_pic_flag) {
|
||||
if (s->max_ra == INT_MAX) {
|
||||
if (s->nal_unit_type == HEVC_NAL_CRA_NUT || IS_BLA(s)) {
|
||||
s->max_ra = s->poc;
|
||||
} else {
|
||||
if (IS_IDR(s))
|
||||
s->max_ra = INT_MIN;
|
||||
}
|
||||
}
|
||||
|
||||
if ((s->nal_unit_type == HEVC_NAL_RASL_R || s->nal_unit_type == HEVC_NAL_RASL_N) &&
|
||||
s->poc <= s->max_ra) {
|
||||
s->is_decoded = 0;
|
||||
break;
|
||||
} else {
|
||||
if (IS_IDR(s))
|
||||
if (s->nal_unit_type == HEVC_NAL_RASL_R && s->poc > s->max_ra)
|
||||
s->max_ra = INT_MIN;
|
||||
}
|
||||
}
|
||||
|
||||
if ((s->nal_unit_type == HEVC_NAL_RASL_R || s->nal_unit_type == HEVC_NAL_RASL_N) &&
|
||||
s->poc <= s->max_ra) {
|
||||
s->is_decoded = 0;
|
||||
break;
|
||||
} else {
|
||||
if (s->nal_unit_type == HEVC_NAL_RASL_R && s->poc > s->max_ra)
|
||||
s->max_ra = INT_MIN;
|
||||
}
|
||||
|
||||
if (s->sh.first_slice_in_pic_flag) {
|
||||
ret = hevc_frame_start(s);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@@ -579,6 +579,8 @@ static av_cold int decode_init_thread_copy(AVCodecContext *avctx)
|
||||
HYuvContext *s = avctx->priv_data;
|
||||
int i, ret;
|
||||
|
||||
s->avctx = avctx;
|
||||
|
||||
if ((ret = ff_huffyuv_alloc_temp(s)) < 0) {
|
||||
ff_huffyuv_common_end(s);
|
||||
return ret;
|
||||
|
||||
@@ -91,13 +91,17 @@ static void jpeg_table_header(AVCodecContext *avctx, PutBitContext *p,
|
||||
{
|
||||
int i, j, size;
|
||||
uint8_t *ptr;
|
||||
MpegEncContext *s = avctx->priv_data;
|
||||
MpegEncContext *s = NULL;
|
||||
|
||||
/* Since avctx->priv_data will point to LJpegEncContext in this case */
|
||||
if (avctx->codec_id != AV_CODEC_ID_LJPEG)
|
||||
s = avctx->priv_data;
|
||||
|
||||
if (avctx->codec_id != AV_CODEC_ID_LJPEG) {
|
||||
int matrix_count = 1 + !!memcmp(luma_intra_matrix,
|
||||
chroma_intra_matrix,
|
||||
sizeof(luma_intra_matrix[0]) * 64);
|
||||
if (s->force_duplicated_matrix)
|
||||
if (s && s->force_duplicated_matrix)
|
||||
matrix_count = 2;
|
||||
/* quant matrixes */
|
||||
put_marker(p, DQT);
|
||||
@@ -134,7 +138,7 @@ static void jpeg_table_header(AVCodecContext *avctx, PutBitContext *p,
|
||||
|
||||
// Only MJPEG can have a variable Huffman variable. All other
|
||||
// formats use the default Huffman table.
|
||||
if (s->out_format == FMT_MJPEG && s->huffman == HUFFMAN_TABLE_OPTIMAL) {
|
||||
if (s && s->huffman == HUFFMAN_TABLE_OPTIMAL) {
|
||||
size += put_huffman_table(p, 0, 0, s->mjpeg_ctx->bits_dc_luminance,
|
||||
s->mjpeg_ctx->val_dc_luminance);
|
||||
size += put_huffman_table(p, 0, 1, s->mjpeg_ctx->bits_dc_chrominance,
|
||||
|
||||
@@ -87,6 +87,8 @@ void ff_mjpegenc_huffman_compute_bits(PTable *prob_table, HuffTable *distincts,
|
||||
|
||||
int min;
|
||||
|
||||
av_assert0(max_length > 0);
|
||||
|
||||
to->nitems = 0;
|
||||
from->nitems = 0;
|
||||
to->item_idx[0] = 0;
|
||||
|
||||
@@ -399,6 +399,9 @@ FF_ENABLE_DEPRECATION_WARNINGS
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
|
||||
if (avctx->codec_id == AV_CODEC_ID_AMV || (avctx->active_thread_type & FF_THREAD_SLICE))
|
||||
s->huffman = 0;
|
||||
|
||||
if (s->intra_dc_precision > (avctx->codec_id == AV_CODEC_ID_MPEG2VIDEO ? 3 : 0)) {
|
||||
av_log(avctx, AV_LOG_ERROR, "intra dc precision too large\n");
|
||||
return AVERROR(EINVAL);
|
||||
|
||||
@@ -173,7 +173,7 @@ static int read_low_coeffs(AVCodecContext *avctx, int16_t *dst, int size, int wi
|
||||
}
|
||||
}
|
||||
|
||||
if (i + rlen > size)
|
||||
if (rlen > size - i)
|
||||
return AVERROR_INVALIDDATA;
|
||||
i += rlen;
|
||||
|
||||
|
||||
@@ -42,11 +42,6 @@
|
||||
#define PNG_FILTER_VALUE_PAETH 4
|
||||
#define PNG_FILTER_VALUE_MIXED 5
|
||||
|
||||
#define PNG_IHDR 0x0001
|
||||
#define PNG_IDAT 0x0002
|
||||
#define PNG_ALLIMAGE 0x0004
|
||||
#define PNG_PLTE 0x0008
|
||||
|
||||
#define NB_PASSES 7
|
||||
|
||||
#define PNGSIG 0x89504e470d0a1a0a
|
||||
|
||||
@@ -36,6 +36,16 @@
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
enum PNGHeaderState {
|
||||
PNG_IHDR = 1 << 0,
|
||||
PNG_PLTE = 1 << 1,
|
||||
};
|
||||
|
||||
enum PNGImageState {
|
||||
PNG_IDAT = 1 << 0,
|
||||
PNG_ALLIMAGE = 1 << 1,
|
||||
};
|
||||
|
||||
typedef struct PNGDecContext {
|
||||
PNGDSPContext dsp;
|
||||
AVCodecContext *avctx;
|
||||
@@ -45,7 +55,8 @@ typedef struct PNGDecContext {
|
||||
ThreadFrame last_picture;
|
||||
ThreadFrame picture;
|
||||
|
||||
int state;
|
||||
enum PNGHeaderState hdr_state;
|
||||
enum PNGImageState pic_state;
|
||||
int width, height;
|
||||
int cur_w, cur_h;
|
||||
int last_w, last_h;
|
||||
@@ -334,7 +345,7 @@ static void png_handle_row(PNGDecContext *s)
|
||||
}
|
||||
s->y++;
|
||||
if (s->y == s->cur_h) {
|
||||
s->state |= PNG_ALLIMAGE;
|
||||
s->pic_state |= PNG_ALLIMAGE;
|
||||
if (s->filter_type == PNG_FILTER_TYPE_LOCO) {
|
||||
if (s->bit_depth == 16) {
|
||||
deloco_rgb16((uint16_t *)ptr, s->row_size / 2,
|
||||
@@ -369,7 +380,7 @@ static void png_handle_row(PNGDecContext *s)
|
||||
memset(s->last_row, 0, s->row_size);
|
||||
for (;;) {
|
||||
if (s->pass == NB_PASSES - 1) {
|
||||
s->state |= PNG_ALLIMAGE;
|
||||
s->pic_state |= PNG_ALLIMAGE;
|
||||
goto the_end;
|
||||
} else {
|
||||
s->pass++;
|
||||
@@ -404,7 +415,7 @@ static int png_decode_idat(PNGDecContext *s, int length)
|
||||
return AVERROR_EXTERNAL;
|
||||
}
|
||||
if (s->zstream.avail_out == 0) {
|
||||
if (!(s->state & PNG_ALLIMAGE)) {
|
||||
if (!(s->pic_state & PNG_ALLIMAGE)) {
|
||||
png_handle_row(s);
|
||||
}
|
||||
s->zstream.avail_out = s->crow_size;
|
||||
@@ -541,12 +552,12 @@ static int decode_ihdr_chunk(AVCodecContext *avctx, PNGDecContext *s,
|
||||
if (length != 13)
|
||||
return AVERROR_INVALIDDATA;
|
||||
|
||||
if (s->state & PNG_IDAT) {
|
||||
if (s->pic_state & PNG_IDAT) {
|
||||
av_log(avctx, AV_LOG_ERROR, "IHDR after IDAT\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
if (s->state & PNG_IHDR) {
|
||||
if (s->hdr_state & PNG_IHDR) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Multiple IHDR\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
@@ -569,7 +580,7 @@ static int decode_ihdr_chunk(AVCodecContext *avctx, PNGDecContext *s,
|
||||
s->filter_type = bytestream2_get_byte(&s->gb);
|
||||
s->interlace_type = bytestream2_get_byte(&s->gb);
|
||||
bytestream2_skip(&s->gb, 4); /* crc */
|
||||
s->state |= PNG_IHDR;
|
||||
s->hdr_state |= PNG_IHDR;
|
||||
if (avctx->debug & FF_DEBUG_PICT_INFO)
|
||||
av_log(avctx, AV_LOG_DEBUG, "width=%d height=%d depth=%d color_type=%d "
|
||||
"compression_type=%d filter_type=%d interlace_type=%d\n",
|
||||
@@ -585,7 +596,7 @@ error:
|
||||
|
||||
static int decode_phys_chunk(AVCodecContext *avctx, PNGDecContext *s)
|
||||
{
|
||||
if (s->state & PNG_IDAT) {
|
||||
if (s->pic_state & PNG_IDAT) {
|
||||
av_log(avctx, AV_LOG_ERROR, "pHYs after IDAT\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
@@ -605,11 +616,11 @@ static int decode_idat_chunk(AVCodecContext *avctx, PNGDecContext *s,
|
||||
int ret;
|
||||
size_t byte_depth = s->bit_depth > 8 ? 2 : 1;
|
||||
|
||||
if (!(s->state & PNG_IHDR)) {
|
||||
if (!(s->hdr_state & PNG_IHDR)) {
|
||||
av_log(avctx, AV_LOG_ERROR, "IDAT without IHDR\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
if (!(s->state & PNG_IDAT)) {
|
||||
if (!(s->pic_state & PNG_IDAT)) {
|
||||
/* init image info */
|
||||
avctx->width = s->width;
|
||||
avctx->height = s->height;
|
||||
@@ -690,12 +701,12 @@ static int decode_idat_chunk(AVCodecContext *avctx, PNGDecContext *s,
|
||||
if ((ret = ff_thread_get_buffer(avctx, &s->previous_picture, AV_GET_BUFFER_FLAG_REF)) < 0)
|
||||
return ret;
|
||||
}
|
||||
ff_thread_finish_setup(avctx);
|
||||
|
||||
p->pict_type = AV_PICTURE_TYPE_I;
|
||||
p->key_frame = 1;
|
||||
p->interlaced_frame = !!s->interlace_type;
|
||||
|
||||
ff_thread_finish_setup(avctx);
|
||||
|
||||
/* compute the compressed row size */
|
||||
if (!s->interlace_type) {
|
||||
s->crow_size = s->row_size + 1;
|
||||
@@ -734,7 +745,7 @@ static int decode_idat_chunk(AVCodecContext *avctx, PNGDecContext *s,
|
||||
s->zstream.next_out = s->crow_buf;
|
||||
}
|
||||
|
||||
s->state |= PNG_IDAT;
|
||||
s->pic_state |= PNG_IDAT;
|
||||
|
||||
/* set image to non-transparent bpp while decompressing */
|
||||
if (s->has_trns && s->color_type != PNG_COLOR_TYPE_PALETTE)
|
||||
@@ -770,7 +781,7 @@ static int decode_plte_chunk(AVCodecContext *avctx, PNGDecContext *s,
|
||||
}
|
||||
for (; i < 256; i++)
|
||||
s->palette[i] = (0xFFU << 24);
|
||||
s->state |= PNG_PLTE;
|
||||
s->hdr_state |= PNG_PLTE;
|
||||
bytestream2_skip(&s->gb, 4); /* crc */
|
||||
|
||||
return 0;
|
||||
@@ -781,18 +792,18 @@ static int decode_trns_chunk(AVCodecContext *avctx, PNGDecContext *s,
|
||||
{
|
||||
int v, i;
|
||||
|
||||
if (!(s->state & PNG_IHDR)) {
|
||||
if (!(s->hdr_state & PNG_IHDR)) {
|
||||
av_log(avctx, AV_LOG_ERROR, "trns before IHDR\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
if (s->state & PNG_IDAT) {
|
||||
if (s->pic_state & PNG_IDAT) {
|
||||
av_log(avctx, AV_LOG_ERROR, "trns after IDAT\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
if (s->color_type == PNG_COLOR_TYPE_PALETTE) {
|
||||
if (length > 256 || !(s->state & PNG_PLTE))
|
||||
if (length > 256 || !(s->hdr_state & PNG_PLTE))
|
||||
return AVERROR_INVALIDDATA;
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
@@ -906,7 +917,7 @@ static int decode_fctl_chunk(AVCodecContext *avctx, PNGDecContext *s,
|
||||
if (length != 26)
|
||||
return AVERROR_INVALIDDATA;
|
||||
|
||||
if (!(s->state & PNG_IHDR)) {
|
||||
if (!(s->hdr_state & PNG_IHDR)) {
|
||||
av_log(avctx, AV_LOG_ERROR, "fctl before IHDR\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
@@ -1122,13 +1133,13 @@ static int decode_frame_common(AVCodecContext *avctx, PNGDecContext *s,
|
||||
}
|
||||
|
||||
if (CONFIG_APNG_DECODER && avctx->codec_id == AV_CODEC_ID_APNG && length == 0) {
|
||||
if (!(s->state & PNG_IDAT))
|
||||
if (!(s->pic_state & PNG_IDAT))
|
||||
return 0;
|
||||
else
|
||||
goto exit_loop;
|
||||
}
|
||||
av_log(avctx, AV_LOG_ERROR, "%d bytes left\n", length);
|
||||
if ( s->state & PNG_ALLIMAGE
|
||||
if ( s->pic_state & PNG_ALLIMAGE
|
||||
&& avctx->strict_std_compliance <= FF_COMPLIANCE_NORMAL)
|
||||
goto exit_loop;
|
||||
ret = AVERROR_INVALIDDATA;
|
||||
@@ -1228,9 +1239,9 @@ static int decode_frame_common(AVCodecContext *avctx, PNGDecContext *s,
|
||||
break;
|
||||
}
|
||||
case MKTAG('I', 'E', 'N', 'D'):
|
||||
if (!(s->state & PNG_ALLIMAGE))
|
||||
if (!(s->pic_state & PNG_ALLIMAGE))
|
||||
av_log(avctx, AV_LOG_ERROR, "IEND without all image\n");
|
||||
if (!(s->state & (PNG_ALLIMAGE|PNG_IDAT))) {
|
||||
if (!(s->pic_state & (PNG_ALLIMAGE|PNG_IDAT))) {
|
||||
ret = AVERROR_INVALIDDATA;
|
||||
goto fail;
|
||||
}
|
||||
@@ -1330,7 +1341,9 @@ static int decode_frame_png(AVCodecContext *avctx,
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
s->y = s->state = s->has_trns = 0;
|
||||
s->y = s->has_trns = 0;
|
||||
s->hdr_state = 0;
|
||||
s->pic_state = 0;
|
||||
|
||||
/* init the zlib */
|
||||
s->zstream.zalloc = ff_png_zalloc;
|
||||
@@ -1377,7 +1390,7 @@ static int decode_frame_apng(AVCodecContext *avctx,
|
||||
FFSWAP(ThreadFrame, s->picture, s->last_picture);
|
||||
p = s->picture.f;
|
||||
|
||||
if (!(s->state & PNG_IHDR)) {
|
||||
if (!(s->hdr_state & PNG_IHDR)) {
|
||||
if (!avctx->extradata_size)
|
||||
return AVERROR_INVALIDDATA;
|
||||
|
||||
@@ -1397,14 +1410,14 @@ static int decode_frame_apng(AVCodecContext *avctx,
|
||||
goto end;
|
||||
}
|
||||
s->y = 0;
|
||||
s->state &= ~(PNG_IDAT | PNG_ALLIMAGE);
|
||||
s->pic_state = 0;
|
||||
bytestream2_init(&s->gb, avpkt->data, avpkt->size);
|
||||
if ((ret = decode_frame_common(avctx, s, p, avpkt)) < 0)
|
||||
goto end;
|
||||
|
||||
if (!(s->state & PNG_ALLIMAGE))
|
||||
if (!(s->pic_state & PNG_ALLIMAGE))
|
||||
av_log(avctx, AV_LOG_WARNING, "Frame did not contain a complete image\n");
|
||||
if (!(s->state & (PNG_ALLIMAGE|PNG_IDAT))) {
|
||||
if (!(s->pic_state & (PNG_ALLIMAGE|PNG_IDAT))) {
|
||||
ret = AVERROR_INVALIDDATA;
|
||||
goto end;
|
||||
}
|
||||
@@ -1453,7 +1466,7 @@ static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src)
|
||||
|
||||
memcpy(pdst->palette, psrc->palette, sizeof(pdst->palette));
|
||||
|
||||
pdst->state |= psrc->state & (PNG_IHDR | PNG_PLTE);
|
||||
pdst->hdr_state |= psrc->hdr_state;
|
||||
|
||||
ff_thread_release_buffer(dst, &pdst->last_picture);
|
||||
if (psrc->last_picture.f->data[0] &&
|
||||
|
||||
@@ -380,7 +380,8 @@ static void release_delayed_buffers(PerThreadContext *p)
|
||||
}
|
||||
}
|
||||
|
||||
static int submit_packet(PerThreadContext *p, AVPacket *avpkt)
|
||||
static int submit_packet(PerThreadContext *p, AVCodecContext *user_avctx,
|
||||
AVPacket *avpkt)
|
||||
{
|
||||
FrameThreadContext *fctx = p->parent;
|
||||
PerThreadContext *prev_thread = fctx->prev_thread;
|
||||
@@ -392,6 +393,12 @@ static int submit_packet(PerThreadContext *p, AVPacket *avpkt)
|
||||
|
||||
pthread_mutex_lock(&p->mutex);
|
||||
|
||||
ret = update_context_from_user(p->avctx, user_avctx);
|
||||
if (ret) {
|
||||
pthread_mutex_unlock(&p->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
release_delayed_buffers(p);
|
||||
|
||||
if (prev_thread) {
|
||||
@@ -480,10 +487,7 @@ int ff_thread_decode_frame(AVCodecContext *avctx,
|
||||
*/
|
||||
|
||||
p = &fctx->threads[fctx->next_decoding];
|
||||
err = update_context_from_user(p->avctx, avctx);
|
||||
if (err)
|
||||
goto finish;
|
||||
err = submit_packet(p, avpkt);
|
||||
err = submit_packet(p, avctx, avpkt);
|
||||
if (err)
|
||||
goto finish;
|
||||
|
||||
@@ -560,12 +564,12 @@ void ff_thread_report_progress(ThreadFrame *f, int n, int field)
|
||||
atomic_load_explicit(&progress[field], memory_order_relaxed) >= n)
|
||||
return;
|
||||
|
||||
p = f->owner->internal->thread_ctx;
|
||||
|
||||
if (f->owner->debug&FF_DEBUG_THREADS)
|
||||
av_log(f->owner, AV_LOG_DEBUG, "%p finished %d field %d\n", progress, n, field);
|
||||
p = f->owner[field]->internal->thread_ctx;
|
||||
|
||||
pthread_mutex_lock(&p->progress_mutex);
|
||||
if (f->owner[field]->debug&FF_DEBUG_THREADS)
|
||||
av_log(f->owner[field], AV_LOG_DEBUG,
|
||||
"%p finished %d field %d\n", progress, n, field);
|
||||
|
||||
atomic_store_explicit(&progress[field], n, memory_order_release);
|
||||
|
||||
@@ -582,12 +586,12 @@ void ff_thread_await_progress(ThreadFrame *f, int n, int field)
|
||||
atomic_load_explicit(&progress[field], memory_order_acquire) >= n)
|
||||
return;
|
||||
|
||||
p = f->owner->internal->thread_ctx;
|
||||
|
||||
if (f->owner->debug&FF_DEBUG_THREADS)
|
||||
av_log(f->owner, AV_LOG_DEBUG, "thread awaiting %d field %d from %p\n", n, field, progress);
|
||||
p = f->owner[field]->internal->thread_ctx;
|
||||
|
||||
pthread_mutex_lock(&p->progress_mutex);
|
||||
if (f->owner[field]->debug&FF_DEBUG_THREADS)
|
||||
av_log(f->owner[field], AV_LOG_DEBUG,
|
||||
"thread awaiting %d field %d from %p\n", n, field, progress);
|
||||
while (atomic_load_explicit(&progress[field], memory_order_relaxed) < n)
|
||||
pthread_cond_wait(&p->progress_cond, &p->progress_mutex);
|
||||
pthread_mutex_unlock(&p->progress_mutex);
|
||||
@@ -878,7 +882,7 @@ static int thread_get_buffer_internal(AVCodecContext *avctx, ThreadFrame *f, int
|
||||
PerThreadContext *p = avctx->internal->thread_ctx;
|
||||
int err;
|
||||
|
||||
f->owner = avctx;
|
||||
f->owner[0] = f->owner[1] = avctx;
|
||||
|
||||
ff_init_buffer_info(avctx, f->f);
|
||||
|
||||
@@ -982,7 +986,7 @@ void ff_thread_release_buffer(AVCodecContext *avctx, ThreadFrame *f)
|
||||
av_log(avctx, AV_LOG_DEBUG, "thread_release_buffer called on pic %p\n", f);
|
||||
|
||||
av_buffer_unref(&f->progress);
|
||||
f->owner = NULL;
|
||||
f->owner[0] = f->owner[1] = NULL;
|
||||
|
||||
if (can_direct_free) {
|
||||
av_frame_unref(f->f);
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
|
||||
typedef struct ThreadFrame {
|
||||
AVFrame *f;
|
||||
AVCodecContext *owner;
|
||||
AVCodecContext *owner[2];
|
||||
// progress->data is an array of 2 ints holding progress for top/bottom
|
||||
// fields
|
||||
AVBufferRef *progress;
|
||||
|
||||
@@ -3971,7 +3971,8 @@ int ff_thread_ref_frame(ThreadFrame *dst, ThreadFrame *src)
|
||||
{
|
||||
int ret;
|
||||
|
||||
dst->owner = src->owner;
|
||||
dst->owner[0] = src->owner[0];
|
||||
dst->owner[1] = src->owner[1];
|
||||
|
||||
ret = av_frame_ref(dst->f, src->f);
|
||||
if (ret < 0)
|
||||
@@ -3981,7 +3982,7 @@ int ff_thread_ref_frame(ThreadFrame *dst, ThreadFrame *src)
|
||||
|
||||
if (src->progress &&
|
||||
!(dst->progress = av_buffer_ref(src->progress))) {
|
||||
ff_thread_release_buffer(dst->owner, dst);
|
||||
ff_thread_release_buffer(dst->owner[0], dst);
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
|
||||
@@ -3997,7 +3998,7 @@ enum AVPixelFormat ff_thread_get_format(AVCodecContext *avctx, const enum AVPixe
|
||||
|
||||
int ff_thread_get_buffer(AVCodecContext *avctx, ThreadFrame *f, int flags)
|
||||
{
|
||||
f->owner = avctx;
|
||||
f->owner[0] = f->owner[1] = avctx;
|
||||
return ff_get_buffer(avctx, f->f, flags);
|
||||
}
|
||||
|
||||
|
||||
@@ -772,7 +772,7 @@ static int vp8_decode_frame_header(VP8Context *s, const uint8_t *buf, int buf_si
|
||||
}
|
||||
|
||||
static av_always_inline
|
||||
void clamp_mv(VP8Context *s, VP56mv *dst, const VP56mv *src)
|
||||
void clamp_mv(VP8mvbounds *s, VP56mv *dst, const VP56mv *src)
|
||||
{
|
||||
dst->x = av_clip(src->x, av_clip(s->mv_min.x, INT16_MIN, INT16_MAX),
|
||||
av_clip(s->mv_max.x, INT16_MIN, INT16_MAX));
|
||||
@@ -1031,7 +1031,7 @@ void vp7_decode_mvs(VP8Context *s, VP8Macroblock *mb,
|
||||
}
|
||||
|
||||
static av_always_inline
|
||||
void vp8_decode_mvs(VP8Context *s, VP8Macroblock *mb,
|
||||
void vp8_decode_mvs(VP8Context *s, VP8mvbounds *mv_bounds, VP8Macroblock *mb,
|
||||
int mb_x, int mb_y, int layout)
|
||||
{
|
||||
VP8Macroblock *mb_edge[3] = { 0 /* top */,
|
||||
@@ -1102,7 +1102,7 @@ void vp8_decode_mvs(VP8Context *s, VP8Macroblock *mb,
|
||||
if (vp56_rac_get_prob_branchy(c, vp8_mode_contexts[cnt[CNT_NEAREST]][1])) {
|
||||
if (vp56_rac_get_prob_branchy(c, vp8_mode_contexts[cnt[CNT_NEAR]][2])) {
|
||||
/* Choose the best mv out of 0,0 and the nearest mv */
|
||||
clamp_mv(s, &mb->mv, &near_mv[CNT_ZERO + (cnt[CNT_NEAREST] >= cnt[CNT_ZERO])]);
|
||||
clamp_mv(mv_bounds, &mb->mv, &near_mv[CNT_ZERO + (cnt[CNT_NEAREST] >= cnt[CNT_ZERO])]);
|
||||
cnt[CNT_SPLITMV] = ((mb_edge[VP8_EDGE_LEFT]->mode == VP8_MVMODE_SPLIT) +
|
||||
(mb_edge[VP8_EDGE_TOP]->mode == VP8_MVMODE_SPLIT)) * 2 +
|
||||
(mb_edge[VP8_EDGE_TOPLEFT]->mode == VP8_MVMODE_SPLIT);
|
||||
@@ -1116,11 +1116,11 @@ void vp8_decode_mvs(VP8Context *s, VP8Macroblock *mb,
|
||||
mb->bmv[0] = mb->mv;
|
||||
}
|
||||
} else {
|
||||
clamp_mv(s, &mb->mv, &near_mv[CNT_NEAR]);
|
||||
clamp_mv(mv_bounds, &mb->mv, &near_mv[CNT_NEAR]);
|
||||
mb->bmv[0] = mb->mv;
|
||||
}
|
||||
} else {
|
||||
clamp_mv(s, &mb->mv, &near_mv[CNT_NEAREST]);
|
||||
clamp_mv(mv_bounds, &mb->mv, &near_mv[CNT_NEAREST]);
|
||||
mb->bmv[0] = mb->mv;
|
||||
}
|
||||
} else {
|
||||
@@ -1166,7 +1166,8 @@ void decode_intra4x4_modes(VP8Context *s, VP56RangeCoder *c, VP8Macroblock *mb,
|
||||
}
|
||||
|
||||
static av_always_inline
|
||||
void decode_mb_mode(VP8Context *s, VP8Macroblock *mb, int mb_x, int mb_y,
|
||||
void decode_mb_mode(VP8Context *s, VP8mvbounds *mv_bounds,
|
||||
VP8Macroblock *mb, int mb_x, int mb_y,
|
||||
uint8_t *segment, uint8_t *ref, int layout, int is_vp7)
|
||||
{
|
||||
VP56RangeCoder *c = &s->c;
|
||||
@@ -1230,7 +1231,7 @@ void decode_mb_mode(VP8Context *s, VP8Macroblock *mb, int mb_x, int mb_y,
|
||||
if (is_vp7)
|
||||
vp7_decode_mvs(s, mb, mb_x, mb_y, layout);
|
||||
else
|
||||
vp8_decode_mvs(s, mb, mb_x, mb_y, layout);
|
||||
vp8_decode_mvs(s, mv_bounds, mb, mb_x, mb_y, layout);
|
||||
} else {
|
||||
// intra MB, 16.1
|
||||
mb->mode = vp8_rac_get_tree(c, vp8_pred16x16_tree_inter, s->prob->pred16x16);
|
||||
@@ -2205,8 +2206,8 @@ void vp78_decode_mv_mb_modes(AVCodecContext *avctx, VP8Frame *curframe,
|
||||
VP8Context *s = avctx->priv_data;
|
||||
int mb_x, mb_y;
|
||||
|
||||
s->mv_min.y = -MARGIN;
|
||||
s->mv_max.y = ((s->mb_height - 1) << 6) + MARGIN;
|
||||
s->mv_bounds.mv_min.y = -MARGIN;
|
||||
s->mv_bounds.mv_max.y = ((s->mb_height - 1) << 6) + MARGIN;
|
||||
for (mb_y = 0; mb_y < s->mb_height; mb_y++) {
|
||||
VP8Macroblock *mb = s->macroblocks_base +
|
||||
((s->mb_width + 1) * (mb_y + 1) + 1);
|
||||
@@ -2214,20 +2215,20 @@ void vp78_decode_mv_mb_modes(AVCodecContext *avctx, VP8Frame *curframe,
|
||||
|
||||
AV_WN32A(s->intra4x4_pred_mode_left, DC_PRED * 0x01010101);
|
||||
|
||||
s->mv_min.x = -MARGIN;
|
||||
s->mv_max.x = ((s->mb_width - 1) << 6) + MARGIN;
|
||||
s->mv_bounds.mv_min.x = -MARGIN;
|
||||
s->mv_bounds.mv_max.x = ((s->mb_width - 1) << 6) + MARGIN;
|
||||
for (mb_x = 0; mb_x < s->mb_width; mb_x++, mb_xy++, mb++) {
|
||||
if (mb_y == 0)
|
||||
AV_WN32A((mb - s->mb_width - 1)->intra4x4_pred_mode_top,
|
||||
DC_PRED * 0x01010101);
|
||||
decode_mb_mode(s, mb, mb_x, mb_y, curframe->seg_map->data + mb_xy,
|
||||
decode_mb_mode(s, &s->mv_bounds, mb, mb_x, mb_y, curframe->seg_map->data + mb_xy,
|
||||
prev_frame && prev_frame->seg_map ?
|
||||
prev_frame->seg_map->data + mb_xy : NULL, 1, is_vp7);
|
||||
s->mv_min.x -= 64;
|
||||
s->mv_max.x -= 64;
|
||||
s->mv_bounds.mv_min.x -= 64;
|
||||
s->mv_bounds.mv_max.x -= 64;
|
||||
}
|
||||
s->mv_min.y -= 64;
|
||||
s->mv_max.y -= 64;
|
||||
s->mv_bounds.mv_min.y -= 64;
|
||||
s->mv_bounds.mv_max.y -= 64;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2247,15 +2248,15 @@ static void vp8_decode_mv_mb_modes(AVCodecContext *avctx, VP8Frame *cur_frame,
|
||||
#define check_thread_pos(td, otd, mb_x_check, mb_y_check) \
|
||||
do { \
|
||||
int tmp = (mb_y_check << 16) | (mb_x_check & 0xFFFF); \
|
||||
if (otd->thread_mb_pos < tmp) { \
|
||||
if (atomic_load(&otd->thread_mb_pos) < tmp) { \
|
||||
pthread_mutex_lock(&otd->lock); \
|
||||
td->wait_mb_pos = tmp; \
|
||||
atomic_store(&td->wait_mb_pos, tmp); \
|
||||
do { \
|
||||
if (otd->thread_mb_pos >= tmp) \
|
||||
if (atomic_load(&otd->thread_mb_pos) >= tmp) \
|
||||
break; \
|
||||
pthread_cond_wait(&otd->cond, &otd->lock); \
|
||||
} while (1); \
|
||||
td->wait_mb_pos = INT_MAX; \
|
||||
atomic_store(&td->wait_mb_pos, INT_MAX); \
|
||||
pthread_mutex_unlock(&otd->lock); \
|
||||
} \
|
||||
} while (0)
|
||||
@@ -2266,12 +2267,10 @@ static void vp8_decode_mv_mb_modes(AVCodecContext *avctx, VP8Frame *cur_frame,
|
||||
int sliced_threading = (avctx->active_thread_type == FF_THREAD_SLICE) && \
|
||||
(num_jobs > 1); \
|
||||
int is_null = !next_td || !prev_td; \
|
||||
int pos_check = (is_null) ? 1 \
|
||||
: (next_td != td && \
|
||||
pos >= next_td->wait_mb_pos) || \
|
||||
(prev_td != td && \
|
||||
pos >= prev_td->wait_mb_pos); \
|
||||
td->thread_mb_pos = pos; \
|
||||
int pos_check = (is_null) ? 1 : \
|
||||
(next_td != td && pos >= atomic_load(&next_td->wait_mb_pos)) || \
|
||||
(prev_td != td && pos >= atomic_load(&prev_td->wait_mb_pos)); \
|
||||
atomic_store(&td->thread_mb_pos, pos); \
|
||||
if (sliced_threading && pos_check) { \
|
||||
pthread_mutex_lock(&td->lock); \
|
||||
pthread_cond_broadcast(&td->cond); \
|
||||
@@ -2288,7 +2287,7 @@ static av_always_inline int decode_mb_row_no_filter(AVCodecContext *avctx, void
|
||||
{
|
||||
VP8Context *s = avctx->priv_data;
|
||||
VP8ThreadData *prev_td, *next_td, *td = &s->thread_data[threadnr];
|
||||
int mb_y = td->thread_mb_pos >> 16;
|
||||
int mb_y = atomic_load(&td->thread_mb_pos) >> 16;
|
||||
int mb_x, mb_xy = mb_y * s->mb_width;
|
||||
int num_jobs = s->num_jobs;
|
||||
VP8Frame *curframe = s->curframe, *prev_frame = s->prev_frame;
|
||||
@@ -2327,8 +2326,8 @@ static av_always_inline int decode_mb_row_no_filter(AVCodecContext *avctx, void
|
||||
if (!is_vp7 || mb_y == 0)
|
||||
memset(td->left_nnz, 0, sizeof(td->left_nnz));
|
||||
|
||||
s->mv_min.x = -MARGIN;
|
||||
s->mv_max.x = ((s->mb_width - 1) << 6) + MARGIN;
|
||||
td->mv_bounds.mv_min.x = -MARGIN;
|
||||
td->mv_bounds.mv_max.x = ((s->mb_width - 1) << 6) + MARGIN;
|
||||
|
||||
for (mb_x = 0; mb_x < s->mb_width; mb_x++, mb_xy++, mb++) {
|
||||
if (c->end <= c->buffer && c->bits >= 0)
|
||||
@@ -2352,7 +2351,7 @@ static av_always_inline int decode_mb_row_no_filter(AVCodecContext *avctx, void
|
||||
dst[2] - dst[1], 2);
|
||||
|
||||
if (!s->mb_layout)
|
||||
decode_mb_mode(s, mb, mb_x, mb_y, curframe->seg_map->data + mb_xy,
|
||||
decode_mb_mode(s, &td->mv_bounds, mb, mb_x, mb_y, curframe->seg_map->data + mb_xy,
|
||||
prev_frame && prev_frame->seg_map ?
|
||||
prev_frame->seg_map->data + mb_xy : NULL, 0, is_vp7);
|
||||
|
||||
@@ -2399,8 +2398,8 @@ static av_always_inline int decode_mb_row_no_filter(AVCodecContext *avctx, void
|
||||
dst[0] += 16;
|
||||
dst[1] += 8;
|
||||
dst[2] += 8;
|
||||
s->mv_min.x -= 64;
|
||||
s->mv_max.x -= 64;
|
||||
td->mv_bounds.mv_min.x -= 64;
|
||||
td->mv_bounds.mv_max.x -= 64;
|
||||
|
||||
if (mb_x == s->mb_width + 1) {
|
||||
update_pos(td, mb_y, s->mb_width + 3);
|
||||
@@ -2428,7 +2427,7 @@ static av_always_inline void filter_mb_row(AVCodecContext *avctx, void *tdata,
|
||||
{
|
||||
VP8Context *s = avctx->priv_data;
|
||||
VP8ThreadData *td = &s->thread_data[threadnr];
|
||||
int mb_x, mb_y = td->thread_mb_pos >> 16, num_jobs = s->num_jobs;
|
||||
int mb_x, mb_y = atomic_load(&td->thread_mb_pos) >> 16, num_jobs = s->num_jobs;
|
||||
AVFrame *curframe = s->curframe->tf.f;
|
||||
VP8Macroblock *mb;
|
||||
VP8ThreadData *prev_td, *next_td;
|
||||
@@ -2506,8 +2505,10 @@ int vp78_decode_mb_row_sliced(AVCodecContext *avctx, void *tdata, int jobnr,
|
||||
int ret;
|
||||
|
||||
td->thread_nr = threadnr;
|
||||
td->mv_bounds.mv_min.y = -MARGIN - 64 * threadnr;
|
||||
td->mv_bounds.mv_max.y = ((s->mb_height - 1) << 6) + MARGIN - 64 * threadnr;
|
||||
for (mb_y = jobnr; mb_y < s->mb_height; mb_y += num_jobs) {
|
||||
td->thread_mb_pos = mb_y << 16;
|
||||
atomic_store(&td->thread_mb_pos, mb_y << 16);
|
||||
ret = s->decode_mb_row_no_filter(avctx, tdata, jobnr, threadnr);
|
||||
if (ret < 0) {
|
||||
update_pos(td, s->mb_height, INT_MAX & 0xFFFF);
|
||||
@@ -2517,8 +2518,8 @@ int vp78_decode_mb_row_sliced(AVCodecContext *avctx, void *tdata, int jobnr,
|
||||
s->filter_mb_row(avctx, tdata, jobnr, threadnr);
|
||||
update_pos(td, mb_y, INT_MAX & 0xFFFF);
|
||||
|
||||
s->mv_min.y -= 64;
|
||||
s->mv_max.y -= 64;
|
||||
td->mv_bounds.mv_min.y -= 64 * num_jobs;
|
||||
td->mv_bounds.mv_max.y -= 64 * num_jobs;
|
||||
|
||||
if (avctx->active_thread_type == FF_THREAD_FRAME)
|
||||
ff_thread_report_progress(&curframe->tf, mb_y, 0);
|
||||
@@ -2664,11 +2665,12 @@ int vp78_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
|
||||
s->num_jobs = num_jobs;
|
||||
s->curframe = curframe;
|
||||
s->prev_frame = prev_frame;
|
||||
s->mv_min.y = -MARGIN;
|
||||
s->mv_max.y = ((s->mb_height - 1) << 6) + MARGIN;
|
||||
s->mv_bounds.mv_min.y = -MARGIN;
|
||||
s->mv_bounds.mv_max.y = ((s->mb_height - 1) << 6) + MARGIN;
|
||||
for (i = 0; i < MAX_THREADS; i++) {
|
||||
s->thread_data[i].thread_mb_pos = 0;
|
||||
s->thread_data[i].wait_mb_pos = INT_MAX;
|
||||
VP8ThreadData *td = &s->thread_data[i];
|
||||
atomic_init(&td->thread_mb_pos, 0);
|
||||
atomic_init(&td->wait_mb_pos, INT_MAX);
|
||||
}
|
||||
if (is_vp7)
|
||||
avctx->execute2(avctx, vp7_decode_mb_row_sliced, s->thread_data, NULL,
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
#ifndef AVCODEC_VP8_H
|
||||
#define AVCODEC_VP8_H
|
||||
|
||||
#include <stdatomic.h>
|
||||
|
||||
#include "libavutil/buffer.h"
|
||||
#include "libavutil/thread.h"
|
||||
|
||||
@@ -91,6 +93,16 @@ typedef struct VP8Macroblock {
|
||||
VP56mv bmv[16];
|
||||
} VP8Macroblock;
|
||||
|
||||
typedef struct VP8intmv {
|
||||
int x;
|
||||
int y;
|
||||
} VP8intmv;
|
||||
|
||||
typedef struct VP8mvbounds {
|
||||
VP8intmv mv_min;
|
||||
VP8intmv mv_max;
|
||||
} VP8mvbounds;
|
||||
|
||||
typedef struct VP8ThreadData {
|
||||
DECLARE_ALIGNED(16, int16_t, block)[6][4][16];
|
||||
DECLARE_ALIGNED(16, int16_t, block_dc)[16];
|
||||
@@ -114,12 +126,13 @@ typedef struct VP8ThreadData {
|
||||
pthread_mutex_t lock;
|
||||
pthread_cond_t cond;
|
||||
#endif
|
||||
int thread_mb_pos; // (mb_y << 16) | (mb_x & 0xFFFF)
|
||||
int wait_mb_pos; // What the current thread is waiting on.
|
||||
atomic_int thread_mb_pos; // (mb_y << 16) | (mb_x & 0xFFFF)
|
||||
atomic_int wait_mb_pos; // What the current thread is waiting on.
|
||||
|
||||
#define EDGE_EMU_LINESIZE 32
|
||||
DECLARE_ALIGNED(16, uint8_t, edge_emu_buffer)[21 * EDGE_EMU_LINESIZE];
|
||||
VP8FilterStrength *filter_strength;
|
||||
VP8mvbounds mv_bounds;
|
||||
} VP8ThreadData;
|
||||
|
||||
typedef struct VP8Frame {
|
||||
@@ -127,11 +140,6 @@ typedef struct VP8Frame {
|
||||
AVBufferRef *seg_map;
|
||||
} VP8Frame;
|
||||
|
||||
typedef struct VP8intmv {
|
||||
int x;
|
||||
int y;
|
||||
} VP8intmv;
|
||||
|
||||
#define MAX_THREADS 8
|
||||
typedef struct VP8Context {
|
||||
VP8ThreadData *thread_data;
|
||||
@@ -150,8 +158,7 @@ typedef struct VP8Context {
|
||||
uint8_t deblock_filter;
|
||||
uint8_t mbskip_enabled;
|
||||
uint8_t profile;
|
||||
VP8intmv mv_min;
|
||||
VP8intmv mv_max;
|
||||
VP8mvbounds mv_bounds;
|
||||
|
||||
int8_t sign_bias[4]; ///< one state [0, 1] per ref frame type
|
||||
int ref_count[3];
|
||||
|
||||
@@ -440,7 +440,7 @@ copy_done:
|
||||
s->pending_end_frame = 0;
|
||||
s->last_dest_frame_pts = s->work->pts;
|
||||
|
||||
return ff_filter_frame(ctx->outputs[0], s->work);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void set_srce_frame_dest_pts(AVFilterContext *ctx)
|
||||
@@ -586,6 +586,7 @@ static int config_input(AVFilterLink *inlink)
|
||||
|
||||
static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref)
|
||||
{
|
||||
int ret;
|
||||
AVFilterContext *ctx = inlink->dst;
|
||||
FrameRateContext *s = ctx->priv;
|
||||
|
||||
@@ -606,7 +607,10 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref)
|
||||
set_srce_frame_dest_pts(ctx);
|
||||
}
|
||||
|
||||
return process_work_frame(ctx, 1);
|
||||
ret = process_work_frame(ctx, 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
return ret ? ff_filter_frame(ctx->outputs[0], s->work) : 0;
|
||||
}
|
||||
|
||||
static int config_output(AVFilterLink *outlink)
|
||||
@@ -658,23 +662,13 @@ static int request_frame(AVFilterLink *outlink)
|
||||
{
|
||||
AVFilterContext *ctx = outlink->src;
|
||||
FrameRateContext *s = ctx->priv;
|
||||
int val, i;
|
||||
int ret, i;
|
||||
|
||||
ff_dlog(ctx, "request_frame()\n");
|
||||
|
||||
// if there is no "next" frame AND we are not in flush then get one from our input filter
|
||||
if (!s->srce[s->frst] && !s->flush) {
|
||||
ff_dlog(ctx, "request_frame() call source's request_frame()\n");
|
||||
val = ff_request_frame(outlink->src->inputs[0]);
|
||||
if (val < 0 && (val != AVERROR_EOF)) {
|
||||
ff_dlog(ctx, "request_frame() source's request_frame() returned error:%d\n", val);
|
||||
return val;
|
||||
} else if (val == AVERROR_EOF) {
|
||||
s->flush = 1;
|
||||
}
|
||||
ff_dlog(ctx, "request_frame() source's request_frame() returned:%d\n", val);
|
||||
return 0;
|
||||
}
|
||||
if (!s->srce[s->frst] && !s->flush)
|
||||
goto request;
|
||||
|
||||
ff_dlog(ctx, "request_frame() REPEAT or FLUSH\n");
|
||||
|
||||
@@ -695,7 +689,23 @@ static int request_frame(AVFilterLink *outlink)
|
||||
}
|
||||
|
||||
set_work_frame_pts(ctx);
|
||||
return process_work_frame(ctx, 0);
|
||||
ret = process_work_frame(ctx, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (ret)
|
||||
return ff_filter_frame(ctx->outputs[0], s->work);
|
||||
|
||||
request:
|
||||
ff_dlog(ctx, "request_frame() call source's request_frame()\n");
|
||||
ret = ff_request_frame(ctx->inputs[0]);
|
||||
if (ret < 0 && (ret != AVERROR_EOF)) {
|
||||
ff_dlog(ctx, "request_frame() source's request_frame() returned error:%d\n", ret);
|
||||
return ret;
|
||||
} else if (ret == AVERROR_EOF) {
|
||||
s->flush = 1;
|
||||
}
|
||||
ff_dlog(ctx, "request_frame() source's request_frame() returned:%d\n", ret);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const AVFilterPad framerate_inputs[] = {
|
||||
|
||||
@@ -2223,7 +2223,7 @@ static int mkv_check_new_extra_data(AVFormatContext *s, AVPacket *pkt)
|
||||
|
||||
switch (par->codec_id) {
|
||||
case AV_CODEC_ID_FLAC:
|
||||
if (side_data_size && (s->pb->seekable & AVIO_SEEKABLE_NORMAL)) {
|
||||
if (side_data_size && (s->pb->seekable & AVIO_SEEKABLE_NORMAL) && !mkv->is_live) {
|
||||
AVCodecParameters *codecpriv_par;
|
||||
int64_t curpos;
|
||||
if (side_data_size != par->extradata_size) {
|
||||
|
||||
@@ -1186,6 +1186,12 @@ static void mov_metadata_creation_time(AVDictionary **metadata, int64_t time)
|
||||
if (time) {
|
||||
if(time >= 2082844800)
|
||||
time -= 2082844800; /* seconds between 1904-01-01 and Epoch */
|
||||
|
||||
if ((int64_t)(time * 1000000ULL) / 1000000 != time) {
|
||||
av_log(NULL, AV_LOG_DEBUG, "creation_time is not representable\n");
|
||||
return;
|
||||
}
|
||||
|
||||
avpriv_dict_set_timestamp(metadata, "creation_time", time * 1000000);
|
||||
}
|
||||
}
|
||||
@@ -5788,6 +5794,7 @@ static int mov_read_close(AVFormatContext *s)
|
||||
av_freep(&mov->fragment_index_data);
|
||||
|
||||
av_freep(&mov->aes_decrypt);
|
||||
av_freep(&mov->chapter_tracks);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -6352,6 +6352,8 @@ static int mov_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt)
|
||||
if (st->codecpar->codec_id == AV_CODEC_ID_AAC) {
|
||||
if (pkt->size > 2 && (AV_RB16(pkt->data) & 0xfff0) == 0xfff0)
|
||||
ret = ff_stream_add_bitstream_filter(st, "aac_adtstoasc", NULL);
|
||||
} else if (st->codecpar->codec_id == AV_CODEC_ID_VP9) {
|
||||
ret = ff_stream_add_bitstream_filter(st, "vp9_superframe", NULL);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -108,7 +108,10 @@ ogm_header(AVFormatContext *s, int idx)
|
||||
if (size > 52) {
|
||||
av_assert0(AV_INPUT_BUFFER_PADDING_SIZE <= 52);
|
||||
size -= 52;
|
||||
ff_alloc_extradata(st->codecpar, size);
|
||||
if (bytestream2_get_bytes_left(&p) < size)
|
||||
return AVERROR_INVALIDDATA;
|
||||
if (ff_alloc_extradata(st->codecpar, size) < 0)
|
||||
return AVERROR(ENOMEM);
|
||||
bytestream2_get_buffer(&p, st->codecpar->extradata, st->codecpar->extradata_size);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -231,83 +231,6 @@ int av_strncasecmp(const char *a, const char *b, size_t n)
|
||||
return c1 - c2;
|
||||
}
|
||||
|
||||
char *av_strreplace(const char *str, const char *from, const char *to)
|
||||
{
|
||||
/* Adjust each of the below values to suit your needs. */
|
||||
/* Increment positions cache size initially by this number. */
|
||||
size_t cache_sz_inc = 16;
|
||||
/* Thereafter, each time capacity needs to be increased,
|
||||
* multiply the increment by this factor. */
|
||||
const size_t cache_sz_inc_factor = 3;
|
||||
/* But never increment capacity by more than this number. */
|
||||
const size_t cache_sz_inc_max = 1048576;
|
||||
|
||||
char *pret, *ret = NULL;
|
||||
const char *pstr2, *pstr = str;
|
||||
size_t i, count = 0;
|
||||
uintptr_t *pos_cache_tmp, *pos_cache = NULL;
|
||||
size_t cache_sz = 0;
|
||||
size_t cpylen, orglen, retlen, tolen, fromlen = strlen(from);
|
||||
|
||||
/* Find all matches and cache their positions. */
|
||||
while ((pstr2 = av_stristr(pstr, from))) {
|
||||
count++;
|
||||
/* Increase the cache size when necessary. */
|
||||
if (cache_sz < count) {
|
||||
cache_sz += cache_sz_inc;
|
||||
pos_cache_tmp = av_realloc(pos_cache, sizeof(*pos_cache) * cache_sz);
|
||||
if (!pos_cache_tmp) {
|
||||
goto end_strreplace;
|
||||
} else pos_cache = pos_cache_tmp;
|
||||
cache_sz_inc *= cache_sz_inc_factor;
|
||||
if (cache_sz_inc > cache_sz_inc_max) {
|
||||
cache_sz_inc = cache_sz_inc_max;
|
||||
}
|
||||
}
|
||||
|
||||
pos_cache[count-1] = pstr2 - str;
|
||||
pstr = pstr2 + fromlen;
|
||||
}
|
||||
orglen = pstr - str + strlen(pstr);
|
||||
/* Allocate memory for the post-replacement string. */
|
||||
if (count > 0) {
|
||||
tolen = strlen(to);
|
||||
retlen = orglen + (tolen - fromlen) * count;
|
||||
} else {
|
||||
retlen = orglen;
|
||||
}
|
||||
ret = av_malloc(retlen + 1);
|
||||
if (!ret) {
|
||||
goto end_strreplace;
|
||||
}
|
||||
|
||||
if (!count) {
|
||||
/* If no matches, then just duplicate the string. */
|
||||
av_strlcpy(ret, str, retlen + 1);
|
||||
} else {
|
||||
/* Otherwise, duplicate the string whilst performing
|
||||
* the replacements using the position cache. */
|
||||
pret = ret;
|
||||
memcpy(pret, str, pos_cache[0]);
|
||||
pret += pos_cache[0];
|
||||
for (i = 0; i < count; i++) {
|
||||
memcpy(pret, to, tolen);
|
||||
pret += tolen;
|
||||
pstr = str + pos_cache[i] + fromlen;
|
||||
cpylen = (i == count-1 ? orglen : pos_cache[i+1]) - pos_cache[i] - fromlen;
|
||||
memcpy(pret, pstr, cpylen);
|
||||
pret += cpylen;
|
||||
}
|
||||
ret[retlen] = '\0';
|
||||
}
|
||||
|
||||
end_strreplace:
|
||||
/* Free the cache and return the post-replacement string,
|
||||
* which will be NULL in the event of an error. */
|
||||
av_free(pos_cache);
|
||||
return ret;
|
||||
}
|
||||
|
||||
const char *av_basename(const char *path)
|
||||
{
|
||||
char *p = strrchr(path, '/');
|
||||
|
||||
@@ -266,11 +266,6 @@ int av_strcasecmp(const char *a, const char *b);
|
||||
*/
|
||||
int av_strncasecmp(const char *a, const char *b, size_t n);
|
||||
|
||||
/**
|
||||
* Locale-independent strings replace.
|
||||
* @note This means only ASCII-range characters are replace
|
||||
*/
|
||||
char *av_strreplace(const char *str, const char *from, const char *to);
|
||||
|
||||
/**
|
||||
* Thread safe basename.
|
||||
|
||||
@@ -78,7 +78,7 @@ fate-filter-lavd-scalenorm: tests/data/filtergraphs/scalenorm
|
||||
fate-filter-lavd-scalenorm: CMD = framecrc -f lavfi -graph_file $(TARGET_PATH)/tests/data/filtergraphs/scalenorm -i dummy
|
||||
|
||||
|
||||
FATE_FILTER-$(call ALLYES FRAMERATE_FILTER TESTSRC2_FILTER) += fate-filter-framerate-up fate-filter-framerate-down
|
||||
FATE_FILTER-$(call ALLYES, FRAMERATE_FILTER TESTSRC2_FILTER) += fate-filter-framerate-up fate-filter-framerate-down
|
||||
fate-filter-framerate-up: CMD = framecrc -lavfi testsrc2=r=2:d=10,framerate=fps=10 -t 1
|
||||
fate-filter-framerate-down: CMD = framecrc -lavfi testsrc2=r=2:d=10,framerate=fps=1 -t 1
|
||||
|
||||
|
||||
Reference in New Issue
Block a user