Compare commits
141 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| dc91b913b6 | |||
| aeba1a4c20 | |||
| d22550dd61 | |||
| 2a7f1bc282 | |||
| 25e794a1ea | |||
| d622923b36 | |||
| c64180fac8 | |||
| 8ee432dc23 | |||
| 5f21bbed8a | |||
| 53ecdbfbe5 | |||
| 5c457c673f | |||
| fb7cd45977 | |||
| 44d218e99a | |||
| be5970fcaa | |||
| c72fca598c | |||
| b0997b8526 | |||
| 4562719c7d | |||
| 6d7dfabfb0 | |||
| 63277aa98e | |||
| 0155d5cd74 | |||
| ed7efbe3ab | |||
| 6aad0b1bb5 | |||
| 5621d10b7a | |||
| 1761cc0cb0 | |||
| 562ff3ee0e | |||
| aa8f8748ca | |||
| 0401246845 | |||
| 76b5f726aa | |||
| 6a7a39878f | |||
| a80b0ee981 | |||
| de40b2fe41 | |||
| 4aeedf4c2a | |||
| 95aacf30e3 | |||
| 6bc2058d00 | |||
| 54dd729cee | |||
| 1f3735892b | |||
| edbc26e38b | |||
| 8bc3cdf007 | |||
| 639c60f5aa | |||
| 0fe3383066 | |||
| eff72f86e2 | |||
| 632262f184 | |||
| 236ddfbe1c | |||
| affb55d4b4 | |||
| 60433ae94f | |||
| 82b9da7662 | |||
| 0ccd2540b0 | |||
| 7f139498f5 | |||
| b51d5b222e | |||
| 70028ce7fd | |||
| ffb599458f | |||
| 55ad9ece31 | |||
| 3d473a8925 | |||
| b4b2f88cab | |||
| cc3b05e424 | |||
| 195cce45cf | |||
| c7a95509b3 | |||
| 6906a2b471 | |||
| 4eb44966a6 | |||
| 9a2b994a71 | |||
| 58b961d8bb | |||
| 6614f33a0b | |||
| 67e401e3cb | |||
| 789dadccc0 | |||
| 09510d9ffd | |||
| 816d4bee4a | |||
| a8fb9c9d27 | |||
| 5e2e8e1b9e | |||
| 28dd12c9b7 | |||
| da4b64ea02 | |||
| 9f011f0876 | |||
| 955be73bc5 | |||
| 3f94e061cb | |||
| a01cf1fe54 | |||
| fe8ae68738 | |||
| 3f851a7719 | |||
| b4b3af795c | |||
| 0bbf1f4785 | |||
| a57ba45eb4 | |||
| ceb5863d04 | |||
| cc8eba0ab8 | |||
| 829d4b009f | |||
| 426c52c2ce | |||
| 15f1648f7f | |||
| 45f40cec3a | |||
| de9f4351fa | |||
| 1ff644e509 | |||
| 698d768d21 | |||
| 137c998b48 | |||
| d416d7f061 | |||
| 807b703a48 | |||
| 5978b8bd9c | |||
| ac0e9506d0 | |||
| be3225153e | |||
| 9b25cf8b06 | |||
| f8fc6416b2 | |||
| 18bcfa81fc | |||
| 8c99a06c5c | |||
| 9179ab9227 | |||
| 6ef700dfb0 | |||
| 72a03b3c06 | |||
| ee059d8ef8 | |||
| 419f62c902 | |||
| 59c05f51d5 | |||
| 79ff380da7 | |||
| 81178db83b | |||
| 039ecef275 | |||
| c5a61adcca | |||
| 095f50e06e | |||
| 2af5b3fa08 | |||
| 5d1e309e67 | |||
| 9a3e525b7c | |||
| e42efdce95 | |||
| b26c6df919 | |||
| 7a74129fa9 | |||
| fd80c0b95f | |||
| a6dc1e84d2 | |||
| 390b6f0cba | |||
| 72389f7916 | |||
| 9315b45dd2 | |||
| df9fbc442d | |||
| 2fd48331d5 | |||
| a98413afb9 | |||
| 0cfea0581b | |||
| 0d00e151d1 | |||
| 990bccfad6 | |||
| f0169e9d58 | |||
| 2057068495 | |||
| 0b9d7b6f8d | |||
| ebe065c177 | |||
| 5f2018c490 | |||
| 3d79b9357d | |||
| 0be265e9a1 | |||
| 5996184bea | |||
| 16af5236ae | |||
| 2b114adcf4 | |||
| 2a5c577ef3 | |||
| 8f099e3a67 | |||
| cfe614787d | |||
| 7efe57ba11 | |||
| da4d578621 |
@@ -0,0 +1,15 @@
|
||||
|
||||
┌────────────────────────────────────┐
|
||||
│ RELEASE NOTES for FFmpeg 4.4 "Rao" │
|
||||
└────────────────────────────────────┘
|
||||
|
||||
The FFmpeg Project proudly presents FFmpeg 4.4 "Rao", about 10
|
||||
months after the release of FFmpeg 4.3.
|
||||
|
||||
A complete Changelog is available at the root of the project, and the
|
||||
complete Git history on https://git.ffmpeg.org/gitweb/ffmpeg.git
|
||||
|
||||
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.
|
||||
@@ -3364,6 +3364,7 @@ opus_muxer_select="ogg_muxer"
|
||||
psp_muxer_select="mov_muxer"
|
||||
rtp_demuxer_select="sdp_demuxer"
|
||||
rtp_muxer_select="golomb jpegtables"
|
||||
rtp_mpegts_muxer_select="mpegts_muxer rtp_muxer"
|
||||
rtpdec_select="asf_demuxer jpegtables mov_demuxer mpegts_demuxer rm_demuxer rtp_protocol srtp"
|
||||
rtsp_demuxer_select="http_protocol rtpdec"
|
||||
rtsp_muxer_select="rtp_muxer http_protocol rtp_protocol rtpenc_chain"
|
||||
|
||||
+1
-1
@@ -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 = 4.4
|
||||
|
||||
# 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
|
||||
|
||||
@@ -107,13 +107,16 @@ static void render_charset(AVCodecContext *avctx, uint8_t *charset,
|
||||
uint8_t pix;
|
||||
int lowdiff, highdiff;
|
||||
int *best_cb = c->mc_best_cb;
|
||||
static uint8_t index1[256];
|
||||
static uint8_t index2[256];
|
||||
static uint8_t dither[256];
|
||||
uint8_t index1[256];
|
||||
uint8_t index2[256];
|
||||
uint8_t dither[256];
|
||||
int i;
|
||||
int distance;
|
||||
|
||||
/* generate lookup-tables for dither and index before looping */
|
||||
/* Generate lookup-tables for dither and index before looping.
|
||||
* This code relies on c->mc_luma_vals[c->mc_pal_size - 1] being
|
||||
* the maximum of all the mc_luma_vals values and on the minimum
|
||||
* being zero; this ensures that dither is properly initialized. */
|
||||
i = 0;
|
||||
for (a=0; a < 256; a++) {
|
||||
if(i < c->mc_pal_size -1 && a == c->mc_luma_vals[i + 1]) {
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
#ifndef AVCODEC_AC3_H
|
||||
#define AVCODEC_AC3_H
|
||||
|
||||
#define AC3_MAX_CODED_FRAME_SIZE 3840 /* in bytes */
|
||||
#define EAC3_MAX_CHANNELS 16 /**< maximum number of channels in EAC3 */
|
||||
#define AC3_MAX_CHANNELS 7 /**< maximum number of channels, including coupling channel */
|
||||
#define CPL_CH 0 /**< coupling channel index */
|
||||
|
||||
+1
-1
@@ -1729,7 +1729,7 @@ static void ac3_output_frame(AC3EncodeContext *s, unsigned char *frame)
|
||||
{
|
||||
int blk;
|
||||
|
||||
init_put_bits(&s->pb, frame, AC3_MAX_CODED_FRAME_SIZE);
|
||||
init_put_bits(&s->pb, frame, s->frame_size);
|
||||
|
||||
s->output_frame_header(s);
|
||||
|
||||
|
||||
+32
-14
@@ -100,7 +100,7 @@ static const int8_t mtf_index_table[16] = {
|
||||
typedef struct ADPCMDecodeContext {
|
||||
ADPCMChannelStatus status[14];
|
||||
int vqa_version; /**< VQA version. Used for ADPCM_IMA_WS */
|
||||
int has_status;
|
||||
int has_status; /**< Status flag. Reset to 0 after a flush. */
|
||||
} ADPCMDecodeContext;
|
||||
|
||||
static av_cold int adpcm_decode_init(AVCodecContext * avctx)
|
||||
@@ -1811,11 +1811,6 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
|
||||
}
|
||||
break;
|
||||
case AV_CODEC_ID_ADPCM_AICA:
|
||||
if (!c->has_status) {
|
||||
for (channel = 0; channel < avctx->channels; channel++)
|
||||
c->status[channel].step = 0;
|
||||
c->has_status = 1;
|
||||
}
|
||||
for (channel = 0; channel < avctx->channels; channel++) {
|
||||
samples = samples_p[channel];
|
||||
for (n = nb_samples >> 1; n > 0; n--) {
|
||||
@@ -2077,13 +2072,6 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
|
||||
}
|
||||
break;
|
||||
case AV_CODEC_ID_ADPCM_ZORK:
|
||||
if (!c->has_status) {
|
||||
for (channel = 0; channel < avctx->channels; channel++) {
|
||||
c->status[channel].predictor = 0;
|
||||
c->status[channel].step_index = 0;
|
||||
}
|
||||
c->has_status = 1;
|
||||
}
|
||||
for (n = 0; n < nb_samples * avctx->channels; n++) {
|
||||
int v = bytestream2_get_byteu(&gb);
|
||||
*samples++ = adpcm_zork_expand_nibble(&c->status[n % avctx->channels], v);
|
||||
@@ -2121,7 +2109,37 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
|
||||
static void adpcm_flush(AVCodecContext *avctx)
|
||||
{
|
||||
ADPCMDecodeContext *c = avctx->priv_data;
|
||||
c->has_status = 0;
|
||||
|
||||
switch(avctx->codec_id) {
|
||||
case AV_CODEC_ID_ADPCM_AICA:
|
||||
for (int channel = 0; channel < avctx->channels; channel++)
|
||||
c->status[channel].step = 0;
|
||||
break;
|
||||
|
||||
case AV_CODEC_ID_ADPCM_ARGO:
|
||||
for (int channel = 0; channel < avctx->channels; channel++) {
|
||||
c->status[channel].sample1 = 0;
|
||||
c->status[channel].sample2 = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case AV_CODEC_ID_ADPCM_IMA_ALP:
|
||||
case AV_CODEC_ID_ADPCM_IMA_CUNNING:
|
||||
case AV_CODEC_ID_ADPCM_IMA_SSI:
|
||||
case AV_CODEC_ID_ADPCM_ZORK:
|
||||
for (int channel = 0; channel < avctx->channels; channel++) {
|
||||
c->status[channel].predictor = 0;
|
||||
c->status[channel].step_index = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Other codecs may want to handle this during decoding. */
|
||||
c->has_status = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
c->has_status = 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -959,14 +959,14 @@ static const AVOption options[] = {
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static const AVClass adpcm_encoder_class = {
|
||||
.class_name = "ADPCM Encoder",
|
||||
.item_name = av_default_item_name,
|
||||
.option = options,
|
||||
.version = LIBAVUTIL_VERSION_INT,
|
||||
};
|
||||
|
||||
#define ADPCM_ENCODER(id_, name_, sample_fmts_, capabilities_, long_name_) \
|
||||
static const AVClass name_ ## _encoder_class = { \
|
||||
.class_name = #name_, \
|
||||
.item_name = av_default_item_name, \
|
||||
.option = options, \
|
||||
.version = LIBAVUTIL_VERSION_INT, \
|
||||
}; \
|
||||
\
|
||||
AVCodec ff_ ## name_ ## _encoder = { \
|
||||
.name = #name_, \
|
||||
.long_name = NULL_IF_CONFIG_SMALL(long_name_), \
|
||||
@@ -979,7 +979,7 @@ AVCodec ff_ ## name_ ## _encoder = { \
|
||||
.sample_fmts = sample_fmts_, \
|
||||
.capabilities = capabilities_, \
|
||||
.caps_internal = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_INIT_THREADSAFE, \
|
||||
.priv_class = &adpcm_encoder_class, \
|
||||
.priv_class = &name_ ## _encoder_class, \
|
||||
}
|
||||
|
||||
ADPCM_ENCODER(AV_CODEC_ID_ADPCM_ARGO, adpcm_argo, sample_fmts_p, 0, "ADPCM Argonaut Games");
|
||||
|
||||
@@ -376,7 +376,7 @@ ASSSplitContext *ff_ass_split(const char *buf)
|
||||
ASSSplitContext *ctx = av_mallocz(sizeof(*ctx));
|
||||
if (!ctx)
|
||||
return NULL;
|
||||
if (buf && !memcmp(buf, "\xef\xbb\xbf", 3)) // Skip UTF-8 BOM header
|
||||
if (buf && !strncmp(buf, "\xef\xbb\xbf", 3)) // Skip UTF-8 BOM header
|
||||
buf += 3;
|
||||
ctx->current_section = -1;
|
||||
if (ass_split(ctx, buf) < 0) {
|
||||
|
||||
@@ -120,7 +120,7 @@ static int av1_metadata_update_fragment(AVBSFContext *bsf, AVPacket *pkt,
|
||||
}
|
||||
|
||||
// If a Temporal Delimiter is present, it must be the first OBU.
|
||||
if (frag->units[0].type == AV1_OBU_TEMPORAL_DELIMITER) {
|
||||
if (frag->nb_units && frag->units[0].type == AV1_OBU_TEMPORAL_DELIMITER) {
|
||||
if (ctx->td == BSF_ELEMENT_REMOVE)
|
||||
ff_cbs_delete_unit(frag, 0);
|
||||
} else if (pkt && ctx->td == BSF_ELEMENT_INSERT) {
|
||||
|
||||
+30
-24
@@ -318,6 +318,13 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *code
|
||||
avctx->time_base.den = avctx->sample_rate;
|
||||
}
|
||||
|
||||
if (av_codec_is_encoder(avctx->codec))
|
||||
ret = ff_encode_preinit(avctx);
|
||||
else
|
||||
ret = ff_decode_preinit(avctx);
|
||||
if (ret < 0)
|
||||
goto free_and_end;
|
||||
|
||||
if (!HAVE_THREADS)
|
||||
av_log(avctx, AV_LOG_WARNING, "Warning: not compiled with thread support, using thread emulation\n");
|
||||
|
||||
@@ -339,13 +346,6 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *code
|
||||
if (!HAVE_THREADS && !(codec->caps_internal & FF_CODEC_CAP_AUTO_THREADS))
|
||||
avctx->thread_count = 1;
|
||||
|
||||
if (av_codec_is_encoder(avctx->codec))
|
||||
ret = ff_encode_preinit(avctx);
|
||||
else
|
||||
ret = ff_decode_preinit(avctx);
|
||||
if (ret < 0)
|
||||
goto free_and_end;
|
||||
|
||||
if ( avctx->codec->init && (!(avctx->active_thread_type&FF_THREAD_FRAME)
|
||||
|| avci->frame_thread_encoder)) {
|
||||
ret = avctx->codec->init(avctx);
|
||||
@@ -644,6 +644,11 @@ FF_ENABLE_DEPRECATION_WARNINGS
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *unknown_if_null(const char *str)
|
||||
{
|
||||
return str ? str : "unknown";
|
||||
}
|
||||
|
||||
void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode)
|
||||
{
|
||||
const char *codec_type;
|
||||
@@ -653,6 +658,7 @@ void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode)
|
||||
int new_line = 0;
|
||||
AVRational display_aspect_ratio;
|
||||
const char *separator = enc->dump_separator ? (const char *)enc->dump_separator : ", ";
|
||||
const char *str;
|
||||
|
||||
if (!buf || buf_size <= 0)
|
||||
return;
|
||||
@@ -688,28 +694,27 @@ void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode)
|
||||
av_strlcat(buf, separator, buf_size);
|
||||
|
||||
snprintf(buf + strlen(buf), buf_size - strlen(buf),
|
||||
"%s", enc->pix_fmt == AV_PIX_FMT_NONE ? "none" :
|
||||
av_get_pix_fmt_name(enc->pix_fmt));
|
||||
"%s", enc->pix_fmt == AV_PIX_FMT_NONE ? "none" :
|
||||
unknown_if_null(av_get_pix_fmt_name(enc->pix_fmt)));
|
||||
if (enc->bits_per_raw_sample && enc->pix_fmt != AV_PIX_FMT_NONE &&
|
||||
enc->bits_per_raw_sample < av_pix_fmt_desc_get(enc->pix_fmt)->comp[0].depth)
|
||||
av_strlcatf(detail, sizeof(detail), "%d bpc, ", enc->bits_per_raw_sample);
|
||||
if (enc->color_range != AVCOL_RANGE_UNSPECIFIED)
|
||||
av_strlcatf(detail, sizeof(detail), "%s, ",
|
||||
av_color_range_name(enc->color_range));
|
||||
if (enc->color_range != AVCOL_RANGE_UNSPECIFIED &&
|
||||
(str = av_color_range_name(enc->color_range)))
|
||||
av_strlcatf(detail, sizeof(detail), "%s, ", str);
|
||||
|
||||
if (enc->colorspace != AVCOL_SPC_UNSPECIFIED ||
|
||||
enc->color_primaries != AVCOL_PRI_UNSPECIFIED ||
|
||||
enc->color_trc != AVCOL_TRC_UNSPECIFIED) {
|
||||
if (enc->colorspace != (int)enc->color_primaries ||
|
||||
enc->colorspace != (int)enc->color_trc) {
|
||||
const char *col = unknown_if_null(av_color_space_name(enc->colorspace));
|
||||
const char *pri = unknown_if_null(av_color_primaries_name(enc->color_primaries));
|
||||
const char *trc = unknown_if_null(av_color_transfer_name(enc->color_trc));
|
||||
if (strcmp(col, pri) || strcmp(col, trc)) {
|
||||
new_line = 1;
|
||||
av_strlcatf(detail, sizeof(detail), "%s/%s/%s, ",
|
||||
av_color_space_name(enc->colorspace),
|
||||
av_color_primaries_name(enc->color_primaries),
|
||||
av_color_transfer_name(enc->color_trc));
|
||||
col, pri, trc);
|
||||
} else
|
||||
av_strlcatf(detail, sizeof(detail), "%s, ",
|
||||
av_get_colorspace_name(enc->colorspace));
|
||||
av_strlcatf(detail, sizeof(detail), "%s, ", col);
|
||||
}
|
||||
|
||||
if (enc->field_order != AV_FIELD_UNKNOWN) {
|
||||
@@ -727,9 +732,9 @@ void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode)
|
||||
}
|
||||
|
||||
if (av_log_get_level() >= AV_LOG_VERBOSE &&
|
||||
enc->chroma_sample_location != AVCHROMA_LOC_UNSPECIFIED)
|
||||
av_strlcatf(detail, sizeof(detail), "%s, ",
|
||||
av_chroma_location_name(enc->chroma_sample_location));
|
||||
enc->chroma_sample_location != AVCHROMA_LOC_UNSPECIFIED &&
|
||||
(str = av_chroma_location_name(enc->chroma_sample_location)))
|
||||
av_strlcatf(detail, sizeof(detail), "%s, ", str);
|
||||
|
||||
if (strlen(detail) > 1) {
|
||||
detail[strlen(detail) - 2] = 0;
|
||||
@@ -787,9 +792,10 @@ void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode)
|
||||
"%d Hz, ", enc->sample_rate);
|
||||
}
|
||||
av_get_channel_layout_string(buf + strlen(buf), buf_size - strlen(buf), enc->channels, enc->channel_layout);
|
||||
if (enc->sample_fmt != AV_SAMPLE_FMT_NONE) {
|
||||
if (enc->sample_fmt != AV_SAMPLE_FMT_NONE &&
|
||||
(str = av_get_sample_fmt_name(enc->sample_fmt))) {
|
||||
snprintf(buf + strlen(buf), buf_size - strlen(buf),
|
||||
", %s", av_get_sample_fmt_name(enc->sample_fmt));
|
||||
", %s", str);
|
||||
}
|
||||
if ( enc->bits_per_raw_sample > 0
|
||||
&& enc->bits_per_raw_sample != av_get_bytes_per_sample(enc->sample_fmt) * 8)
|
||||
|
||||
@@ -70,7 +70,7 @@ static av_cold int decode_init(AVCodecContext *avctx)
|
||||
BinkAudioContext *s = avctx->priv_data;
|
||||
int sample_rate = avctx->sample_rate;
|
||||
int sample_rate_half;
|
||||
int i;
|
||||
int i, ret;
|
||||
int frame_len_bits;
|
||||
|
||||
/* determine frame length */
|
||||
@@ -132,11 +132,13 @@ static av_cold int decode_init(AVCodecContext *avctx)
|
||||
s->first = 1;
|
||||
|
||||
if (CONFIG_BINKAUDIO_RDFT_DECODER && avctx->codec->id == AV_CODEC_ID_BINKAUDIO_RDFT)
|
||||
ff_rdft_init(&s->trans.rdft, frame_len_bits, DFT_C2R);
|
||||
ret = ff_rdft_init(&s->trans.rdft, frame_len_bits, DFT_C2R);
|
||||
else if (CONFIG_BINKAUDIO_DCT_DECODER)
|
||||
ff_dct_init(&s->trans.dct, frame_len_bits, DCT_III);
|
||||
ret = ff_dct_init(&s->trans.dct, frame_len_bits, DCT_III);
|
||||
else
|
||||
av_assert0(0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
s->pkt = av_packet_alloc();
|
||||
if (!s->pkt)
|
||||
@@ -345,6 +347,7 @@ AVCodec ff_binkaudio_rdft_decoder = {
|
||||
.close = decode_end,
|
||||
.receive_frame = binkaudio_receive_frame,
|
||||
.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1,
|
||||
.caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
|
||||
};
|
||||
|
||||
AVCodec ff_binkaudio_dct_decoder = {
|
||||
@@ -357,4 +360,5 @@ AVCodec ff_binkaudio_dct_decoder = {
|
||||
.close = decode_end,
|
||||
.receive_frame = binkaudio_receive_frame,
|
||||
.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1,
|
||||
.caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
|
||||
};
|
||||
|
||||
+20
-19
@@ -45,14 +45,15 @@ void av_bsf_free(AVBSFContext **pctx)
|
||||
return;
|
||||
ctx = *pctx;
|
||||
|
||||
if (ctx->filter->close)
|
||||
ctx->filter->close(ctx);
|
||||
if (ctx->internal) {
|
||||
if (ctx->filter->close)
|
||||
ctx->filter->close(ctx);
|
||||
av_packet_free(&ctx->internal->buffer_pkt);
|
||||
av_freep(&ctx->internal);
|
||||
}
|
||||
if (ctx->filter->priv_class && ctx->priv_data)
|
||||
av_opt_free(ctx->priv_data);
|
||||
|
||||
if (ctx->internal)
|
||||
av_packet_free(&ctx->internal->buffer_pkt);
|
||||
av_freep(&ctx->internal);
|
||||
av_freep(&ctx->priv_data);
|
||||
|
||||
avcodec_parameters_free(&ctx->par_in);
|
||||
@@ -110,20 +111,6 @@ int av_bsf_alloc(const AVBitStreamFilter *filter, AVBSFContext **pctx)
|
||||
ret = AVERROR(ENOMEM);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
bsfi = av_mallocz(sizeof(*bsfi));
|
||||
if (!bsfi) {
|
||||
ret = AVERROR(ENOMEM);
|
||||
goto fail;
|
||||
}
|
||||
ctx->internal = bsfi;
|
||||
|
||||
bsfi->buffer_pkt = av_packet_alloc();
|
||||
if (!bsfi->buffer_pkt) {
|
||||
ret = AVERROR(ENOMEM);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* allocate priv data and init private options */
|
||||
if (filter->priv_data_size) {
|
||||
ctx->priv_data = av_mallocz(filter->priv_data_size);
|
||||
@@ -136,6 +123,20 @@ int av_bsf_alloc(const AVBitStreamFilter *filter, AVBSFContext **pctx)
|
||||
av_opt_set_defaults(ctx->priv_data);
|
||||
}
|
||||
}
|
||||
/* Allocate AVBSFInternal; must happen after priv_data has been allocated
|
||||
* so that a filter->close needing priv_data is never called without. */
|
||||
bsfi = av_mallocz(sizeof(*bsfi));
|
||||
if (!bsfi) {
|
||||
ret = AVERROR(ENOMEM);
|
||||
goto fail;
|
||||
}
|
||||
ctx->internal = bsfi;
|
||||
|
||||
bsfi->buffer_pkt = av_packet_alloc();
|
||||
if (!bsfi->buffer_pkt) {
|
||||
ret = AVERROR(ENOMEM);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
*pctx = ctx;
|
||||
return 0;
|
||||
|
||||
+62
-14
@@ -221,6 +221,7 @@ static void free_buffers(CFHDContext *s)
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < FF_ARRAY_ELEMS(s->plane); i++) {
|
||||
Plane *p = &s->plane[i];
|
||||
av_freep(&s->plane[i].idwt_buf);
|
||||
av_freep(&s->plane[i].idwt_tmp);
|
||||
s->plane[i].idwt_size = 0;
|
||||
@@ -230,9 +231,16 @@ static void free_buffers(CFHDContext *s)
|
||||
|
||||
for (j = 0; j < 10; j++)
|
||||
s->plane[i].l_h[j] = NULL;
|
||||
|
||||
for (j = 0; j < DWT_LEVELS_3D; j++)
|
||||
p->band[j][0].read_ok =
|
||||
p->band[j][1].read_ok =
|
||||
p->band[j][2].read_ok =
|
||||
p->band[j][3].read_ok = 0;
|
||||
}
|
||||
s->a_height = 0;
|
||||
s->a_width = 0;
|
||||
s->a_transform_type = INT_MIN;
|
||||
}
|
||||
|
||||
static int alloc_buffers(AVCodecContext *avctx)
|
||||
@@ -356,6 +364,7 @@ static int alloc_buffers(AVCodecContext *avctx)
|
||||
}
|
||||
}
|
||||
|
||||
s->a_transform_type = s->transform_type;
|
||||
s->a_height = s->coded_height;
|
||||
s->a_width = s->coded_width;
|
||||
s->a_format = s->coded_format;
|
||||
@@ -655,7 +664,8 @@ static int cfhd_decode(AVCodecContext *avctx, void *data, int *got_frame,
|
||||
s->coded_height = s->a_height;
|
||||
|
||||
if (s->a_width != s->coded_width || s->a_height != s->coded_height ||
|
||||
s->a_format != s->coded_format) {
|
||||
s->a_format != s->coded_format ||
|
||||
s->transform_type != s->a_transform_type) {
|
||||
free_buffers(s);
|
||||
if ((ret = alloc_buffers(avctx)) < 0) {
|
||||
free_buffers(s);
|
||||
@@ -698,11 +708,18 @@ static int cfhd_decode(AVCodecContext *avctx, void *data, int *got_frame,
|
||||
coeff_data = s->plane[s->channel_num].subband[s->subband_num_actual];
|
||||
|
||||
/* Lowpass coefficients */
|
||||
if (tag == BitstreamMarker && data == 0xf0f && s->a_width && s->a_height) {
|
||||
int lowpass_height = s->plane[s->channel_num].band[0][0].height;
|
||||
int lowpass_width = s->plane[s->channel_num].band[0][0].width;
|
||||
int lowpass_a_height = s->plane[s->channel_num].band[0][0].a_height;
|
||||
int lowpass_a_width = s->plane[s->channel_num].band[0][0].a_width;
|
||||
if (tag == BitstreamMarker && data == 0xf0f) {
|
||||
int lowpass_height, lowpass_width, lowpass_a_height, lowpass_a_width;
|
||||
|
||||
if (!s->a_width || !s->a_height) {
|
||||
ret = AVERROR_INVALIDDATA;
|
||||
goto end;
|
||||
}
|
||||
|
||||
lowpass_height = s->plane[s->channel_num].band[0][0].height;
|
||||
lowpass_width = s->plane[s->channel_num].band[0][0].width;
|
||||
lowpass_a_height = s->plane[s->channel_num].band[0][0].a_height;
|
||||
lowpass_a_width = s->plane[s->channel_num].band[0][0].a_width;
|
||||
|
||||
if (lowpass_width < 3 ||
|
||||
lowpass_width > lowpass_a_width) {
|
||||
@@ -749,20 +766,30 @@ static int cfhd_decode(AVCodecContext *avctx, void *data, int *got_frame,
|
||||
lowpass_width * sizeof(*coeff_data));
|
||||
}
|
||||
|
||||
s->plane[s->channel_num].band[0][0].read_ok = 1;
|
||||
|
||||
av_log(avctx, AV_LOG_DEBUG, "Lowpass coefficients %d\n", lowpass_width * lowpass_height);
|
||||
}
|
||||
|
||||
if ((tag == BandHeader || tag == BandSecondPass) && s->subband_num_actual != 255 && s->a_width && s->a_height) {
|
||||
int highpass_height = s->plane[s->channel_num].band[s->level][s->subband_num].height;
|
||||
int highpass_width = s->plane[s->channel_num].band[s->level][s->subband_num].width;
|
||||
int highpass_a_width = s->plane[s->channel_num].band[s->level][s->subband_num].a_width;
|
||||
int highpass_a_height = s->plane[s->channel_num].band[s->level][s->subband_num].a_height;
|
||||
int highpass_stride = s->plane[s->channel_num].band[s->level][s->subband_num].stride;
|
||||
av_assert0(s->subband_num_actual != 255);
|
||||
if (tag == BandHeader || tag == BandSecondPass) {
|
||||
int highpass_height, highpass_width, highpass_a_width, highpass_a_height, highpass_stride, a_expected;
|
||||
int expected;
|
||||
int a_expected = highpass_a_height * highpass_a_width;
|
||||
int level, run, coeff;
|
||||
int count = 0, bytes;
|
||||
|
||||
if (!s->a_width || !s->a_height) {
|
||||
ret = AVERROR_INVALIDDATA;
|
||||
goto end;
|
||||
}
|
||||
|
||||
highpass_height = s->plane[s->channel_num].band[s->level][s->subband_num].height;
|
||||
highpass_width = s->plane[s->channel_num].band[s->level][s->subband_num].width;
|
||||
highpass_a_width = s->plane[s->channel_num].band[s->level][s->subband_num].a_width;
|
||||
highpass_a_height = s->plane[s->channel_num].band[s->level][s->subband_num].a_height;
|
||||
highpass_stride = s->plane[s->channel_num].band[s->level][s->subband_num].stride;
|
||||
a_expected = highpass_a_height * highpass_a_width;
|
||||
|
||||
if (!got_buffer) {
|
||||
av_log(avctx, AV_LOG_ERROR, "No end of header tag found\n");
|
||||
ret = AVERROR(EINVAL);
|
||||
@@ -873,6 +900,7 @@ static int cfhd_decode(AVCodecContext *avctx, void *data, int *got_frame,
|
||||
bytestream2_seek(&gb, bytes, SEEK_CUR);
|
||||
|
||||
av_log(avctx, AV_LOG_DEBUG, "End subband coeffs %i extra %i\n", count, count - expected);
|
||||
s->plane[s->channel_num].band[s->level][s->subband_num].read_ok = 1;
|
||||
finish:
|
||||
if (s->subband_num_actual != 255)
|
||||
s->codebook = 0;
|
||||
@@ -888,6 +916,7 @@ finish:
|
||||
ff_thread_finish_setup(avctx);
|
||||
|
||||
if (!s->a_width || !s->a_height || s->a_format == AV_PIX_FMT_NONE ||
|
||||
s->a_transform_type == INT_MIN ||
|
||||
s->coded_width || s->coded_height || s->coded_format != AV_PIX_FMT_NONE) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Invalid dimensions\n");
|
||||
ret = AVERROR(EINVAL);
|
||||
@@ -900,6 +929,22 @@ finish:
|
||||
goto end;
|
||||
}
|
||||
|
||||
for (plane = 0; plane < s->planes; plane++) {
|
||||
int o, level;
|
||||
|
||||
for (level = 0; level < (s->transform_type == 0 ? DWT_LEVELS : DWT_LEVELS_3D) ; level++) {
|
||||
if (s->transform_type == 2)
|
||||
if (level == 2 || level == 5)
|
||||
continue;
|
||||
for (o = !!level; o < 4 ; o++) {
|
||||
if (!s->plane[plane].band[level][o].read_ok) {
|
||||
ret = AVERROR_INVALIDDATA;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (s->transform_type == 0 && s->sample_type != 1) {
|
||||
for (plane = 0; plane < s->planes && !ret; plane++) {
|
||||
/* level 1 */
|
||||
@@ -1381,12 +1426,14 @@ static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src)
|
||||
if (pdst->plane[0].idwt_size != psrc->plane[0].idwt_size ||
|
||||
pdst->a_format != psrc->a_format ||
|
||||
pdst->a_width != psrc->a_width ||
|
||||
pdst->a_height != psrc->a_height)
|
||||
pdst->a_height != psrc->a_height ||
|
||||
pdst->a_transform_type != psrc->a_transform_type)
|
||||
free_buffers(pdst);
|
||||
|
||||
pdst->a_format = psrc->a_format;
|
||||
pdst->a_width = psrc->a_width;
|
||||
pdst->a_height = psrc->a_height;
|
||||
pdst->a_transform_type = psrc->a_transform_type;
|
||||
pdst->transform_type = psrc->transform_type;
|
||||
pdst->progressive = psrc->progressive;
|
||||
pdst->planes = psrc->planes;
|
||||
@@ -1395,6 +1442,7 @@ static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src)
|
||||
pdst->coded_width = pdst->a_width;
|
||||
pdst->coded_height = pdst->a_height;
|
||||
pdst->coded_format = pdst->a_format;
|
||||
pdst->transform_type = pdst->a_transform_type;
|
||||
ret = alloc_buffers(dst);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@@ -114,6 +114,7 @@ typedef struct SubBand {
|
||||
int width;
|
||||
int a_height;
|
||||
int height;
|
||||
int8_t read_ok;
|
||||
} SubBand;
|
||||
|
||||
typedef struct Plane {
|
||||
@@ -165,6 +166,7 @@ typedef struct CFHDContext {
|
||||
int a_width;
|
||||
int a_height;
|
||||
int a_format;
|
||||
int a_transform_type;
|
||||
|
||||
int bpc; // bits per channel/component
|
||||
int channel_cnt;
|
||||
|
||||
+4
-4
@@ -925,10 +925,10 @@ static void fill_in_adpcm_bufer(DCAEncContext *c)
|
||||
* But there are no proper value in decoder history, so likely result will be no good.
|
||||
* Bitstream has "Predictor history flag switch", but this flag disables history for all subbands
|
||||
*/
|
||||
samples[0] = c->adpcm_history[ch][band][0] << 7;
|
||||
samples[1] = c->adpcm_history[ch][band][1] << 7;
|
||||
samples[2] = c->adpcm_history[ch][band][2] << 7;
|
||||
samples[3] = c->adpcm_history[ch][band][3] << 7;
|
||||
samples[0] = c->adpcm_history[ch][band][0] * (1 << 7);
|
||||
samples[1] = c->adpcm_history[ch][band][1] * (1 << 7);
|
||||
samples[2] = c->adpcm_history[ch][band][2] * (1 << 7);
|
||||
samples[3] = c->adpcm_history[ch][band][3] * (1 << 7);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -261,24 +261,22 @@ const AVDVProfile* ff_dv_frame_profile(AVCodecContext* codec, const AVDVProfile
|
||||
const uint8_t *frame, unsigned buf_size)
|
||||
{
|
||||
#if CONFIG_DVPROFILE
|
||||
int i, dsf, stype;
|
||||
int i, dsf, stype, pal;
|
||||
|
||||
if(buf_size < DV_PROFILE_BYTES)
|
||||
return NULL;
|
||||
|
||||
dsf = (frame[3] & 0x80) >> 7;
|
||||
stype = frame[80 * 5 + 48 + 3] & 0x1f;
|
||||
pal = !!(frame[80 * 5 + 48 + 3] & 0x20);
|
||||
|
||||
/* 576i50 25Mbps 4:1:1 is a special case */
|
||||
if ((dsf == 1 && stype == 0 && frame[4] & 0x07 /* the APT field */) ||
|
||||
(stype == 31 && codec && codec->codec_tag==AV_RL32("SL25") && codec->coded_width==720 && codec->coded_height==576))
|
||||
return &dv_profiles[2];
|
||||
|
||||
if( stype == 0
|
||||
&& codec
|
||||
&& (codec->codec_tag==AV_RL32("dvsd") || codec->codec_tag==AV_RL32("CDVC"))
|
||||
&& codec->coded_width ==720
|
||||
&& codec->coded_height==576)
|
||||
/* hack for trac issues #8333 and #2177, PAL DV files with dsf flag 0 - detect via pal flag and buf_size */
|
||||
if (dsf == 0 && pal == 1 && stype == dv_profiles[1].video_stype && buf_size == dv_profiles[1].frame_size)
|
||||
return &dv_profiles[1];
|
||||
|
||||
for (i = 0; i < FF_ARRAY_ELEMS(dv_profiles); i++)
|
||||
|
||||
+1
-1
@@ -565,7 +565,7 @@ FF_ENABLE_DEPRECATION_WARNINGS
|
||||
if (avctx->pix_fmt == avctx->codec->pix_fmts[i])
|
||||
break;
|
||||
if (avctx->codec->pix_fmts[i] == AV_PIX_FMT_NONE
|
||||
&& !((avctx->codec_id == AV_CODEC_ID_MJPEG || avctx->codec_id == AV_CODEC_ID_LJPEG)
|
||||
&& !(avctx->codec_id == AV_CODEC_ID_MJPEG
|
||||
&& avctx->strict_std_compliance <= FF_COMPLIANCE_UNOFFICIAL)) {
|
||||
char buf[128];
|
||||
snprintf(buf, sizeof(buf), "%d", avctx->pix_fmt);
|
||||
|
||||
+6
-1
@@ -422,7 +422,12 @@ static int huf_decode(VLC *vlc, GetByteContext *gb, int nbits, int run_sym,
|
||||
|
||||
if (x == run_sym) {
|
||||
int run = get_bits(&gbit, 8);
|
||||
uint16_t fill = out[oe - 1];
|
||||
uint16_t fill;
|
||||
|
||||
if (oe == 0 || oe + run > no)
|
||||
return AVERROR_INVALIDDATA;
|
||||
|
||||
fill = out[oe - 1];
|
||||
|
||||
while (run-- > 0)
|
||||
out[oe++] = fill;
|
||||
|
||||
@@ -188,7 +188,7 @@ static uint64_t frac64(uint64_t a, uint64_t b)
|
||||
|
||||
static uint64_t phi_at(struct ws_interval *in, int64_t ts)
|
||||
{
|
||||
uint64_t dt = ts - in->ts_start;
|
||||
uint64_t dt = ts - (uint64_t)in->ts_start;
|
||||
uint64_t dt2 = dt & 1 ? /* dt * (dt - 1) / 2 without overflow */
|
||||
dt * ((dt - 1) >> 1) : (dt >> 1) * (dt - 1);
|
||||
return in->phi0 + dt * in->dphi0 + dt2 * in->ddphi;
|
||||
|
||||
@@ -1513,4 +1513,5 @@ AVCodec ff_flac_encoder = {
|
||||
AV_SAMPLE_FMT_S32,
|
||||
AV_SAMPLE_FMT_NONE },
|
||||
.priv_class = &flac_encoder_class,
|
||||
.caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
|
||||
};
|
||||
|
||||
@@ -159,7 +159,7 @@ static void init_blocks(FlashSV2Context * s, Block * blocks,
|
||||
b->enc = encbuf;
|
||||
b->data = databuf;
|
||||
encbuf += b->width * b->height * 3;
|
||||
databuf += !databuf ? 0 : b->width * b->height * 6;
|
||||
databuf = databuf ? databuf + b->width * b->height * 6 : NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -1029,7 +1029,7 @@ static int kempf_restore_buf(const uint8_t *src, int len,
|
||||
else if (npal <= 16) nb = 4;
|
||||
else nb = 8;
|
||||
|
||||
for (j = 0; j < height; j++, dst += stride, jpeg_tile += tile_stride) {
|
||||
for (j = 0; j < height; j++, dst += stride, jpeg_tile = FF_PTR_ADD(jpeg_tile, tile_stride)) {
|
||||
if (get_bits(&gb, 8))
|
||||
continue;
|
||||
for (i = 0; i < width; i++) {
|
||||
|
||||
@@ -678,6 +678,6 @@ AVCodec ff_h261_decoder = {
|
||||
.close = h261_decode_end,
|
||||
.decode = h261_decode_frame,
|
||||
.capabilities = AV_CODEC_CAP_DR1,
|
||||
.caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
|
||||
.caps_internal = FF_CODEC_CAP_INIT_THREADSAFE,
|
||||
.max_lowres = 3,
|
||||
};
|
||||
|
||||
@@ -771,7 +771,7 @@ AVCodec ff_h263_decoder = {
|
||||
.decode = ff_h263_decode_frame,
|
||||
.capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1 |
|
||||
AV_CODEC_CAP_TRUNCATED | AV_CODEC_CAP_DELAY,
|
||||
.caps_internal = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM | FF_CODEC_CAP_INIT_CLEANUP,
|
||||
.caps_internal = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM,
|
||||
.flush = ff_mpeg_flush,
|
||||
.max_lowres = 3,
|
||||
.pix_fmts = ff_h263_hwaccel_pixfmt_list_420,
|
||||
@@ -789,7 +789,7 @@ AVCodec ff_h263p_decoder = {
|
||||
.decode = ff_h263_decode_frame,
|
||||
.capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1 |
|
||||
AV_CODEC_CAP_TRUNCATED | AV_CODEC_CAP_DELAY,
|
||||
.caps_internal = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM | FF_CODEC_CAP_INIT_CLEANUP,
|
||||
.caps_internal = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM,
|
||||
.flush = ff_mpeg_flush,
|
||||
.max_lowres = 3,
|
||||
.pix_fmts = ff_h263_hwaccel_pixfmt_list_420,
|
||||
|
||||
@@ -466,7 +466,7 @@ static int h264_metadata_update_fragment(AVBSFContext *bsf, AVPacket *pkt,
|
||||
if (ctx->aud == BSF_ELEMENT_REMOVE)
|
||||
ff_cbs_delete_unit(au, 0);
|
||||
} else {
|
||||
if (ctx->aud == BSF_ELEMENT_INSERT) {
|
||||
if (pkt && ctx->aud == BSF_ELEMENT_INSERT) {
|
||||
err = h264_metadata_insert_aud(bsf, au);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
@@ -304,9 +304,8 @@ int ff_h264_update_thread_context(AVCodecContext *dst,
|
||||
if (dst == src)
|
||||
return 0;
|
||||
|
||||
// We can't fail if SPS isn't set at it breaks current skip_frame code
|
||||
//if (!h1->ps.sps)
|
||||
// return AVERROR_INVALIDDATA;
|
||||
if (inited && !h1->ps.sps)
|
||||
return AVERROR_INVALIDDATA;
|
||||
|
||||
if (inited &&
|
||||
(h->width != h1->width ||
|
||||
@@ -922,6 +921,11 @@ static int h264_slice_header_init(H264Context *h)
|
||||
const SPS *sps = h->ps.sps;
|
||||
int i, ret;
|
||||
|
||||
if (!sps) {
|
||||
ret = AVERROR_INVALIDDATA;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ff_set_sar(h->avctx, sps->sar);
|
||||
av_pix_fmt_get_chroma_sub_sample(h->avctx->pix_fmt,
|
||||
&h->chroma_x_shift, &h->chroma_y_shift);
|
||||
|
||||
@@ -335,7 +335,7 @@ static int h265_metadata_update_fragment(AVBSFContext *bsf, AVPacket *pkt,
|
||||
int err, i;
|
||||
|
||||
// If an AUD is present, it must be the first NAL unit.
|
||||
if (au->units[0].type == HEVC_NAL_AUD) {
|
||||
if (au->nb_units && au->units[0].type == HEVC_NAL_AUD) {
|
||||
if (ctx->aud == BSF_ELEMENT_REMOVE)
|
||||
ff_cbs_delete_unit(au, 0);
|
||||
} else {
|
||||
|
||||
+5
-3
@@ -173,7 +173,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPac
|
||||
int uqvq, ret;
|
||||
unsigned int mthread_inlen, mthread_outlen;
|
||||
unsigned int len = buf_size;
|
||||
int linesize;
|
||||
int linesize, offset;
|
||||
|
||||
if ((ret = ff_thread_get_buffer(avctx, &tframe, 0)) < 0)
|
||||
return ret;
|
||||
@@ -373,8 +373,10 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPac
|
||||
|
||||
/* Convert colorspace */
|
||||
y_out = frame->data[0] + (height - 1) * frame->linesize[0];
|
||||
u_out = frame->data[1] + (height - 1) * frame->linesize[1];
|
||||
v_out = frame->data[2] + (height - 1) * frame->linesize[2];
|
||||
offset = (height - 1) * frame->linesize[1];
|
||||
u_out = FF_PTR_ADD(frame->data[1], offset);
|
||||
offset = (height - 1) * frame->linesize[2];
|
||||
v_out = FF_PTR_ADD(frame->data[2], offset);
|
||||
switch (c->imgtype) {
|
||||
case IMGTYPE_YUV111:
|
||||
for (row = 0; row < height; row++) {
|
||||
|
||||
@@ -76,6 +76,10 @@ static int decode_idat(LSCRContext *s, int length)
|
||||
int ret;
|
||||
s->zstream.avail_in = FFMIN(length, bytestream2_get_bytes_left(&s->gb));
|
||||
s->zstream.next_in = s->gb.buffer;
|
||||
|
||||
if (length <= 0)
|
||||
return AVERROR_INVALIDDATA;
|
||||
|
||||
bytestream2_skip(&s->gb, length);
|
||||
|
||||
/* decode one line if possible */
|
||||
|
||||
+16
-16
@@ -76,6 +76,7 @@ static int init_default_huffman_tables(MJpegDecodeContext *s)
|
||||
int i, ret;
|
||||
|
||||
for (i = 0; i < FF_ARRAY_ELEMS(ht); i++) {
|
||||
ff_free_vlc(&s->vlcs[ht[i].class][ht[i].index]);
|
||||
ret = ff_mjpeg_build_vlc(&s->vlcs[ht[i].class][ht[i].index],
|
||||
ht[i].bits, ht[i].values,
|
||||
ht[i].class == 1, s->avctx);
|
||||
@@ -153,7 +154,8 @@ av_cold int ff_mjpeg_decode_init(AVCodecContext *avctx)
|
||||
if (ff_mjpeg_decode_dht(s)) {
|
||||
av_log(avctx, AV_LOG_ERROR,
|
||||
"error using external huffman table, switching back to internal\n");
|
||||
init_default_huffman_tables(s);
|
||||
if ((ret = init_default_huffman_tables(s)) < 0)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
if (avctx->field_order == AV_FIELD_BB) { /* quicktime icefloe 019 */
|
||||
@@ -2085,28 +2087,26 @@ static int mjpeg_decode_app(MJpegDecodeContext *s)
|
||||
|
||||
/* Allocate if this is the first APP2 we've seen. */
|
||||
if (s->iccnum == 0) {
|
||||
s->iccdata = av_mallocz(nummarkers * sizeof(*(s->iccdata)));
|
||||
s->iccdatalens = av_mallocz(nummarkers * sizeof(*(s->iccdatalens)));
|
||||
if (!s->iccdata || !s->iccdatalens) {
|
||||
if (!FF_ALLOCZ_TYPED_ARRAY(s->iccentries, nummarkers)) {
|
||||
av_log(s->avctx, AV_LOG_ERROR, "Could not allocate ICC data arrays\n");
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
s->iccnum = nummarkers;
|
||||
}
|
||||
|
||||
if (s->iccdata[seqno - 1]) {
|
||||
if (s->iccentries[seqno - 1].data) {
|
||||
av_log(s->avctx, AV_LOG_WARNING, "Duplicate ICC sequence number\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
s->iccdatalens[seqno - 1] = len;
|
||||
s->iccdata[seqno - 1] = av_malloc(len);
|
||||
if (!s->iccdata[seqno - 1]) {
|
||||
s->iccentries[seqno - 1].length = len;
|
||||
s->iccentries[seqno - 1].data = av_malloc(len);
|
||||
if (!s->iccentries[seqno - 1].data) {
|
||||
av_log(s->avctx, AV_LOG_ERROR, "Could not allocate ICC data buffer\n");
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
|
||||
memcpy(s->iccdata[seqno - 1], align_get_bits(&s->gb), len);
|
||||
memcpy(s->iccentries[seqno - 1].data, align_get_bits(&s->gb), len);
|
||||
skip_bits(&s->gb, len << 3);
|
||||
len = 0;
|
||||
s->iccread++;
|
||||
@@ -2315,11 +2315,11 @@ static void reset_icc_profile(MJpegDecodeContext *s)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (s->iccdata)
|
||||
if (s->iccentries) {
|
||||
for (i = 0; i < s->iccnum; i++)
|
||||
av_freep(&s->iccdata[i]);
|
||||
av_freep(&s->iccdata);
|
||||
av_freep(&s->iccdatalens);
|
||||
av_freep(&s->iccentries[i].data);
|
||||
av_freep(&s->iccentries);
|
||||
}
|
||||
|
||||
s->iccread = 0;
|
||||
s->iccnum = 0;
|
||||
@@ -2835,7 +2835,7 @@ the_end:
|
||||
|
||||
/* Sum size of all parts. */
|
||||
for (i = 0; i < s->iccnum; i++)
|
||||
total_size += s->iccdatalens[i];
|
||||
total_size += s->iccentries[i].length;
|
||||
|
||||
sd = av_frame_new_side_data(frame, AV_FRAME_DATA_ICC_PROFILE, total_size);
|
||||
if (!sd) {
|
||||
@@ -2845,8 +2845,8 @@ the_end:
|
||||
|
||||
/* Reassemble the parts, which are now in-order. */
|
||||
for (i = 0; i < s->iccnum; i++) {
|
||||
memcpy(sd->data + offset, s->iccdata[i], s->iccdatalens[i]);
|
||||
offset += s->iccdatalens[i];
|
||||
memcpy(sd->data + offset, s->iccentries[i].data, s->iccentries[i].length);
|
||||
offset += s->iccentries[i].length;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -44,6 +44,11 @@
|
||||
|
||||
#define MAX_COMPONENTS 4
|
||||
|
||||
typedef struct ICCEntry {
|
||||
uint8_t *data;
|
||||
int length;
|
||||
} ICCEntry;
|
||||
|
||||
typedef struct MJpegDecodeContext {
|
||||
AVClass *class;
|
||||
AVCodecContext *avctx;
|
||||
@@ -138,8 +143,7 @@ typedef struct MJpegDecodeContext {
|
||||
|
||||
const AVPixFmtDescriptor *pix_desc;
|
||||
|
||||
uint8_t **iccdata;
|
||||
int *iccdatalens;
|
||||
ICCEntry *iccentries;
|
||||
int iccnum;
|
||||
int iccread;
|
||||
|
||||
|
||||
@@ -312,8 +312,10 @@ av_cold int ff_mjpeg_encode_init(MpegEncContext *s)
|
||||
|
||||
av_cold void ff_mjpeg_encode_close(MpegEncContext *s)
|
||||
{
|
||||
av_freep(&s->mjpeg_ctx->huff_buffer);
|
||||
av_freep(&s->mjpeg_ctx);
|
||||
if (s->mjpeg_ctx) {
|
||||
av_freep(&s->mjpeg_ctx->huff_buffer);
|
||||
av_freep(&s->mjpeg_ctx);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+23
-23
@@ -109,8 +109,8 @@ static av_always_inline int cmp_direct_inline(MpegEncContext *s, const int x, co
|
||||
me_cmp_func cmp_func, me_cmp_func chroma_cmp_func, int qpel){
|
||||
MotionEstContext * const c= &s->me;
|
||||
const int stride= c->stride;
|
||||
const int hx= subx + (x<<(1+qpel));
|
||||
const int hy= suby + (y<<(1+qpel));
|
||||
const int hx = subx + x * (1 << (1 + qpel));
|
||||
const int hy = suby + y * (1 << (1 + qpel));
|
||||
uint8_t * const * const ref= c->ref[ref_index];
|
||||
uint8_t * const * const src= c->src[src_index];
|
||||
int d;
|
||||
@@ -599,7 +599,7 @@ static inline int h263_mv4_search(MpegEncContext *s, int mx, int my, int shift)
|
||||
P_LEFT[0] = s->current_picture.motion_val[0][mot_xy - 1][0];
|
||||
P_LEFT[1] = s->current_picture.motion_val[0][mot_xy - 1][1];
|
||||
|
||||
if(P_LEFT[0] > (c->xmax<<shift)) P_LEFT[0] = (c->xmax<<shift);
|
||||
if (P_LEFT[0] > c->xmax * (1 << shift)) P_LEFT[0] = c->xmax * (1 << shift);
|
||||
|
||||
/* special case for first line */
|
||||
if (s->first_slice_line && block<2) {
|
||||
@@ -610,10 +610,10 @@ static inline int h263_mv4_search(MpegEncContext *s, int mx, int my, int shift)
|
||||
P_TOP[1] = s->current_picture.motion_val[0][mot_xy - mot_stride ][1];
|
||||
P_TOPRIGHT[0] = s->current_picture.motion_val[0][mot_xy - mot_stride + off[block]][0];
|
||||
P_TOPRIGHT[1] = s->current_picture.motion_val[0][mot_xy - mot_stride + off[block]][1];
|
||||
if(P_TOP[1] > (c->ymax<<shift)) P_TOP[1] = (c->ymax<<shift);
|
||||
if(P_TOPRIGHT[0] < (c->xmin<<shift)) P_TOPRIGHT[0]= (c->xmin<<shift);
|
||||
if(P_TOPRIGHT[0] > (c->xmax<<shift)) P_TOPRIGHT[0]= (c->xmax<<shift);
|
||||
if(P_TOPRIGHT[1] > (c->ymax<<shift)) P_TOPRIGHT[1]= (c->ymax<<shift);
|
||||
if (P_TOP[1] > c->ymax * (1 << shift)) P_TOP[1] = c->ymax * (1 << shift);
|
||||
if (P_TOPRIGHT[0] < c->xmin * (1 << shift)) P_TOPRIGHT[0] = c->xmin * (1 << shift);
|
||||
if (P_TOPRIGHT[0] > c->xmax * (1 << shift)) P_TOPRIGHT[0] = c->xmax * (1 << shift);
|
||||
if (P_TOPRIGHT[1] > c->ymax * (1 << shift)) P_TOPRIGHT[1] = c->ymax * (1 << shift);
|
||||
|
||||
P_MEDIAN[0]= mid_pred(P_LEFT[0], P_TOP[0], P_TOPRIGHT[0]);
|
||||
P_MEDIAN[1]= mid_pred(P_LEFT[1], P_TOP[1], P_TOPRIGHT[1]);
|
||||
@@ -629,8 +629,8 @@ static inline int h263_mv4_search(MpegEncContext *s, int mx, int my, int shift)
|
||||
continue;
|
||||
if (i>4 && i<9)
|
||||
continue;
|
||||
if(P[i][0] > (c->xmax<<shift)) P[i][0]= (c->xmax<<shift);
|
||||
if(P[i][1] > (c->ymax<<shift)) P[i][1]= (c->ymax<<shift);
|
||||
if (P[i][0] > c->xmax * (1 << shift)) P[i][0] = c->xmax * (1 << shift);
|
||||
if (P[i][1] > c->ymax * (1 << shift)) P[i][1] = c->ymax * (1 <<shift );
|
||||
}
|
||||
|
||||
dmin4 = epzs_motion_search2(s, &mx4, &my4, P, block, block, s->p_mv_table, (1<<16)>>shift, 1);
|
||||
@@ -785,7 +785,7 @@ static int interlaced_search(MpegEncContext *s, int ref_index,
|
||||
P_TOPRIGHT[0] = mv_table[xy - mot_stride + 1][0];
|
||||
P_TOPRIGHT[1] = mv_table[xy - mot_stride + 1][1];
|
||||
if(P_TOP[1] > (c->ymax<<1)) P_TOP[1] = (c->ymax<<1);
|
||||
if(P_TOPRIGHT[0] < (c->xmin<<1)) P_TOPRIGHT[0]= (c->xmin<<1);
|
||||
if (P_TOPRIGHT[0] < c->xmin * (1 << 1)) P_TOPRIGHT[0] = c->xmin * (1 << 1);
|
||||
if(P_TOPRIGHT[0] > (c->xmax<<1)) P_TOPRIGHT[0]= (c->xmax<<1);
|
||||
if(P_TOPRIGHT[1] > (c->ymax<<1)) P_TOPRIGHT[1]= (c->ymax<<1);
|
||||
|
||||
@@ -839,7 +839,7 @@ static int interlaced_search(MpegEncContext *s, int ref_index,
|
||||
dmin_sum += best_dmin;
|
||||
}
|
||||
|
||||
c->ymin<<=1;
|
||||
c->ymin *= 2;
|
||||
c->ymax<<=1;
|
||||
c->stride>>=1;
|
||||
c->uvstride>>=1;
|
||||
@@ -981,8 +981,8 @@ void ff_estimate_p_frame_motion(MpegEncContext * s,
|
||||
if(mx || my)
|
||||
mb_type |= CANDIDATE_MB_TYPE_SKIPPED; //FIXME check difference
|
||||
}else{
|
||||
mx <<=shift;
|
||||
my <<=shift;
|
||||
mx *= 1 << shift;
|
||||
my *= 1 << shift;
|
||||
}
|
||||
if ((s->avctx->flags & AV_CODEC_FLAG_4MV)
|
||||
&& !c->skip && varc>50<<8 && vard>10<<8){
|
||||
@@ -1143,7 +1143,7 @@ static int estimate_motion_b(MpegEncContext *s, int mb_x, int mb_y,
|
||||
P_TOPRIGHT[0] = mv_table[mot_xy - mot_stride + 1][0];
|
||||
P_TOPRIGHT[1] = mv_table[mot_xy - mot_stride + 1][1];
|
||||
if (P_TOP[1] > (c->ymax << shift)) P_TOP[1] = (c->ymax << shift);
|
||||
if (P_TOPRIGHT[0] < (c->xmin << shift)) P_TOPRIGHT[0] = (c->xmin << shift);
|
||||
if (P_TOPRIGHT[0] < c->xmin * (1 << shift)) P_TOPRIGHT[0] = c->xmin * (1 << shift);
|
||||
if (P_TOPRIGHT[1] > (c->ymax << shift)) P_TOPRIGHT[1] = (c->ymax << shift);
|
||||
|
||||
P_MEDIAN[0] = mid_pred(P_LEFT[0], P_TOP[0], P_TOPRIGHT[0]);
|
||||
@@ -1155,7 +1155,7 @@ static int estimate_motion_b(MpegEncContext *s, int mb_x, int mb_y,
|
||||
if(mv_table == s->b_forw_mv_table){
|
||||
mv_scale= (s->pb_time<<16) / (s->pp_time<<shift);
|
||||
}else{
|
||||
mv_scale= ((s->pb_time - s->pp_time)<<16) / (s->pp_time<<shift);
|
||||
mv_scale = ((s->pb_time - s->pp_time) * (1 << 16)) / (s->pp_time<<shift);
|
||||
}
|
||||
|
||||
dmin = ff_epzs_motion_search(s, &mx, &my, P, 0, ref_index, s->p_mv_table, mv_scale, 0, 16);
|
||||
@@ -1255,8 +1255,8 @@ static inline int bidir_refine(MpegEncContext * s, int mb_x, int mb_y)
|
||||
const int flags= c->sub_flags;
|
||||
const int qpel= flags&FLAG_QPEL;
|
||||
const int shift= 1+qpel;
|
||||
const int xmin= c->xmin<<shift;
|
||||
const int ymin= c->ymin<<shift;
|
||||
const int xmin= c->xmin * (1 << shift);
|
||||
const int ymin= c->ymin * (1 << shift);
|
||||
const int xmax= c->xmax<<shift;
|
||||
const int ymax= c->ymax<<shift;
|
||||
#define HASH(fx,fy,bx,by) ((fx)+17*(fy)+63*(bx)+117*(by))
|
||||
@@ -1454,15 +1454,15 @@ static inline int direct_search(MpegEncContext * s, int mb_x, int mb_y)
|
||||
c->pred_x=0;
|
||||
c->pred_y=0;
|
||||
|
||||
P_LEFT[0] = av_clip(mv_table[mot_xy - 1][0], xmin<<shift, xmax<<shift);
|
||||
P_LEFT[1] = av_clip(mv_table[mot_xy - 1][1], ymin<<shift, ymax<<shift);
|
||||
P_LEFT[0] = av_clip(mv_table[mot_xy - 1][0], xmin * (1 << shift), xmax << shift);
|
||||
P_LEFT[1] = av_clip(mv_table[mot_xy - 1][1], ymin * (1 << shift), ymax << shift);
|
||||
|
||||
/* special case for first line */
|
||||
if (!s->first_slice_line) { //FIXME maybe allow this over thread boundary as it is clipped
|
||||
P_TOP[0] = av_clip(mv_table[mot_xy - mot_stride ][0], xmin<<shift, xmax<<shift);
|
||||
P_TOP[1] = av_clip(mv_table[mot_xy - mot_stride ][1], ymin<<shift, ymax<<shift);
|
||||
P_TOPRIGHT[0] = av_clip(mv_table[mot_xy - mot_stride + 1 ][0], xmin<<shift, xmax<<shift);
|
||||
P_TOPRIGHT[1] = av_clip(mv_table[mot_xy - mot_stride + 1 ][1], ymin<<shift, ymax<<shift);
|
||||
P_TOP[0] = av_clip(mv_table[mot_xy - mot_stride ][0], xmin * (1 << shift), xmax << shift);
|
||||
P_TOP[1] = av_clip(mv_table[mot_xy - mot_stride ][1], ymin * (1 << shift), ymax << shift);
|
||||
P_TOPRIGHT[0] = av_clip(mv_table[mot_xy - mot_stride + 1][0], xmin * (1 << shift), xmax << shift);
|
||||
P_TOPRIGHT[1] = av_clip(mv_table[mot_xy - mot_stride + 1][1], ymin * (1 << shift), ymax << shift);
|
||||
|
||||
P_MEDIAN[0]= mid_pred(P_LEFT[0], P_TOP[0], P_TOPRIGHT[0]);
|
||||
P_MEDIAN[1]= mid_pred(P_LEFT[1], P_TOP[1], P_TOPRIGHT[1]);
|
||||
|
||||
@@ -82,7 +82,7 @@ static int hpel_motion_search(MpegEncContext * s,
|
||||
if (mx > xmin && mx < xmax &&
|
||||
my > ymin && my < ymax) {
|
||||
int d= dmin;
|
||||
const int index= (my<<ME_MAP_SHIFT) + mx;
|
||||
const int index = my * (1 << ME_MAP_SHIFT) + mx;
|
||||
const int t= score_map[(index-(1<<ME_MAP_SHIFT))&(ME_MAP_SIZE-1)]
|
||||
+ (mv_penalty[bx - pred_x] + mv_penalty[by-2 - pred_y])*c->penalty_factor;
|
||||
const int l= score_map[(index- 1 )&(ME_MAP_SIZE-1)]
|
||||
@@ -95,13 +95,13 @@ static int hpel_motion_search(MpegEncContext * s,
|
||||
#if defined(ASSERT_LEVEL) && ASSERT_LEVEL > 1
|
||||
unsigned key;
|
||||
unsigned map_generation= c->map_generation;
|
||||
key= ((my-1)<<ME_MAP_MV_BITS) + (mx) + map_generation;
|
||||
key = (my - 1) * (1 << ME_MAP_MV_BITS) + (mx) + map_generation;
|
||||
av_assert2(c->map[(index-(1<<ME_MAP_SHIFT))&(ME_MAP_SIZE-1)] == key);
|
||||
key= ((my+1)<<ME_MAP_MV_BITS) + (mx) + map_generation;
|
||||
key = (my + 1) * (1 << ME_MAP_MV_BITS) + (mx) + map_generation;
|
||||
av_assert2(c->map[(index+(1<<ME_MAP_SHIFT))&(ME_MAP_SIZE-1)] == key);
|
||||
key= ((my)<<ME_MAP_MV_BITS) + (mx+1) + map_generation;
|
||||
key = (my) * (1 << ME_MAP_MV_BITS) + (mx + 1) + map_generation;
|
||||
av_assert2(c->map[(index+1)&(ME_MAP_SIZE-1)] == key);
|
||||
key= ((my)<<ME_MAP_MV_BITS) + (mx-1) + map_generation;
|
||||
key = (my) * (1 << ME_MAP_MV_BITS) + (mx - 1) + map_generation;
|
||||
av_assert2(c->map[(index-1)&(ME_MAP_SIZE-1)] == key);
|
||||
#endif
|
||||
if(t<=b){
|
||||
@@ -246,7 +246,7 @@ static int qpel_motion_search(MpegEncContext * s,
|
||||
int bx=4*mx, by=4*my;
|
||||
int d= dmin;
|
||||
int i, nx, ny;
|
||||
const int index= (my<<ME_MAP_SHIFT) + mx;
|
||||
const int index = my * (1 << ME_MAP_SHIFT) + mx;
|
||||
const int t= score_map[(index-(1<<ME_MAP_SHIFT) )&(ME_MAP_SIZE-1)];
|
||||
const int l= score_map[(index- 1 )&(ME_MAP_SIZE-1)];
|
||||
const int r= score_map[(index+ 1 )&(ME_MAP_SIZE-1)];
|
||||
@@ -299,7 +299,8 @@ static int qpel_motion_search(MpegEncContext * s,
|
||||
const int cy2= b + t - 2*c;
|
||||
int cxy;
|
||||
|
||||
if(map[(index-(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)] == ((my-1)<<ME_MAP_MV_BITS) + (mx-1) + map_generation){
|
||||
if (map[(index - (1 << ME_MAP_SHIFT) - 1) & (ME_MAP_SIZE - 1)] ==
|
||||
(my - 1) * (1 << ME_MAP_MV_BITS) + (mx - 1) + map_generation) {
|
||||
tl= score_map[(index-(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)];
|
||||
}else{
|
||||
tl= cmp(s, mx-1, my-1, 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);//FIXME wrong if chroma me is different
|
||||
@@ -328,7 +329,7 @@ static int qpel_motion_search(MpegEncContext * s,
|
||||
for(i=0; i<8; i++){
|
||||
if(score < best[i]){
|
||||
memmove(&best[i+1], &best[i], sizeof(int)*(7-i));
|
||||
memmove(&best_pos[i+1][0], &best_pos[i][0], sizeof(int)*2*(7-i));
|
||||
memmove(best_pos[i + 1], best_pos[i], sizeof(best_pos[0]) * (7 - i));
|
||||
best[i]= score;
|
||||
best_pos[i][0]= nx + 4*mx;
|
||||
best_pos[i][1]= ny + 4*my;
|
||||
|
||||
@@ -2880,7 +2880,8 @@ static av_cold int mpeg_decode_end(AVCodecContext *avctx)
|
||||
{
|
||||
Mpeg1Context *s = avctx->priv_data;
|
||||
|
||||
ff_mpv_common_end(&s->mpeg_enc_ctx);
|
||||
if (s->mpeg_enc_ctx_allocated)
|
||||
ff_mpv_common_end(&s->mpeg_enc_ctx);
|
||||
av_buffer_unref(&s->a53_buf_ref);
|
||||
return 0;
|
||||
}
|
||||
@@ -2897,7 +2898,7 @@ AVCodec ff_mpeg1video_decoder = {
|
||||
.capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1 |
|
||||
AV_CODEC_CAP_TRUNCATED | AV_CODEC_CAP_DELAY |
|
||||
AV_CODEC_CAP_SLICE_THREADS,
|
||||
.caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP |
|
||||
.caps_internal = FF_CODEC_CAP_INIT_THREADSAFE |
|
||||
FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM,
|
||||
.flush = flush,
|
||||
.max_lowres = 3,
|
||||
@@ -2931,7 +2932,7 @@ AVCodec ff_mpeg2video_decoder = {
|
||||
.capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1 |
|
||||
AV_CODEC_CAP_TRUNCATED | AV_CODEC_CAP_DELAY |
|
||||
AV_CODEC_CAP_SLICE_THREADS,
|
||||
.caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP |
|
||||
.caps_internal = FF_CODEC_CAP_INIT_THREADSAFE |
|
||||
FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM,
|
||||
.flush = flush,
|
||||
.max_lowres = 3,
|
||||
@@ -2976,7 +2977,7 @@ AVCodec ff_mpegvideo_decoder = {
|
||||
.close = mpeg_decode_end,
|
||||
.decode = mpeg_decode_frame,
|
||||
.capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_TRUNCATED | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SLICE_THREADS,
|
||||
.caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP |
|
||||
.caps_internal = FF_CODEC_CAP_INIT_THREADSAFE |
|
||||
FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM,
|
||||
.flush = flush,
|
||||
.max_lowres = 3,
|
||||
|
||||
@@ -3579,8 +3579,7 @@ AVCodec ff_mpeg4_decoder = {
|
||||
AV_CODEC_CAP_TRUNCATED | AV_CODEC_CAP_DELAY |
|
||||
AV_CODEC_CAP_FRAME_THREADS,
|
||||
.caps_internal = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM |
|
||||
FF_CODEC_CAP_ALLOCATE_PROGRESS |
|
||||
FF_CODEC_CAP_INIT_CLEANUP,
|
||||
FF_CODEC_CAP_ALLOCATE_PROGRESS,
|
||||
.flush = ff_mpeg_flush,
|
||||
.max_lowres = 3,
|
||||
.pix_fmts = ff_h263_hwaccel_pixfmt_list_420,
|
||||
|
||||
@@ -79,8 +79,11 @@ int ff_mpeg_framesize_alloc(AVCodecContext *avctx, MotionEstContext *me,
|
||||
// linesize * interlaced * MBsize
|
||||
// we also use this buffer for encoding in encode_mb_internal() needig an additional 32 lines
|
||||
if (!FF_ALLOCZ_TYPED_ARRAY(sc->edge_emu_buffer, alloc_size * EMU_EDGE_HEIGHT) ||
|
||||
!FF_ALLOCZ_TYPED_ARRAY(me->scratchpad, alloc_size * 4 * 16 * 2))
|
||||
!FF_ALLOCZ_TYPED_ARRAY(me->scratchpad, alloc_size * 4 * 16 * 2)) {
|
||||
av_freep(&sc->edge_emu_buffer);
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
|
||||
me->temp = me->scratchpad;
|
||||
sc->rd_scratchpad = me->scratchpad;
|
||||
sc->b_scratchpad = me->scratchpad;
|
||||
|
||||
+74
-79
@@ -366,13 +366,6 @@ static int init_duplicate_context(MpegEncContext *s)
|
||||
if (s->mb_height & 1)
|
||||
yc_size += 2*s->b8_stride + 2*s->mb_stride;
|
||||
|
||||
s->sc.edge_emu_buffer =
|
||||
s->me.scratchpad =
|
||||
s->me.temp =
|
||||
s->sc.rd_scratchpad =
|
||||
s->sc.b_scratchpad =
|
||||
s->sc.obmc_scratchpad = NULL;
|
||||
|
||||
if (s->encoding) {
|
||||
if (!FF_ALLOCZ_TYPED_ARRAY(s->me.map, ME_MAP_SIZE) ||
|
||||
!FF_ALLOCZ_TYPED_ARRAY(s->me.score_map, ME_MAP_SIZE))
|
||||
@@ -413,6 +406,35 @@ static int init_duplicate_context(MpegEncContext *s)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize an MpegEncContext's thread contexts. Presumes that
|
||||
* slice_context_count is already set and that all the fields
|
||||
* that are freed/reset in free_duplicate_context() are NULL.
|
||||
*/
|
||||
static int init_duplicate_contexts(MpegEncContext *s)
|
||||
{
|
||||
int nb_slices = s->slice_context_count, ret;
|
||||
|
||||
/* We initialize the copies before the original so that
|
||||
* fields allocated in init_duplicate_context are NULL after
|
||||
* copying. This prevents double-frees upon allocation error. */
|
||||
for (int i = 1; i < nb_slices; i++) {
|
||||
s->thread_context[i] = av_memdup(s, sizeof(MpegEncContext));
|
||||
if (!s->thread_context[i])
|
||||
return AVERROR(ENOMEM);
|
||||
if ((ret = init_duplicate_context(s->thread_context[i])) < 0)
|
||||
return ret;
|
||||
s->thread_context[i]->start_mb_y =
|
||||
(s->mb_height * (i ) + nb_slices / 2) / nb_slices;
|
||||
s->thread_context[i]->end_mb_y =
|
||||
(s->mb_height * (i + 1) + nb_slices / 2) / nb_slices;
|
||||
}
|
||||
s->start_mb_y = 0;
|
||||
s->end_mb_y = nb_slices > 1 ? (s->mb_height + nb_slices / 2) / nb_slices
|
||||
: s->mb_height;
|
||||
return init_duplicate_context(s);
|
||||
}
|
||||
|
||||
static void free_duplicate_context(MpegEncContext *s)
|
||||
{
|
||||
if (!s)
|
||||
@@ -435,6 +457,15 @@ static void free_duplicate_context(MpegEncContext *s)
|
||||
s->block = NULL;
|
||||
}
|
||||
|
||||
static void free_duplicate_contexts(MpegEncContext *s)
|
||||
{
|
||||
for (int i = 1; i < s->slice_context_count; i++) {
|
||||
free_duplicate_context(s->thread_context[i]);
|
||||
av_freep(&s->thread_context[i]);
|
||||
}
|
||||
free_duplicate_context(s);
|
||||
}
|
||||
|
||||
static void backup_duplicate_context(MpegEncContext *bak, MpegEncContext *src)
|
||||
{
|
||||
#define COPY(a) bak->a = src->a
|
||||
@@ -524,7 +555,6 @@ int ff_mpeg_update_thread_context(AVCodecContext *dst,
|
||||
}
|
||||
|
||||
if (s->height != s1->height || s->width != s1->width || s->context_reinit) {
|
||||
s->context_reinit = 0;
|
||||
s->height = s1->height;
|
||||
s->width = s1->width;
|
||||
if ((ret = ff_mpv_common_frame_size_change(s)) < 0)
|
||||
@@ -932,53 +962,42 @@ av_cold int ff_mpv_common_init(MpegEncContext *s)
|
||||
for (i = 0; i < MAX_PICTURE_COUNT; i++) {
|
||||
s->picture[i].f = av_frame_alloc();
|
||||
if (!s->picture[i].f)
|
||||
return AVERROR(ENOMEM);
|
||||
goto fail_nomem;
|
||||
}
|
||||
|
||||
if (!(s->next_picture.f = av_frame_alloc()) ||
|
||||
!(s->last_picture.f = av_frame_alloc()) ||
|
||||
!(s->current_picture.f = av_frame_alloc()) ||
|
||||
!(s->new_picture.f = av_frame_alloc()))
|
||||
return AVERROR(ENOMEM);
|
||||
goto fail_nomem;
|
||||
|
||||
if ((ret = init_context_frame(s)))
|
||||
return AVERROR(ENOMEM);
|
||||
goto fail;
|
||||
|
||||
s->parse_context.state = -1;
|
||||
|
||||
s->context_initialized = 1;
|
||||
memset(s->thread_context, 0, sizeof(s->thread_context));
|
||||
s->thread_context[0] = s;
|
||||
s->slice_context_count = nb_slices;
|
||||
|
||||
// if (s->width && s->height) {
|
||||
if (nb_slices > 1) {
|
||||
for (i = 0; i < nb_slices; i++) {
|
||||
if (i) {
|
||||
s->thread_context[i] = av_memdup(s, sizeof(MpegEncContext));
|
||||
if (!s->thread_context[i])
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
if ((ret = init_duplicate_context(s->thread_context[i])) < 0)
|
||||
return ret;
|
||||
s->thread_context[i]->start_mb_y =
|
||||
(s->mb_height * (i) + nb_slices / 2) / nb_slices;
|
||||
s->thread_context[i]->end_mb_y =
|
||||
(s->mb_height * (i + 1) + nb_slices / 2) / nb_slices;
|
||||
}
|
||||
} else {
|
||||
if ((ret = init_duplicate_context(s)) < 0)
|
||||
return ret;
|
||||
s->start_mb_y = 0;
|
||||
s->end_mb_y = s->mb_height;
|
||||
}
|
||||
s->slice_context_count = nb_slices;
|
||||
ret = init_duplicate_contexts(s);
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
// }
|
||||
|
||||
return 0;
|
||||
fail_nomem:
|
||||
ret = AVERROR(ENOMEM);
|
||||
fail:
|
||||
ff_mpv_common_end(s);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees and resets MpegEncContext fields depending on the resolution.
|
||||
* Frees and resets MpegEncContext fields depending on the resolution
|
||||
* as well as the slice thread contexts.
|
||||
* Is used during resolution changes to avoid a full reinitialization of the
|
||||
* codec.
|
||||
*/
|
||||
@@ -986,6 +1005,8 @@ static void free_context_frame(MpegEncContext *s)
|
||||
{
|
||||
int i, j, k;
|
||||
|
||||
free_duplicate_contexts(s);
|
||||
|
||||
av_freep(&s->mb_type);
|
||||
av_freep(&s->p_mv_table_base);
|
||||
av_freep(&s->b_forw_mv_table_base);
|
||||
@@ -1038,16 +1059,6 @@ int ff_mpv_common_frame_size_change(MpegEncContext *s)
|
||||
if (!s->context_initialized)
|
||||
return AVERROR(EINVAL);
|
||||
|
||||
if (s->slice_context_count > 1) {
|
||||
for (i = 0; i < s->slice_context_count; i++) {
|
||||
free_duplicate_context(s->thread_context[i]);
|
||||
}
|
||||
for (i = 1; i < s->slice_context_count; i++) {
|
||||
av_freep(&s->thread_context[i]);
|
||||
}
|
||||
} else
|
||||
free_duplicate_context(s);
|
||||
|
||||
free_context_frame(s);
|
||||
|
||||
if (s->picture)
|
||||
@@ -1067,42 +1078,33 @@ int ff_mpv_common_frame_size_change(MpegEncContext *s)
|
||||
|
||||
if ((s->width || s->height) &&
|
||||
(err = av_image_check_size(s->width, s->height, 0, s->avctx)) < 0)
|
||||
return err;
|
||||
goto fail;
|
||||
|
||||
/* set chroma shifts */
|
||||
err = av_pix_fmt_get_chroma_sub_sample(s->avctx->pix_fmt,
|
||||
&s->chroma_x_shift,
|
||||
&s->chroma_y_shift);
|
||||
if (err < 0)
|
||||
goto fail;
|
||||
|
||||
if ((err = init_context_frame(s)))
|
||||
return err;
|
||||
goto fail;
|
||||
|
||||
memset(s->thread_context, 0, sizeof(s->thread_context));
|
||||
s->thread_context[0] = s;
|
||||
|
||||
if (s->width && s->height) {
|
||||
int nb_slices = s->slice_context_count;
|
||||
if (nb_slices > 1) {
|
||||
for (i = 0; i < nb_slices; i++) {
|
||||
if (i) {
|
||||
s->thread_context[i] = av_memdup(s, sizeof(MpegEncContext));
|
||||
if (!s->thread_context[i]) {
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
}
|
||||
if ((err = init_duplicate_context(s->thread_context[i])) < 0)
|
||||
return err;
|
||||
s->thread_context[i]->start_mb_y =
|
||||
(s->mb_height * (i) + nb_slices / 2) / nb_slices;
|
||||
s->thread_context[i]->end_mb_y =
|
||||
(s->mb_height * (i + 1) + nb_slices / 2) / nb_slices;
|
||||
}
|
||||
} else {
|
||||
err = init_duplicate_context(s);
|
||||
if (err < 0)
|
||||
return err;
|
||||
s->start_mb_y = 0;
|
||||
s->end_mb_y = s->mb_height;
|
||||
}
|
||||
s->slice_context_count = nb_slices;
|
||||
err = init_duplicate_contexts(s);
|
||||
if (err < 0)
|
||||
goto fail;
|
||||
}
|
||||
s->context_reinit = 0;
|
||||
|
||||
return 0;
|
||||
fail:
|
||||
free_context_frame(s);
|
||||
s->context_reinit = 1;
|
||||
return err;
|
||||
}
|
||||
|
||||
/* init common structure for both encoder and decoder */
|
||||
@@ -1113,15 +1115,9 @@ void ff_mpv_common_end(MpegEncContext *s)
|
||||
if (!s)
|
||||
return;
|
||||
|
||||
if (s->slice_context_count > 1) {
|
||||
for (i = 0; i < s->slice_context_count; i++) {
|
||||
free_duplicate_context(s->thread_context[i]);
|
||||
}
|
||||
for (i = 1; i < s->slice_context_count; i++) {
|
||||
av_freep(&s->thread_context[i]);
|
||||
}
|
||||
free_context_frame(s);
|
||||
if (s->slice_context_count > 1)
|
||||
s->slice_context_count = 1;
|
||||
} else free_duplicate_context(s);
|
||||
|
||||
av_freep(&s->parse_context.buffer);
|
||||
s->parse_context.buffer_size = 0;
|
||||
@@ -1153,9 +1149,8 @@ void ff_mpv_common_end(MpegEncContext *s)
|
||||
ff_mpeg_unref_picture(s->avctx, &s->new_picture);
|
||||
av_frame_free(&s->new_picture.f);
|
||||
|
||||
free_context_frame(s);
|
||||
|
||||
s->context_initialized = 0;
|
||||
s->context_reinit = 0;
|
||||
s->last_picture_ptr =
|
||||
s->next_picture_ptr =
|
||||
s->current_picture_ptr = NULL;
|
||||
|
||||
@@ -627,7 +627,7 @@ FF_ENABLE_DEPRECATION_WARNINGS
|
||||
#if FF_API_PRIVATE_OPT
|
||||
FF_DISABLE_DEPRECATION_WARNINGS
|
||||
if (avctx->mpeg_quant)
|
||||
s->mpeg_quant = avctx->mpeg_quant;
|
||||
s->mpeg_quant = 1;
|
||||
FF_ENABLE_DEPRECATION_WARNINGS
|
||||
#endif
|
||||
|
||||
@@ -1008,8 +1008,7 @@ FF_ENABLE_DEPRECATION_WARNINGS
|
||||
if (CONFIG_H263_ENCODER && s->out_format == FMT_H263)
|
||||
ff_h263_encode_init(s);
|
||||
if (CONFIG_MSMPEG4_ENCODER && s->msmpeg4_version)
|
||||
if ((ret = ff_msmpeg4_encode_init(s)) < 0)
|
||||
return ret;
|
||||
ff_msmpeg4_encode_init(s);
|
||||
if ((CONFIG_MPEG1VIDEO_ENCODER || CONFIG_MPEG2VIDEO_ENCODER)
|
||||
&& s->out_format == FMT_MPEG1)
|
||||
ff_mpeg1_encode_init(s);
|
||||
@@ -1696,7 +1695,8 @@ no_output_pic:
|
||||
// input is not a shared pix -> reuse buffer for current_pix
|
||||
s->current_picture_ptr = s->reordered_input_picture[0];
|
||||
for (i = 0; i < 4; i++) {
|
||||
s->new_picture.f->data[i] += INPLACE_OFFSET;
|
||||
if (s->new_picture.f->data[i])
|
||||
s->new_picture.f->data[i] += INPLACE_OFFSET;
|
||||
}
|
||||
}
|
||||
ff_mpeg_unref_picture(s->avctx, &s->current_picture);
|
||||
|
||||
@@ -50,7 +50,7 @@ void ff_msmpeg4_encode_motion(MpegEncContext * s, int mx, int my);
|
||||
int ff_msmpeg4_coded_block_pred(MpegEncContext * s, int n,
|
||||
uint8_t **coded_block_ptr);
|
||||
|
||||
int ff_msmpeg4_encode_init(MpegEncContext *s);
|
||||
void ff_msmpeg4_encode_init(MpegEncContext *s);
|
||||
void ff_msmpeg4_encode_picture_header(MpegEncContext *s, int picture_number);
|
||||
void ff_msmpeg4_encode_ext_header(MpegEncContext *s);
|
||||
void ff_msmpeg4_encode_mb(MpegEncContext *s, int16_t block[6][64],
|
||||
|
||||
@@ -870,7 +870,7 @@ AVCodec ff_msmpeg4v1_decoder = {
|
||||
.close = ff_h263_decode_end,
|
||||
.decode = ff_h263_decode_frame,
|
||||
.capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1,
|
||||
.caps_internal = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM | FF_CODEC_CAP_INIT_CLEANUP,
|
||||
.caps_internal = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM,
|
||||
.max_lowres = 3,
|
||||
.pix_fmts = (const enum AVPixelFormat[]) {
|
||||
AV_PIX_FMT_YUV420P,
|
||||
@@ -888,7 +888,7 @@ AVCodec ff_msmpeg4v2_decoder = {
|
||||
.close = ff_h263_decode_end,
|
||||
.decode = ff_h263_decode_frame,
|
||||
.capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1,
|
||||
.caps_internal = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM | FF_CODEC_CAP_INIT_CLEANUP,
|
||||
.caps_internal = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM,
|
||||
.max_lowres = 3,
|
||||
.pix_fmts = (const enum AVPixelFormat[]) {
|
||||
AV_PIX_FMT_YUV420P,
|
||||
@@ -906,7 +906,7 @@ AVCodec ff_msmpeg4v3_decoder = {
|
||||
.close = ff_h263_decode_end,
|
||||
.decode = ff_h263_decode_frame,
|
||||
.capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1,
|
||||
.caps_internal = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM | FF_CODEC_CAP_INIT_CLEANUP,
|
||||
.caps_internal = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM,
|
||||
.max_lowres = 3,
|
||||
.pix_fmts = (const enum AVPixelFormat[]) {
|
||||
AV_PIX_FMT_YUV420P,
|
||||
@@ -924,7 +924,7 @@ AVCodec ff_wmv1_decoder = {
|
||||
.close = ff_h263_decode_end,
|
||||
.decode = ff_h263_decode_frame,
|
||||
.capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1,
|
||||
.caps_internal = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM | FF_CODEC_CAP_INIT_CLEANUP,
|
||||
.caps_internal = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM,
|
||||
.max_lowres = 3,
|
||||
.pix_fmts = (const enum AVPixelFormat[]) {
|
||||
AV_PIX_FMT_YUV420P,
|
||||
|
||||
+8
-15
@@ -32,7 +32,6 @@
|
||||
|
||||
#include "libavutil/attributes.h"
|
||||
#include "libavutil/avutil.h"
|
||||
#include "libavutil/mem.h"
|
||||
#include "mpegvideo.h"
|
||||
#include "h263.h"
|
||||
#include "internal.h"
|
||||
@@ -46,13 +45,11 @@
|
||||
static uint8_t rl_length[NB_RL_TABLES][MAX_LEVEL+1][MAX_RUN+1][2];
|
||||
|
||||
/* build the table which associate a (x,y) motion vector to a vlc */
|
||||
static av_cold int init_mv_table(MVTable *tab)
|
||||
static av_cold void init_mv_table(MVTable *tab, uint16_t table_mv_index[4096])
|
||||
{
|
||||
int i, x, y;
|
||||
|
||||
tab->table_mv_index = av_malloc(sizeof(uint16_t) * 4096);
|
||||
if (!tab->table_mv_index)
|
||||
return AVERROR(ENOMEM);
|
||||
tab->table_mv_index = table_mv_index;
|
||||
|
||||
/* mark all entries as not used */
|
||||
for(i=0;i<4096;i++)
|
||||
@@ -63,8 +60,6 @@ static av_cold int init_mv_table(MVTable *tab)
|
||||
y = tab->table_mvy[i];
|
||||
tab->table_mv_index[(x << 6) | y] = i;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ff_msmpeg4_code012(PutBitContext *pb, int n)
|
||||
@@ -118,10 +113,10 @@ static int get_size_of_code(MpegEncContext * s, RLTable *rl, int last, int run,
|
||||
return size;
|
||||
}
|
||||
|
||||
av_cold int ff_msmpeg4_encode_init(MpegEncContext *s)
|
||||
av_cold void ff_msmpeg4_encode_init(MpegEncContext *s)
|
||||
{
|
||||
static int init_done=0;
|
||||
int i, ret;
|
||||
int i;
|
||||
|
||||
ff_msmpeg4_common_init(s);
|
||||
if(s->msmpeg4_version>=4){
|
||||
@@ -130,12 +125,12 @@ av_cold int ff_msmpeg4_encode_init(MpegEncContext *s)
|
||||
}
|
||||
|
||||
if (!init_done) {
|
||||
static uint16_t mv_index_tables[2][4096];
|
||||
/* init various encoding tables */
|
||||
init_done = 1;
|
||||
if ((ret = init_mv_table(&ff_mv_tables[0])) < 0)
|
||||
return ret;
|
||||
if ((ret = init_mv_table(&ff_mv_tables[1])) < 0)
|
||||
return ret;
|
||||
init_mv_table(&ff_mv_tables[0], mv_index_tables[0]);
|
||||
init_mv_table(&ff_mv_tables[1], mv_index_tables[1]);
|
||||
|
||||
for(i=0;i<NB_RL_TABLES;i++)
|
||||
ff_rl_init(&ff_rl_table[i], ff_static_rl_table_store[i]);
|
||||
|
||||
@@ -152,8 +147,6 @@ av_cold int ff_msmpeg4_encode_init(MpegEncContext *s)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void find_best_tables(MpegEncContext * s)
|
||||
|
||||
@@ -71,6 +71,7 @@ static int msp2_decode_frame(AVCodecContext *avctx,
|
||||
while (bytestream2_get_bytes_left(&gb) && x < width) {
|
||||
int size = bytestream2_get_byte(&gb);
|
||||
if (size) {
|
||||
size = FFMIN(size, bytestream2_get_bytes_left(&gb));
|
||||
memcpy(p->data[0] + y * p->linesize[0] + x, gb.buffer, FFMIN(size, width - x));
|
||||
bytestream2_skip(&gb, size);
|
||||
} else {
|
||||
|
||||
+10
-7
@@ -291,14 +291,15 @@ static int decode_pixel_in_context(ArithCoder *acoder, PixContext *pctx,
|
||||
return decode_pixel(acoder, pctx, ref_pix, nlen, 1);
|
||||
}
|
||||
|
||||
static int decode_region(ArithCoder *acoder, uint8_t *dst, uint8_t *rgb_pic,
|
||||
static int decode_region(ArithCoder *acoder, uint8_t *dst, uint8_t *rgb_dst,
|
||||
int x, int y, int width, int height, ptrdiff_t stride,
|
||||
ptrdiff_t rgb_stride, PixContext *pctx,
|
||||
const uint32_t *pal)
|
||||
{
|
||||
int i, j, p;
|
||||
uint8_t *rgb_dst = rgb_pic + x * 3 + y * rgb_stride;
|
||||
|
||||
rgb_stride = rgb_dst ? rgb_stride : 0;
|
||||
rgb_dst = rgb_dst ? rgb_dst + x * 3 + y * rgb_stride : NULL;
|
||||
dst += x + y * stride;
|
||||
|
||||
for (j = 0; j < height; j++) {
|
||||
@@ -312,11 +313,11 @@ static int decode_region(ArithCoder *acoder, uint8_t *dst, uint8_t *rgb_pic,
|
||||
return p;
|
||||
dst[i] = p;
|
||||
|
||||
if (rgb_pic)
|
||||
if (rgb_dst)
|
||||
AV_WB24(rgb_dst + i * 3, pal[p]);
|
||||
}
|
||||
dst += stride;
|
||||
rgb_dst += rgb_stride;
|
||||
rgb_dst = FF_PTR_ADD(rgb_dst, rgb_stride);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -476,17 +477,19 @@ static int decode_region_intra(SliceContext *sc, ArithCoder *acoder,
|
||||
ptrdiff_t stride = c->pal_stride;
|
||||
ptrdiff_t rgb_stride = c->rgb_stride;
|
||||
uint8_t *dst = c->pal_pic + x + y * stride;
|
||||
uint8_t *rgb_dst = c->rgb_pic + x * 3 + y * rgb_stride;
|
||||
uint8_t *rgb_dst = c->rgb_pic ? c->rgb_pic + x * 3 + y * rgb_stride : NULL;
|
||||
|
||||
pix = decode_pixel(acoder, &sc->intra_pix_ctx, NULL, 0, 0);
|
||||
if (pix < 0)
|
||||
return pix;
|
||||
rgb_pix = c->pal[pix];
|
||||
for (i = 0; i < height; i++, dst += stride, rgb_dst += rgb_stride) {
|
||||
for (i = 0; i < height; i++, dst += stride) {
|
||||
memset(dst, pix, width);
|
||||
if (c->rgb_pic)
|
||||
if (rgb_dst) {
|
||||
for (j = 0; j < width * 3; j += 3)
|
||||
AV_WB24(rgb_dst + j, rgb_pix);
|
||||
rgb_dst += rgb_stride;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return decode_region(acoder, c->pal_pic, c->rgb_pic,
|
||||
|
||||
@@ -179,6 +179,9 @@ int av_parser_parse2(AVCodecParserContext *s, AVCodecContext *avctx,
|
||||
/* offset of the next frame */
|
||||
s->next_frame_offset = s->cur_offset + index;
|
||||
s->fetch_timestamp = 1;
|
||||
} else {
|
||||
/* Don't return a pointer to dummy_buf. */
|
||||
*poutbuf = NULL;
|
||||
}
|
||||
if (index < 0)
|
||||
index = 0;
|
||||
|
||||
+173
-90
@@ -57,6 +57,18 @@ typedef struct PNGDecContext {
|
||||
ThreadFrame last_picture;
|
||||
ThreadFrame picture;
|
||||
|
||||
AVDictionary *frame_metadata;
|
||||
|
||||
uint8_t iccp_name[82];
|
||||
uint8_t *iccp_data;
|
||||
size_t iccp_data_len;
|
||||
|
||||
int stereo_mode;
|
||||
|
||||
int have_chrm;
|
||||
uint32_t white_point[2];
|
||||
uint32_t display_primaries[3][2];
|
||||
|
||||
enum PNGHeaderState hdr_state;
|
||||
enum PNGImageState pic_state;
|
||||
int width, height;
|
||||
@@ -77,8 +89,8 @@ typedef struct PNGDecContext {
|
||||
int has_trns;
|
||||
uint8_t transparent_color_be[6];
|
||||
|
||||
uint8_t *image_buf;
|
||||
int image_linesize;
|
||||
uint8_t *background_buf;
|
||||
unsigned background_buf_allocated;
|
||||
uint32_t palette[256];
|
||||
uint8_t *crow_buf;
|
||||
uint8_t *last_row;
|
||||
@@ -330,27 +342,27 @@ static int percent_missing(PNGDecContext *s)
|
||||
}
|
||||
|
||||
/* process exactly one decompressed row */
|
||||
static void png_handle_row(PNGDecContext *s)
|
||||
static void png_handle_row(PNGDecContext *s, uint8_t *dst, ptrdiff_t dst_stride)
|
||||
{
|
||||
uint8_t *ptr, *last_row;
|
||||
int got_line;
|
||||
|
||||
if (!s->interlace_type) {
|
||||
ptr = s->image_buf + s->image_linesize * (s->y + s->y_offset) + s->x_offset * s->bpp;
|
||||
ptr = dst + dst_stride * (s->y + s->y_offset) + s->x_offset * s->bpp;
|
||||
if (s->y == 0)
|
||||
last_row = s->last_row;
|
||||
else
|
||||
last_row = ptr - s->image_linesize;
|
||||
last_row = ptr - dst_stride;
|
||||
|
||||
ff_png_filter_row(&s->dsp, ptr, s->crow_buf[0], s->crow_buf + 1,
|
||||
last_row, s->row_size, s->bpp);
|
||||
/* loco lags by 1 row so that it doesn't interfere with top prediction */
|
||||
if (s->filter_type == PNG_FILTER_TYPE_LOCO && s->y > 0) {
|
||||
if (s->bit_depth == 16) {
|
||||
deloco_rgb16((uint16_t *)(ptr - s->image_linesize), s->row_size / 2,
|
||||
deloco_rgb16((uint16_t *)(ptr - dst_stride), s->row_size / 2,
|
||||
s->color_type == PNG_COLOR_TYPE_RGB_ALPHA);
|
||||
} else {
|
||||
deloco_rgb8(ptr - s->image_linesize, s->row_size,
|
||||
deloco_rgb8(ptr - dst_stride, s->row_size,
|
||||
s->color_type == PNG_COLOR_TYPE_RGB_ALPHA);
|
||||
}
|
||||
}
|
||||
@@ -370,7 +382,7 @@ static void png_handle_row(PNGDecContext *s)
|
||||
} else {
|
||||
got_line = 0;
|
||||
for (;;) {
|
||||
ptr = s->image_buf + s->image_linesize * (s->y + s->y_offset) + s->x_offset * s->bpp;
|
||||
ptr = dst + dst_stride * (s->y + s->y_offset) + s->x_offset * s->bpp;
|
||||
if ((ff_png_pass_ymask[s->pass] << (s->y & 7)) & 0x80) {
|
||||
/* if we already read one row, it is time to stop to
|
||||
* wait for the next one */
|
||||
@@ -411,7 +423,8 @@ the_end:;
|
||||
}
|
||||
}
|
||||
|
||||
static int png_decode_idat(PNGDecContext *s, int length)
|
||||
static int png_decode_idat(PNGDecContext *s, int length,
|
||||
uint8_t *dst, ptrdiff_t dst_stride)
|
||||
{
|
||||
int ret;
|
||||
s->zstream.avail_in = FFMIN(length, bytestream2_get_bytes_left(&s->gb));
|
||||
@@ -427,7 +440,7 @@ static int png_decode_idat(PNGDecContext *s, int length)
|
||||
}
|
||||
if (s->zstream.avail_out == 0) {
|
||||
if (!(s->pic_state & PNG_ALLIMAGE)) {
|
||||
png_handle_row(s);
|
||||
png_handle_row(s, dst, dst_stride);
|
||||
}
|
||||
s->zstream.avail_out = s->crow_size;
|
||||
s->zstream.next_out = s->crow_buf;
|
||||
@@ -509,8 +522,7 @@ static uint8_t *iso88591_to_utf8(const uint8_t *in, size_t size_in)
|
||||
return out;
|
||||
}
|
||||
|
||||
static int decode_text_chunk(PNGDecContext *s, uint32_t length, int compressed,
|
||||
AVDictionary **dict)
|
||||
static int decode_text_chunk(PNGDecContext *s, uint32_t length, int compressed)
|
||||
{
|
||||
int ret, method;
|
||||
const uint8_t *data = s->gb.buffer;
|
||||
@@ -552,7 +564,7 @@ static int decode_text_chunk(PNGDecContext *s, uint32_t length, int compressed,
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
|
||||
av_dict_set(dict, kw_utf8, txt_utf8,
|
||||
av_dict_set(&s->frame_metadata, kw_utf8, txt_utf8,
|
||||
AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);
|
||||
return 0;
|
||||
}
|
||||
@@ -732,8 +744,7 @@ static int decode_idat_chunk(AVCodecContext *avctx, PNGDecContext *s,
|
||||
}
|
||||
ff_dlog(avctx, "row_size=%d crow_size =%d\n",
|
||||
s->row_size, s->crow_size);
|
||||
s->image_buf = p->data[0];
|
||||
s->image_linesize = p->linesize[0];
|
||||
|
||||
/* copy the palette if needed */
|
||||
if (avctx->pix_fmt == AV_PIX_FMT_PAL8)
|
||||
memcpy(p->data[1], s->palette, 256 * sizeof(uint32_t));
|
||||
@@ -764,7 +775,7 @@ static int decode_idat_chunk(AVCodecContext *avctx, PNGDecContext *s,
|
||||
if (s->has_trns && s->color_type != PNG_COLOR_TYPE_PALETTE)
|
||||
s->bpp -= byte_depth;
|
||||
|
||||
ret = png_decode_idat(s, length);
|
||||
ret = png_decode_idat(s, length, p->data[0], p->linesize[0]);
|
||||
|
||||
if (s->has_trns && s->color_type != PNG_COLOR_TYPE_PALETTE)
|
||||
s->bpp += byte_depth;
|
||||
@@ -851,21 +862,21 @@ static int decode_trns_chunk(AVCodecContext *avctx, PNGDecContext *s,
|
||||
static int decode_iccp_chunk(PNGDecContext *s, int length, AVFrame *f)
|
||||
{
|
||||
int ret, cnt = 0;
|
||||
uint8_t *data, profile_name[82];
|
||||
AVBPrint bp;
|
||||
AVFrameSideData *sd;
|
||||
|
||||
while ((profile_name[cnt++] = bytestream2_get_byte(&s->gb)) && cnt < 81);
|
||||
while ((s->iccp_name[cnt++] = bytestream2_get_byte(&s->gb)) && cnt < 81);
|
||||
if (cnt > 80) {
|
||||
av_log(s->avctx, AV_LOG_ERROR, "iCCP with invalid name!\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
ret = AVERROR_INVALIDDATA;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
length = FFMAX(length - cnt, 0);
|
||||
|
||||
if (bytestream2_get_byte(&s->gb) != 0) {
|
||||
av_log(s->avctx, AV_LOG_ERROR, "iCCP with invalid compression!\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
ret = AVERROR_INVALIDDATA;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
length = FFMAX(length - 1, 0);
|
||||
@@ -873,24 +884,19 @@ static int decode_iccp_chunk(PNGDecContext *s, int length, AVFrame *f)
|
||||
if ((ret = decode_zbuf(&bp, s->gb.buffer, s->gb.buffer + length)) < 0)
|
||||
return ret;
|
||||
|
||||
ret = av_bprint_finalize(&bp, (char **)&data);
|
||||
av_freep(&s->iccp_data);
|
||||
ret = av_bprint_finalize(&bp, (char **)&s->iccp_data);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
sd = av_frame_new_side_data(f, AV_FRAME_DATA_ICC_PROFILE, bp.len);
|
||||
if (!sd) {
|
||||
av_free(data);
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
|
||||
av_dict_set(&sd->metadata, "name", profile_name, 0);
|
||||
memcpy(sd->data, data, bp.len);
|
||||
av_free(data);
|
||||
s->iccp_data_len = bp.len;
|
||||
|
||||
/* ICC compressed data and CRC */
|
||||
bytestream2_skip(&s->gb, length + 4);
|
||||
|
||||
return 0;
|
||||
fail:
|
||||
s->iccp_name[0] = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void handle_small_bpp(PNGDecContext *s, AVFrame *p)
|
||||
@@ -913,7 +919,7 @@ static void handle_small_bpp(PNGDecContext *s, AVFrame *p)
|
||||
pd[8*i + 1]= (pd[i]>>6) & 1;
|
||||
pd[8*i + 0]= pd[i]>>7;
|
||||
}
|
||||
pd += s->image_linesize;
|
||||
pd += p->linesize[0];
|
||||
}
|
||||
} else if (s->bits_per_pixel == 2) {
|
||||
int i, j;
|
||||
@@ -941,7 +947,7 @@ static void handle_small_bpp(PNGDecContext *s, AVFrame *p)
|
||||
pd[4*i + 0]= ( pd[i]>>6 )*0x55;
|
||||
}
|
||||
}
|
||||
pd += s->image_linesize;
|
||||
pd += p->linesize[0];
|
||||
}
|
||||
} else if (s->bits_per_pixel == 4) {
|
||||
int i, j;
|
||||
@@ -961,7 +967,7 @@ static void handle_small_bpp(PNGDecContext *s, AVFrame *p)
|
||||
pd[2*i + 0] = (pd[i] >> 4) * 0x11;
|
||||
}
|
||||
}
|
||||
pd += s->image_linesize;
|
||||
pd += p->linesize[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1056,8 +1062,8 @@ static void handle_p_frame_png(PNGDecContext *s, AVFrame *p)
|
||||
for (j = 0; j < s->height; j++) {
|
||||
for (i = 0; i < ls; i++)
|
||||
pd[i] += pd_last[i];
|
||||
pd += s->image_linesize;
|
||||
pd_last += s->image_linesize;
|
||||
pd += p->linesize[0];
|
||||
pd_last += s->last_picture.f->linesize[0];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1068,8 +1074,12 @@ static void handle_p_frame_png(PNGDecContext *s, AVFrame *p)
|
||||
static int handle_p_frame_apng(AVCodecContext *avctx, PNGDecContext *s,
|
||||
AVFrame *p)
|
||||
{
|
||||
uint8_t *dst = p->data[0];
|
||||
ptrdiff_t dst_stride = p->linesize[0];
|
||||
const uint8_t *src = s->last_picture.f->data[0];
|
||||
ptrdiff_t src_stride = s->last_picture.f->linesize[0];
|
||||
|
||||
size_t x, y;
|
||||
uint8_t *buffer;
|
||||
|
||||
if (s->blend_op == APNG_BLEND_OP_OVER &&
|
||||
avctx->pix_fmt != AV_PIX_FMT_RGBA &&
|
||||
@@ -1083,32 +1093,39 @@ static int handle_p_frame_apng(AVCodecContext *avctx, PNGDecContext *s,
|
||||
ff_thread_await_progress(&s->last_picture, INT_MAX, 0);
|
||||
|
||||
// need to reset a rectangle to background:
|
||||
// create a new writable copy
|
||||
if (s->last_dispose_op == APNG_DISPOSE_OP_BACKGROUND) {
|
||||
int ret = av_frame_make_writable(s->last_picture.f);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
av_fast_malloc(&s->background_buf, &s->background_buf_allocated,
|
||||
src_stride * p->height);
|
||||
if (!s->background_buf)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
memcpy(s->background_buf, src, src_stride * p->height);
|
||||
|
||||
for (y = s->last_y_offset; y < s->last_y_offset + s->last_h; y++) {
|
||||
memset(s->last_picture.f->data[0] + s->image_linesize * y +
|
||||
memset(s->background_buf + src_stride * y +
|
||||
s->bpp * s->last_x_offset, 0, s->bpp * s->last_w);
|
||||
}
|
||||
|
||||
src = s->background_buf;
|
||||
}
|
||||
|
||||
buffer = av_memdup(s->last_picture.f->data[0], s->image_linesize * s->height);
|
||||
if (!buffer)
|
||||
return AVERROR(ENOMEM);
|
||||
// copy unchanged rectangles from the last frame
|
||||
for (y = 0; y < s->y_offset; y++)
|
||||
memcpy(dst + y * dst_stride, src + y * src_stride, p->width * s->bpp);
|
||||
for (y = s->y_offset; y < s->y_offset + s->cur_h; y++) {
|
||||
memcpy(dst + y * dst_stride, src + y * src_stride, s->x_offset * s->bpp);
|
||||
memcpy(dst + y * dst_stride + (s->x_offset + s->cur_w) * s->bpp,
|
||||
src + y * src_stride + (s->x_offset + s->cur_w) * s->bpp,
|
||||
(p->width - s->cur_w - s->x_offset) * s->bpp);
|
||||
}
|
||||
for (y = s->y_offset + s->cur_h; y < p->height; y++)
|
||||
memcpy(dst + y * dst_stride, src + y * src_stride, p->width * s->bpp);
|
||||
|
||||
// Perform blending
|
||||
if (s->blend_op == APNG_BLEND_OP_SOURCE) {
|
||||
if (s->blend_op == APNG_BLEND_OP_OVER) {
|
||||
// Perform blending
|
||||
for (y = s->y_offset; y < s->y_offset + s->cur_h; ++y) {
|
||||
size_t row_start = s->image_linesize * y + s->bpp * s->x_offset;
|
||||
memcpy(buffer + row_start, p->data[0] + row_start, s->bpp * s->cur_w);
|
||||
}
|
||||
} else { // APNG_BLEND_OP_OVER
|
||||
for (y = s->y_offset; y < s->y_offset + s->cur_h; ++y) {
|
||||
uint8_t *foreground = p->data[0] + s->image_linesize * y + s->bpp * s->x_offset;
|
||||
uint8_t *background = buffer + s->image_linesize * y + s->bpp * s->x_offset;
|
||||
uint8_t *foreground = dst + dst_stride * y + s->bpp * s->x_offset;
|
||||
const uint8_t *background = src + src_stride * y + s->bpp * s->x_offset;
|
||||
for (x = s->x_offset; x < s->x_offset + s->cur_w; ++x, foreground += s->bpp, background += s->bpp) {
|
||||
size_t b;
|
||||
uint8_t foreground_alpha, background_alpha, output_alpha;
|
||||
@@ -1135,18 +1152,17 @@ static int handle_p_frame_apng(AVCodecContext *avctx, PNGDecContext *s,
|
||||
break;
|
||||
}
|
||||
|
||||
if (foreground_alpha == 0)
|
||||
if (foreground_alpha == 255)
|
||||
continue;
|
||||
|
||||
if (foreground_alpha == 255) {
|
||||
memcpy(background, foreground, s->bpp);
|
||||
if (foreground_alpha == 0) {
|
||||
memcpy(foreground, background, s->bpp);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (avctx->pix_fmt == AV_PIX_FMT_PAL8) {
|
||||
// TODO: Alpha blending with PAL8 will likely need the entire image converted over to RGBA first
|
||||
avpriv_request_sample(avctx, "Alpha blending palette samples");
|
||||
background[0] = foreground[0];
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1164,15 +1180,11 @@ static int handle_p_frame_apng(AVCodecContext *avctx, PNGDecContext *s,
|
||||
}
|
||||
}
|
||||
output[b] = output_alpha;
|
||||
memcpy(background, output, s->bpp);
|
||||
memcpy(foreground, output, s->bpp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Copy blended buffer into the frame and free
|
||||
memcpy(p->data[0], buffer, s->image_linesize * s->height);
|
||||
av_free(buffer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1180,7 +1192,6 @@ static int decode_frame_common(AVCodecContext *avctx, PNGDecContext *s,
|
||||
AVFrame *p, const AVPacket *avpkt)
|
||||
{
|
||||
const AVCRC *crc_tab = av_crc_get_table(AV_CRC_32_IEEE_LE);
|
||||
AVDictionary **metadatap = NULL;
|
||||
uint32_t tag, length;
|
||||
int decode_next_dat = 0;
|
||||
int i, ret;
|
||||
@@ -1209,7 +1220,7 @@ static int decode_frame_common(AVCodecContext *avctx, PNGDecContext *s,
|
||||
}
|
||||
|
||||
length = bytestream2_get_be32(&s->gb);
|
||||
if (length > 0x7fffffff || length > bytestream2_get_bytes_left(&s->gb)) {
|
||||
if (length > 0x7fffffff || length + 8 > bytestream2_get_bytes_left(&s->gb)) {
|
||||
av_log(avctx, AV_LOG_ERROR, "chunk too big\n");
|
||||
ret = AVERROR_INVALIDDATA;
|
||||
goto fail;
|
||||
@@ -1248,7 +1259,6 @@ static int decode_frame_common(AVCodecContext *avctx, PNGDecContext *s,
|
||||
}
|
||||
}
|
||||
|
||||
metadatap = &p->metadata;
|
||||
switch (tag) {
|
||||
case MKTAG('I', 'H', 'D', 'R'):
|
||||
if ((ret = decode_ihdr_chunk(avctx, s, length)) < 0)
|
||||
@@ -1290,26 +1300,20 @@ static int decode_frame_common(AVCodecContext *avctx, PNGDecContext *s,
|
||||
goto skip_tag;
|
||||
break;
|
||||
case MKTAG('t', 'E', 'X', 't'):
|
||||
if (decode_text_chunk(s, length, 0, metadatap) < 0)
|
||||
if (decode_text_chunk(s, length, 0) < 0)
|
||||
av_log(avctx, AV_LOG_WARNING, "Broken tEXt chunk\n");
|
||||
bytestream2_skip(&s->gb, length + 4);
|
||||
break;
|
||||
case MKTAG('z', 'T', 'X', 't'):
|
||||
if (decode_text_chunk(s, length, 1, metadatap) < 0)
|
||||
if (decode_text_chunk(s, length, 1) < 0)
|
||||
av_log(avctx, AV_LOG_WARNING, "Broken zTXt chunk\n");
|
||||
bytestream2_skip(&s->gb, length + 4);
|
||||
break;
|
||||
case MKTAG('s', 'T', 'E', 'R'): {
|
||||
int mode = bytestream2_get_byte(&s->gb);
|
||||
AVStereo3D *stereo3d = av_stereo3d_create_side_data(p);
|
||||
if (!stereo3d) {
|
||||
ret = AVERROR(ENOMEM);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (mode == 0 || mode == 1) {
|
||||
stereo3d->type = AV_STEREO3D_SIDEBYSIDE;
|
||||
stereo3d->flags = mode ? 0 : AV_STEREO3D_FLAG_INVERT;
|
||||
s->stereo_mode = mode;
|
||||
} else {
|
||||
av_log(avctx, AV_LOG_WARNING,
|
||||
"Unknown value in sTER chunk (%d)\n", mode);
|
||||
@@ -1323,22 +1327,17 @@ static int decode_frame_common(AVCodecContext *avctx, PNGDecContext *s,
|
||||
break;
|
||||
}
|
||||
case MKTAG('c', 'H', 'R', 'M'): {
|
||||
AVMasteringDisplayMetadata *mdm = av_mastering_display_metadata_create_side_data(p);
|
||||
if (!mdm) {
|
||||
ret = AVERROR(ENOMEM);
|
||||
goto fail;
|
||||
}
|
||||
s->have_chrm = 1;
|
||||
|
||||
mdm->white_point[0] = av_make_q(bytestream2_get_be32(&s->gb), 100000);
|
||||
mdm->white_point[1] = av_make_q(bytestream2_get_be32(&s->gb), 100000);
|
||||
s->white_point[0] = bytestream2_get_be32(&s->gb);
|
||||
s->white_point[1] = bytestream2_get_be32(&s->gb);
|
||||
|
||||
/* RGB Primaries */
|
||||
for (i = 0; i < 3; i++) {
|
||||
mdm->display_primaries[i][0] = av_make_q(bytestream2_get_be32(&s->gb), 100000);
|
||||
mdm->display_primaries[i][1] = av_make_q(bytestream2_get_be32(&s->gb), 100000);
|
||||
s->display_primaries[i][0] = bytestream2_get_be32(&s->gb);
|
||||
s->display_primaries[i][1] = bytestream2_get_be32(&s->gb);
|
||||
}
|
||||
|
||||
mdm->has_primaries = 1;
|
||||
bytestream2_skip(&s->gb, 4); /* crc */
|
||||
break;
|
||||
}
|
||||
@@ -1353,7 +1352,7 @@ static int decode_frame_common(AVCodecContext *avctx, PNGDecContext *s,
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
av_dict_set(&p->metadata, "gamma", gamma_str, AV_DICT_DONT_STRDUP_VAL);
|
||||
av_dict_set(&s->frame_metadata, "gamma", gamma_str, AV_DICT_DONT_STRDUP_VAL);
|
||||
|
||||
bytestream2_skip(&s->gb, 4); /* crc */
|
||||
break;
|
||||
@@ -1396,7 +1395,7 @@ exit_loop:
|
||||
av_assert0(s->bit_depth > 1);
|
||||
|
||||
for (y = 0; y < s->height; ++y) {
|
||||
uint8_t *row = &s->image_buf[s->image_linesize * y];
|
||||
uint8_t *row = &p->data[0][p->linesize[0] * y];
|
||||
|
||||
if (s->bpp == 2 && byte_depth == 1) {
|
||||
uint8_t *pixel = &row[2 * s->width - 1];
|
||||
@@ -1456,6 +1455,77 @@ fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void clear_frame_metadata(PNGDecContext *s)
|
||||
{
|
||||
av_freep(&s->iccp_data);
|
||||
s->iccp_data_len = 0;
|
||||
s->iccp_name[0] = 0;
|
||||
|
||||
s->stereo_mode = -1;
|
||||
|
||||
s->have_chrm = 0;
|
||||
|
||||
av_dict_free(&s->frame_metadata);
|
||||
}
|
||||
|
||||
static int output_frame(PNGDecContext *s, AVFrame *f,
|
||||
const AVFrame *src)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = av_frame_ref(f, src);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (s->iccp_data) {
|
||||
AVFrameSideData *sd = av_frame_new_side_data(f, AV_FRAME_DATA_ICC_PROFILE, s->iccp_data_len);
|
||||
if (!sd) {
|
||||
ret = AVERROR(ENOMEM);
|
||||
goto fail;
|
||||
}
|
||||
memcpy(sd->data, s->iccp_data, s->iccp_data_len);
|
||||
|
||||
av_dict_set(&sd->metadata, "name", s->iccp_name, 0);
|
||||
}
|
||||
|
||||
if (s->stereo_mode >= 0) {
|
||||
AVStereo3D *stereo3d = av_stereo3d_create_side_data(f);
|
||||
if (!stereo3d) {
|
||||
ret = AVERROR(ENOMEM);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
stereo3d->type = AV_STEREO3D_SIDEBYSIDE;
|
||||
stereo3d->flags = s->stereo_mode ? 0 : AV_STEREO3D_FLAG_INVERT;
|
||||
}
|
||||
|
||||
if (s->have_chrm) {
|
||||
AVMasteringDisplayMetadata *mdm = av_mastering_display_metadata_create_side_data(f);
|
||||
if (!mdm) {
|
||||
ret = AVERROR(ENOMEM);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
mdm->white_point[0] = av_make_q(s->white_point[0], 100000);
|
||||
mdm->white_point[1] = av_make_q(s->white_point[1], 100000);
|
||||
|
||||
/* RGB Primaries */
|
||||
for (int i = 0; i < 3; i++) {
|
||||
mdm->display_primaries[i][0] = av_make_q(s->display_primaries[i][0], 100000);
|
||||
mdm->display_primaries[i][1] = av_make_q(s->display_primaries[i][1], 100000);
|
||||
}
|
||||
|
||||
mdm->has_primaries = 1;
|
||||
}
|
||||
|
||||
FFSWAP(AVDictionary*, f->metadata, s->frame_metadata);
|
||||
|
||||
return 0;
|
||||
fail:
|
||||
av_frame_unref(f);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if CONFIG_PNG_DECODER
|
||||
static int decode_frame_png(AVCodecContext *avctx,
|
||||
void *data, int *got_frame,
|
||||
@@ -1464,10 +1534,13 @@ static int decode_frame_png(AVCodecContext *avctx,
|
||||
PNGDecContext *const s = avctx->priv_data;
|
||||
const uint8_t *buf = avpkt->data;
|
||||
int buf_size = avpkt->size;
|
||||
AVFrame *dst_frame = data;
|
||||
AVFrame *p = s->picture.f;
|
||||
int64_t sig;
|
||||
int ret;
|
||||
|
||||
clear_frame_metadata(s);
|
||||
|
||||
bytestream2_init(&s->gb, buf, buf_size);
|
||||
|
||||
/* check signature */
|
||||
@@ -1501,7 +1574,8 @@ static int decode_frame_png(AVCodecContext *avctx,
|
||||
goto the_end;
|
||||
}
|
||||
|
||||
if ((ret = av_frame_ref(data, s->picture.f)) < 0)
|
||||
ret = output_frame(s, dst_frame, s->picture.f);
|
||||
if (ret < 0)
|
||||
goto the_end;
|
||||
|
||||
if (!(avctx->active_thread_type & FF_THREAD_FRAME)) {
|
||||
@@ -1525,9 +1599,12 @@ static int decode_frame_apng(AVCodecContext *avctx,
|
||||
AVPacket *avpkt)
|
||||
{
|
||||
PNGDecContext *const s = avctx->priv_data;
|
||||
AVFrame *dst_frame = data;
|
||||
int ret;
|
||||
AVFrame *p = s->picture.f;
|
||||
|
||||
clear_frame_metadata(s);
|
||||
|
||||
if (!(s->hdr_state & PNG_IHDR)) {
|
||||
if (!avctx->extradata_size)
|
||||
return AVERROR_INVALIDDATA;
|
||||
@@ -1559,7 +1636,9 @@ static int decode_frame_apng(AVCodecContext *avctx,
|
||||
ret = AVERROR_INVALIDDATA;
|
||||
goto end;
|
||||
}
|
||||
if ((ret = av_frame_ref(data, s->picture.f)) < 0)
|
||||
|
||||
ret = output_frame(s, dst_frame, s->picture.f);
|
||||
if (ret < 0)
|
||||
goto end;
|
||||
|
||||
if (!(avctx->active_thread_type & FF_THREAD_FRAME)) {
|
||||
@@ -1662,6 +1741,10 @@ static av_cold int png_dec_end(AVCodecContext *avctx)
|
||||
s->last_row_size = 0;
|
||||
av_freep(&s->tmp_row);
|
||||
s->tmp_row_size = 0;
|
||||
av_freep(&s->background_buf);
|
||||
|
||||
av_freep(&s->iccp_data);
|
||||
av_dict_free(&s->frame_metadata);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ retry:
|
||||
} else {
|
||||
int ret = av_image_get_buffer_size(avctx->pix_fmt, avctx->width, avctx->height, 1);
|
||||
next = pnmctx.bytestream - pnmctx.bytestream_start + skip;
|
||||
if (ret >= 0)
|
||||
if (ret >= 0 && next + (uint64_t)ret <= INT_MAX)
|
||||
next += ret;
|
||||
}
|
||||
if (next != END_NOT_FOUND && pnmctx.bytestream_start != buf + skip)
|
||||
|
||||
@@ -623,8 +623,8 @@ static int decode_slice_thread(AVCodecContext *avctx, void *arg, int jobnr, int
|
||||
AVFrame *pic = ctx->frame;
|
||||
int i, hdr_size, qscale, log2_chroma_blocks_per_mb;
|
||||
int luma_stride, chroma_stride;
|
||||
int y_data_size, u_data_size, v_data_size, a_data_size;
|
||||
uint8_t *dest_y, *dest_u, *dest_v, *dest_a;
|
||||
int y_data_size, u_data_size, v_data_size, a_data_size, offset;
|
||||
uint8_t *dest_y, *dest_u, *dest_v;
|
||||
LOCAL_ALIGNED_16(int16_t, qmat_luma_scaled, [64]);
|
||||
LOCAL_ALIGNED_16(int16_t, qmat_chroma_scaled,[64]);
|
||||
int mb_x_shift;
|
||||
@@ -676,16 +676,16 @@ static int decode_slice_thread(AVCodecContext *avctx, void *arg, int jobnr, int
|
||||
log2_chroma_blocks_per_mb = 1;
|
||||
}
|
||||
|
||||
dest_y = pic->data[0] + (slice->mb_y << 4) * luma_stride + (slice->mb_x << 5);
|
||||
offset = (slice->mb_y << 4) * luma_stride + (slice->mb_x << 5);
|
||||
dest_y = pic->data[0] + offset;
|
||||
dest_u = pic->data[1] + (slice->mb_y << 4) * chroma_stride + (slice->mb_x << mb_x_shift);
|
||||
dest_v = pic->data[2] + (slice->mb_y << 4) * chroma_stride + (slice->mb_x << mb_x_shift);
|
||||
dest_a = pic->data[3] + (slice->mb_y << 4) * luma_stride + (slice->mb_x << 5);
|
||||
|
||||
if (ctx->frame_type && ctx->first_field ^ ctx->frame->top_field_first) {
|
||||
dest_y += pic->linesize[0];
|
||||
dest_u += pic->linesize[1];
|
||||
dest_v += pic->linesize[2];
|
||||
dest_a += pic->linesize[3];
|
||||
offset += pic->linesize[3];
|
||||
}
|
||||
|
||||
ret = decode_slice_luma(avctx, slice, (uint16_t*)dest_y, luma_stride,
|
||||
@@ -722,10 +722,12 @@ static int decode_slice_thread(AVCodecContext *avctx, void *arg, int jobnr, int
|
||||
}
|
||||
|
||||
/* decode alpha plane if available */
|
||||
if (ctx->alpha_info && pic->data[3] && a_data_size)
|
||||
if (ctx->alpha_info && pic->data[3] && a_data_size) {
|
||||
uint8_t *dest_a = pic->data[3] + offset;
|
||||
decode_slice_alpha(ctx, (uint16_t*)dest_a, luma_stride,
|
||||
buf + y_data_size + u_data_size + v_data_size,
|
||||
a_data_size, slice->mb_count);
|
||||
}
|
||||
|
||||
slice->ret = 0;
|
||||
return 0;
|
||||
|
||||
@@ -957,6 +957,7 @@ AVCodec ff_prores_aw_encoder = {
|
||||
.capabilities = AV_CODEC_CAP_FRAME_THREADS,
|
||||
.priv_class = &proresaw_enc_class,
|
||||
.profiles = NULL_IF_CONFIG_SMALL(ff_prores_profiles),
|
||||
.caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
|
||||
};
|
||||
|
||||
AVCodec ff_prores_encoder = {
|
||||
@@ -972,4 +973,5 @@ AVCodec ff_prores_encoder = {
|
||||
.capabilities = AV_CODEC_CAP_FRAME_THREADS,
|
||||
.priv_class = &prores_enc_class,
|
||||
.profiles = NULL_IF_CONFIG_SMALL(ff_prores_profiles),
|
||||
.caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
|
||||
};
|
||||
|
||||
+183
-129
@@ -64,6 +64,12 @@ enum {
|
||||
STATE_SETUP_FINISHED,
|
||||
};
|
||||
|
||||
enum {
|
||||
UNINITIALIZED, ///< Thread has not been created, AVCodec->close mustn't be called
|
||||
NEEDS_CLOSE, ///< AVCodec->close needs to be called
|
||||
INITIALIZED, ///< Thread has been properly set up
|
||||
};
|
||||
|
||||
/**
|
||||
* Context used by codec threads and stored in their AVCodecInternal thread_ctx.
|
||||
*/
|
||||
@@ -72,6 +78,7 @@ typedef struct PerThreadContext {
|
||||
|
||||
pthread_t thread;
|
||||
int thread_init;
|
||||
unsigned pthread_init_cnt;///< Number of successfully initialized mutexes/conditions
|
||||
pthread_cond_t input_cond; ///< Used to wait for a new packet from the main thread.
|
||||
pthread_cond_t progress_cond; ///< Used by child threads to wait for progress to change.
|
||||
pthread_cond_t output_cond; ///< Used by the main thread to wait for frames to finish.
|
||||
@@ -120,6 +127,7 @@ typedef struct FrameThreadContext {
|
||||
PerThreadContext *threads; ///< The contexts for each thread.
|
||||
PerThreadContext *prev_thread; ///< The last thread submit_packet() was called on.
|
||||
|
||||
unsigned pthread_init_cnt; ///< Number of successfully initialized mutexes/conditions
|
||||
pthread_mutex_t buffer_mutex; ///< Mutex used to protect get/release_buffer().
|
||||
/**
|
||||
* This lock is used for ensuring threads run in serial when hwaccel
|
||||
@@ -674,6 +682,59 @@ static void park_frame_worker_threads(FrameThreadContext *fctx, int thread_count
|
||||
async_lock(fctx);
|
||||
}
|
||||
|
||||
#define SENTINEL 0 // This forbids putting a mutex/condition variable at the front.
|
||||
#define OFFSET_ARRAY(...) __VA_ARGS__, SENTINEL
|
||||
#define DEFINE_OFFSET_ARRAY(type, name, mutexes, conds) \
|
||||
static const unsigned name ## _offsets[] = { offsetof(type, pthread_init_cnt),\
|
||||
OFFSET_ARRAY mutexes, \
|
||||
OFFSET_ARRAY conds }
|
||||
|
||||
#define OFF(member) offsetof(FrameThreadContext, member)
|
||||
DEFINE_OFFSET_ARRAY(FrameThreadContext, thread_ctx,
|
||||
(OFF(buffer_mutex), OFF(hwaccel_mutex), OFF(async_mutex)),
|
||||
(OFF(async_cond)));
|
||||
#undef OFF
|
||||
|
||||
#define OFF(member) offsetof(PerThreadContext, member)
|
||||
DEFINE_OFFSET_ARRAY(PerThreadContext, per_thread,
|
||||
(OFF(progress_mutex), OFF(mutex)),
|
||||
(OFF(input_cond), OFF(progress_cond), OFF(output_cond)));
|
||||
#undef OFF
|
||||
|
||||
static av_cold void free_pthread(void *obj, const unsigned offsets[])
|
||||
{
|
||||
unsigned cnt = *(unsigned*)((char*)obj + offsets[0]);
|
||||
const unsigned *cur_offset = offsets;
|
||||
|
||||
for (; *(++cur_offset) != SENTINEL && cnt; cnt--)
|
||||
pthread_mutex_destroy((pthread_mutex_t*)((char*)obj + *cur_offset));
|
||||
for (; *(++cur_offset) != SENTINEL && cnt; cnt--)
|
||||
pthread_cond_destroy ((pthread_cond_t *)((char*)obj + *cur_offset));
|
||||
}
|
||||
|
||||
static av_cold int init_pthread(void *obj, const unsigned offsets[])
|
||||
{
|
||||
const unsigned *cur_offset = offsets;
|
||||
unsigned cnt = 0;
|
||||
int err;
|
||||
|
||||
#define PTHREAD_INIT_LOOP(type) \
|
||||
for (; *(++cur_offset) != SENTINEL; cnt++) { \
|
||||
pthread_ ## type ## _t *dst = (void*)((char*)obj + *cur_offset); \
|
||||
err = pthread_ ## type ## _init(dst, NULL); \
|
||||
if (err) { \
|
||||
err = AVERROR(err); \
|
||||
goto fail; \
|
||||
} \
|
||||
}
|
||||
PTHREAD_INIT_LOOP(mutex)
|
||||
PTHREAD_INIT_LOOP(cond)
|
||||
|
||||
fail:
|
||||
*(unsigned*)((char*)obj + offsets[0]) = cnt;
|
||||
return err;
|
||||
}
|
||||
|
||||
void ff_frame_thread_free(AVCodecContext *avctx, int thread_count)
|
||||
{
|
||||
FrameThreadContext *fctx = avctx->internal->thread_ctx;
|
||||
@@ -698,63 +759,49 @@ void ff_frame_thread_free(AVCodecContext *avctx, int thread_count)
|
||||
|
||||
for (i = 0; i < thread_count; i++) {
|
||||
PerThreadContext *p = &fctx->threads[i];
|
||||
AVCodecContext *ctx = p->avctx;
|
||||
|
||||
pthread_mutex_lock(&p->mutex);
|
||||
p->die = 1;
|
||||
pthread_cond_signal(&p->input_cond);
|
||||
pthread_mutex_unlock(&p->mutex);
|
||||
if (ctx->internal) {
|
||||
if (p->thread_init == INITIALIZED) {
|
||||
pthread_mutex_lock(&p->mutex);
|
||||
p->die = 1;
|
||||
pthread_cond_signal(&p->input_cond);
|
||||
pthread_mutex_unlock(&p->mutex);
|
||||
|
||||
if (p->thread_init)
|
||||
pthread_join(p->thread, NULL);
|
||||
p->thread_init=0;
|
||||
|
||||
if (codec->close && p->avctx)
|
||||
codec->close(p->avctx);
|
||||
pthread_join(p->thread, NULL);
|
||||
}
|
||||
if (codec->close && p->thread_init != UNINITIALIZED)
|
||||
codec->close(ctx);
|
||||
|
||||
#if FF_API_THREAD_SAFE_CALLBACKS
|
||||
release_delayed_buffers(p);
|
||||
release_delayed_buffers(p);
|
||||
for (int j = 0; j < p->released_buffers_allocated; j++)
|
||||
av_frame_free(&p->released_buffers[j]);
|
||||
av_freep(&p->released_buffers);
|
||||
#endif
|
||||
if (ctx->priv_data) {
|
||||
if (codec->priv_class)
|
||||
av_opt_free(ctx->priv_data);
|
||||
av_freep(&ctx->priv_data);
|
||||
}
|
||||
|
||||
av_freep(&ctx->slice_offset);
|
||||
|
||||
av_buffer_unref(&ctx->internal->pool);
|
||||
av_freep(&ctx->internal);
|
||||
av_buffer_unref(&ctx->hw_frames_ctx);
|
||||
}
|
||||
|
||||
av_frame_free(&p->frame);
|
||||
}
|
||||
|
||||
for (i = 0; i < thread_count; i++) {
|
||||
PerThreadContext *p = &fctx->threads[i];
|
||||
|
||||
pthread_mutex_destroy(&p->mutex);
|
||||
pthread_mutex_destroy(&p->progress_mutex);
|
||||
pthread_cond_destroy(&p->input_cond);
|
||||
pthread_cond_destroy(&p->progress_cond);
|
||||
pthread_cond_destroy(&p->output_cond);
|
||||
free_pthread(p, per_thread_offsets);
|
||||
av_packet_free(&p->avpkt);
|
||||
|
||||
#if FF_API_THREAD_SAFE_CALLBACKS
|
||||
for (int j = 0; j < p->released_buffers_allocated; j++)
|
||||
av_frame_free(&p->released_buffers[j]);
|
||||
av_freep(&p->released_buffers);
|
||||
#endif
|
||||
|
||||
if (p->avctx) {
|
||||
if (codec->priv_class)
|
||||
av_opt_free(p->avctx->priv_data);
|
||||
av_freep(&p->avctx->priv_data);
|
||||
|
||||
av_freep(&p->avctx->slice_offset);
|
||||
}
|
||||
|
||||
if (p->avctx) {
|
||||
av_buffer_unref(&p->avctx->internal->pool);
|
||||
av_freep(&p->avctx->internal);
|
||||
av_buffer_unref(&p->avctx->hw_frames_ctx);
|
||||
}
|
||||
|
||||
av_freep(&p->avctx);
|
||||
}
|
||||
|
||||
av_freep(&fctx->threads);
|
||||
pthread_mutex_destroy(&fctx->buffer_mutex);
|
||||
pthread_mutex_destroy(&fctx->hwaccel_mutex);
|
||||
pthread_mutex_destroy(&fctx->async_mutex);
|
||||
pthread_cond_destroy(&fctx->async_cond);
|
||||
free_pthread(fctx, thread_ctx_offsets);
|
||||
|
||||
av_freep(&avctx->internal->thread_ctx);
|
||||
|
||||
@@ -763,13 +810,89 @@ void ff_frame_thread_free(AVCodecContext *avctx, int thread_count)
|
||||
avctx->codec = NULL;
|
||||
}
|
||||
|
||||
static av_cold int init_thread(PerThreadContext *p, int *threads_to_free,
|
||||
FrameThreadContext *fctx, AVCodecContext *avctx,
|
||||
AVCodecContext *src, const AVCodec *codec, int first)
|
||||
{
|
||||
AVCodecContext *copy;
|
||||
int err;
|
||||
|
||||
atomic_init(&p->state, STATE_INPUT_READY);
|
||||
|
||||
copy = av_memdup(src, sizeof(*src));
|
||||
if (!copy)
|
||||
return AVERROR(ENOMEM);
|
||||
copy->priv_data = NULL;
|
||||
|
||||
/* From now on, this PerThreadContext will be cleaned up by
|
||||
* ff_frame_thread_free in case of errors. */
|
||||
(*threads_to_free)++;
|
||||
|
||||
p->parent = fctx;
|
||||
p->avctx = copy;
|
||||
|
||||
copy->internal = av_memdup(src->internal, sizeof(*src->internal));
|
||||
if (!copy->internal)
|
||||
return AVERROR(ENOMEM);
|
||||
copy->internal->thread_ctx = p;
|
||||
|
||||
copy->delay = avctx->delay;
|
||||
|
||||
if (codec->priv_data_size) {
|
||||
copy->priv_data = av_mallocz(codec->priv_data_size);
|
||||
if (!copy->priv_data)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
if (codec->priv_class) {
|
||||
*(const AVClass **)copy->priv_data = codec->priv_class;
|
||||
err = av_opt_copy(copy->priv_data, src->priv_data);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
err = init_pthread(p, per_thread_offsets);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (!(p->frame = av_frame_alloc()) ||
|
||||
!(p->avpkt = av_packet_alloc()))
|
||||
return AVERROR(ENOMEM);
|
||||
copy->internal->last_pkt_props = p->avpkt;
|
||||
|
||||
if (!first)
|
||||
copy->internal->is_copy = 1;
|
||||
|
||||
if (codec->init) {
|
||||
err = codec->init(copy);
|
||||
if (err < 0) {
|
||||
if (codec->caps_internal & FF_CODEC_CAP_INIT_CLEANUP)
|
||||
p->thread_init = NEEDS_CLOSE;
|
||||
return err;
|
||||
}
|
||||
}
|
||||
p->thread_init = NEEDS_CLOSE;
|
||||
|
||||
if (first)
|
||||
update_context_from_thread(avctx, copy, 1);
|
||||
|
||||
atomic_init(&p->debug_threads, (copy->debug & FF_DEBUG_THREADS) != 0);
|
||||
|
||||
err = AVERROR(pthread_create(&p->thread, NULL, frame_worker_thread, p));
|
||||
if (err < 0)
|
||||
return err;
|
||||
p->thread_init = INITIALIZED;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ff_frame_thread_init(AVCodecContext *avctx)
|
||||
{
|
||||
int thread_count = avctx->thread_count;
|
||||
const AVCodec *codec = avctx->codec;
|
||||
AVCodecContext *src = avctx;
|
||||
FrameThreadContext *fctx;
|
||||
int i, err = 0;
|
||||
int err, i = 0;
|
||||
|
||||
if (!thread_count) {
|
||||
int nb_cpus = av_cpu_count();
|
||||
@@ -789,107 +912,38 @@ int ff_frame_thread_init(AVCodecContext *avctx)
|
||||
if (!fctx)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
fctx->threads = av_mallocz_array(thread_count, sizeof(PerThreadContext));
|
||||
if (!fctx->threads) {
|
||||
err = init_pthread(fctx, thread_ctx_offsets);
|
||||
if (err < 0) {
|
||||
free_pthread(fctx, thread_ctx_offsets);
|
||||
av_freep(&avctx->internal->thread_ctx);
|
||||
return AVERROR(ENOMEM);
|
||||
return err;
|
||||
}
|
||||
|
||||
pthread_mutex_init(&fctx->buffer_mutex, NULL);
|
||||
pthread_mutex_init(&fctx->hwaccel_mutex, NULL);
|
||||
pthread_mutex_init(&fctx->async_mutex, NULL);
|
||||
pthread_cond_init(&fctx->async_cond, NULL);
|
||||
|
||||
fctx->async_lock = 1;
|
||||
fctx->delaying = 1;
|
||||
|
||||
if (codec->type == AVMEDIA_TYPE_VIDEO)
|
||||
avctx->delay = src->thread_count - 1;
|
||||
|
||||
for (i = 0; i < thread_count; i++) {
|
||||
AVCodecContext *copy = av_malloc(sizeof(AVCodecContext));
|
||||
fctx->threads = av_mallocz_array(thread_count, sizeof(PerThreadContext));
|
||||
if (!fctx->threads) {
|
||||
err = AVERROR(ENOMEM);
|
||||
goto error;
|
||||
}
|
||||
|
||||
for (; i < thread_count; ) {
|
||||
PerThreadContext *p = &fctx->threads[i];
|
||||
int first = !i;
|
||||
|
||||
pthread_mutex_init(&p->mutex, NULL);
|
||||
pthread_mutex_init(&p->progress_mutex, NULL);
|
||||
pthread_cond_init(&p->input_cond, NULL);
|
||||
pthread_cond_init(&p->progress_cond, NULL);
|
||||
pthread_cond_init(&p->output_cond, NULL);
|
||||
|
||||
p->frame = av_frame_alloc();
|
||||
if (!p->frame) {
|
||||
av_freep(©);
|
||||
err = AVERROR(ENOMEM);
|
||||
goto error;
|
||||
}
|
||||
p->avpkt = av_packet_alloc();
|
||||
if (!p->avpkt) {
|
||||
av_freep(©);
|
||||
err = AVERROR(ENOMEM);
|
||||
goto error;
|
||||
}
|
||||
|
||||
p->parent = fctx;
|
||||
p->avctx = copy;
|
||||
|
||||
if (!copy) {
|
||||
err = AVERROR(ENOMEM);
|
||||
goto error;
|
||||
}
|
||||
|
||||
*copy = *src;
|
||||
|
||||
copy->internal = av_malloc(sizeof(AVCodecInternal));
|
||||
if (!copy->internal) {
|
||||
copy->priv_data = NULL;
|
||||
err = AVERROR(ENOMEM);
|
||||
goto error;
|
||||
}
|
||||
*copy->internal = *src->internal;
|
||||
copy->internal->thread_ctx = p;
|
||||
copy->internal->last_pkt_props = p->avpkt;
|
||||
|
||||
copy->delay = avctx->delay;
|
||||
|
||||
if (codec->priv_data_size) {
|
||||
copy->priv_data = av_mallocz(codec->priv_data_size);
|
||||
if (!copy->priv_data) {
|
||||
err = AVERROR(ENOMEM);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (codec->priv_class) {
|
||||
*(const AVClass **)copy->priv_data = codec->priv_class;
|
||||
err = av_opt_copy(copy->priv_data, src->priv_data);
|
||||
if (err < 0)
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
if (i)
|
||||
copy->internal->is_copy = 1;
|
||||
|
||||
if (codec->init)
|
||||
err = codec->init(copy);
|
||||
|
||||
if (err) goto error;
|
||||
|
||||
if (!i)
|
||||
update_context_from_thread(avctx, copy, 1);
|
||||
|
||||
atomic_init(&p->debug_threads, (copy->debug & FF_DEBUG_THREADS) != 0);
|
||||
|
||||
err = AVERROR(pthread_create(&p->thread, NULL, frame_worker_thread, p));
|
||||
p->thread_init= !err;
|
||||
if(!p->thread_init)
|
||||
err = init_thread(p, &i, fctx, avctx, src, codec, first);
|
||||
if (err < 0)
|
||||
goto error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
ff_frame_thread_free(avctx, i+1);
|
||||
|
||||
ff_frame_thread_free(avctx, i);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
@@ -35,16 +35,9 @@
|
||||
|
||||
#include "version.h"
|
||||
|
||||
#if ARCH_X86_64
|
||||
// TODO: Benchmark and optionally enable on other 64-bit architectures.
|
||||
typedef uint64_t BitBuf;
|
||||
#define AV_WBBUF AV_WB64
|
||||
#define AV_WLBUF AV_WL64
|
||||
#else
|
||||
typedef uint32_t BitBuf;
|
||||
#define AV_WBBUF AV_WB32
|
||||
#define AV_WLBUF AV_WL32
|
||||
#endif
|
||||
|
||||
static const int BUF_BITS = 8 * sizeof(BitBuf);
|
||||
|
||||
|
||||
+13
-9
@@ -155,10 +155,14 @@ static void qtrle_encode_line(QtrleEncContext *s, const AVFrame *p, int line, ui
|
||||
int sec_lowest_bulk_cost;
|
||||
int sec_lowest_bulk_cost_index;
|
||||
|
||||
uint8_t *this_line = p-> data[0] + line*p-> linesize[0] +
|
||||
(width - 1)*s->pixel_size;
|
||||
uint8_t *prev_line = s->previous_frame->data[0] + line * s->previous_frame->linesize[0] +
|
||||
(width - 1)*s->pixel_size;
|
||||
const uint8_t *this_line = p->data[0] + line * p->linesize[0] + width * s->pixel_size;
|
||||
/* There might be no earlier frame if the current frame is a keyframe.
|
||||
* So just use a pointer to the current frame to avoid a check
|
||||
* to avoid NULL - s->pixel_size (which is undefined behaviour). */
|
||||
const uint8_t *prev_line = s->key_frame ? this_line
|
||||
: s->previous_frame->data[0]
|
||||
+ line * s->previous_frame->linesize[0]
|
||||
+ width * s->pixel_size;
|
||||
|
||||
s->length_table[width] = 0;
|
||||
skipcount = 0;
|
||||
@@ -175,6 +179,9 @@ static void qtrle_encode_line(QtrleEncContext *s, const AVFrame *p, int line, ui
|
||||
|
||||
int prev_bulk_cost;
|
||||
|
||||
this_line -= s->pixel_size;
|
||||
prev_line -= s->pixel_size;
|
||||
|
||||
/* If our lowest bulk cost index is too far away, replace it
|
||||
* with the next lowest bulk cost */
|
||||
if (FFMIN(width, i + MAX_RLE_BULK) < lowest_bulk_cost_index) {
|
||||
@@ -259,10 +266,6 @@ static void qtrle_encode_line(QtrleEncContext *s, const AVFrame *p, int line, ui
|
||||
/* These bulk costs increase every iteration */
|
||||
lowest_bulk_cost += s->pixel_size;
|
||||
sec_lowest_bulk_cost += s->pixel_size;
|
||||
if (this_line >= p->data[0] + s->pixel_size)
|
||||
this_line -= s->pixel_size;
|
||||
if (prev_line >= s->previous_frame->data[0] + s->pixel_size)
|
||||
prev_line -= s->pixel_size;
|
||||
}
|
||||
|
||||
/* Good! Now we have the best sequence for this line, let's output it. */
|
||||
@@ -369,7 +372,8 @@ static int qtrle_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
|
||||
if ((ret = ff_alloc_packet2(avctx, pkt, s->max_buf_size, 0)) < 0)
|
||||
return ret;
|
||||
|
||||
if (avctx->gop_size == 0 || (s->avctx->frame_number % avctx->gop_size) == 0) {
|
||||
if (avctx->gop_size == 0 || !s->previous_frame->data[0] ||
|
||||
(s->avctx->frame_number % avctx->gop_size) == 0) {
|
||||
/* I-Frame */
|
||||
s->key_frame = 1;
|
||||
} else {
|
||||
|
||||
@@ -493,6 +493,7 @@ static av_cold int raw_close_decoder(AVCodecContext *avctx)
|
||||
RawVideoContext *context = avctx->priv_data;
|
||||
|
||||
av_buffer_unref(&context->palette);
|
||||
av_freep(&context->bitstream_buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+1
-3
@@ -226,7 +226,7 @@ static int rv20_decode_picture_header(RVDecContext *rv)
|
||||
new_w = rv->orig_width;
|
||||
new_h = rv->orig_height;
|
||||
}
|
||||
if (new_w != s->width || new_h != s->height) {
|
||||
if (new_w != s->width || new_h != s->height || !s->context_initialized) {
|
||||
AVRational old_aspect = s->avctx->sample_aspect_ratio;
|
||||
av_log(s->avctx, AV_LOG_DEBUG,
|
||||
"attempting to change resolution to %dx%d\n", new_w, new_h);
|
||||
@@ -687,7 +687,6 @@ AVCodec ff_rv10_decoder = {
|
||||
.close = rv10_decode_end,
|
||||
.decode = rv10_decode_frame,
|
||||
.capabilities = AV_CODEC_CAP_DR1,
|
||||
.caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
|
||||
.max_lowres = 3,
|
||||
.pix_fmts = (const enum AVPixelFormat[]) {
|
||||
AV_PIX_FMT_YUV420P,
|
||||
@@ -705,7 +704,6 @@ AVCodec ff_rv20_decoder = {
|
||||
.close = rv10_decode_end,
|
||||
.decode = rv10_decode_frame,
|
||||
.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY,
|
||||
.caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
|
||||
.flush = ff_mpeg_flush,
|
||||
.max_lowres = 3,
|
||||
.pix_fmts = (const enum AVPixelFormat[]) {
|
||||
|
||||
+9
-4
@@ -1383,6 +1383,7 @@ static int rv34_decoder_alloc(RV34DecContext *r)
|
||||
|
||||
if (!(r->cbp_chroma && r->cbp_luma && r->deblock_coefs &&
|
||||
r->intra_types_hist && r->mb_type)) {
|
||||
r->s.context_reinit = 1;
|
||||
rv34_decoder_free(r);
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
@@ -1530,7 +1531,7 @@ int ff_rv34_decode_update_thread_context(AVCodecContext *dst, const AVCodecConte
|
||||
if (dst == src || !s1->context_initialized)
|
||||
return 0;
|
||||
|
||||
if (s->height != s1->height || s->width != s1->width) {
|
||||
if (s->height != s1->height || s->width != s1->width || s->context_reinit) {
|
||||
s->height = s1->height;
|
||||
s->width = s1->width;
|
||||
if ((err = ff_mpv_common_frame_size_change(s)) < 0)
|
||||
@@ -1667,11 +1668,12 @@ int ff_rv34_decode_frame(AVCodecContext *avctx,
|
||||
if (s->mb_num_left > 0 && s->current_picture_ptr) {
|
||||
av_log(avctx, AV_LOG_ERROR, "New frame but still %d MB left.\n",
|
||||
s->mb_num_left);
|
||||
ff_er_frame_end(&s->er);
|
||||
if (!s->context_reinit)
|
||||
ff_er_frame_end(&s->er);
|
||||
ff_mpv_frame_end(s);
|
||||
}
|
||||
|
||||
if (s->width != si.width || s->height != si.height) {
|
||||
if (s->width != si.width || s->height != si.height || s->context_reinit) {
|
||||
int err;
|
||||
|
||||
av_log(s->avctx, AV_LOG_WARNING, "Changing dimensions to %dx%d\n",
|
||||
@@ -1689,7 +1691,6 @@ int ff_rv34_decode_frame(AVCodecContext *avctx,
|
||||
err = ff_set_dimensions(s->avctx, s->width, s->height);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if ((err = ff_mpv_common_frame_size_change(s)) < 0)
|
||||
return err;
|
||||
if ((err = rv34_decoder_realloc(r)) < 0)
|
||||
@@ -1744,6 +1745,10 @@ int ff_rv34_decode_frame(AVCodecContext *avctx,
|
||||
}
|
||||
s->mb_x = s->mb_y = 0;
|
||||
ff_thread_finish_setup(s->avctx);
|
||||
} else if (s->context_reinit) {
|
||||
av_log(s->avctx, AV_LOG_ERROR, "Decoder needs full frames to "
|
||||
"reinitialize (start MB is %d).\n", si.start);
|
||||
return AVERROR_INVALIDDATA;
|
||||
} else if (HAVE_THREADS &&
|
||||
(s->avctx->active_thread_type & FF_THREAD_FRAME)) {
|
||||
av_log(s->avctx, AV_LOG_ERROR, "Decoder needs full frames in frame "
|
||||
|
||||
@@ -152,7 +152,7 @@ static int setts_filter(AVBSFContext *ctx, AVPacket *pkt)
|
||||
s->var_values[VAR_PREV_OUTDTS] = s->prev_outdts;
|
||||
s->var_values[VAR_STARTPTS] = s->start_pts;
|
||||
s->var_values[VAR_STARTDTS] = s->start_dts;
|
||||
s->var_values[VAR_TB] = av_q2d(ctx->time_base_out);
|
||||
s->var_values[VAR_TB] = ctx->time_base_out.den ? av_q2d(ctx->time_base_out) : 0;
|
||||
s->var_values[VAR_SR] = ctx->par_in->sample_rate;
|
||||
|
||||
new_ts = llrint(av_expr_eval(s->ts_expr, s->var_values, NULL));
|
||||
|
||||
+1
-1
@@ -232,7 +232,7 @@ static int lzss_decompress(AVCodecContext *avctx,
|
||||
|
||||
if (offset <= 0)
|
||||
offset = 1;
|
||||
if (oi < offset)
|
||||
if (oi < offset || oi + count * 2 > dst_size)
|
||||
return AVERROR_INVALIDDATA;
|
||||
for (int j = 0; j < count * 2; j++) {
|
||||
dst[oi] = dst[oi - offset];
|
||||
|
||||
+2
-2
@@ -475,13 +475,13 @@ static int predictor_calc_error(int *k, int *state, int order, int error)
|
||||
for (i = order-2; i >= 0; i--, k_ptr--, state_ptr--)
|
||||
{
|
||||
int k_value = *k_ptr, state_value = *state_ptr;
|
||||
x -= shift_down(k_value * (unsigned)state_value, LATTICE_SHIFT);
|
||||
x -= (unsigned)shift_down(k_value * (unsigned)state_value, LATTICE_SHIFT);
|
||||
state_ptr[1] = state_value + shift_down(k_value * (unsigned)x, LATTICE_SHIFT);
|
||||
}
|
||||
#else
|
||||
for (i = order-2; i >= 0; i--)
|
||||
{
|
||||
x -= shift_down(k[i] * state[i], LATTICE_SHIFT);
|
||||
x -= (unsigned)shift_down(k[i] * state[i], LATTICE_SHIFT);
|
||||
state[i+1] = state[i] + shift_down(k[i] * x, LATTICE_SHIFT);
|
||||
}
|
||||
#endif
|
||||
|
||||
+195
-199
@@ -275,9 +275,101 @@ static int add_metadata(int count, int type,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Map stored raw sensor values into linear reference values (see: DNG Specification - Chapter 5)
|
||||
*/
|
||||
static uint16_t av_always_inline dng_process_color16(uint16_t value,
|
||||
const uint16_t *lut,
|
||||
uint16_t black_level,
|
||||
float scale_factor)
|
||||
{
|
||||
float value_norm;
|
||||
|
||||
// Lookup table lookup
|
||||
if (lut)
|
||||
value = lut[value];
|
||||
|
||||
// Black level subtraction
|
||||
value = av_clip_uint16_c((unsigned)value - black_level);
|
||||
|
||||
// Color scaling
|
||||
value_norm = (float)value * scale_factor;
|
||||
|
||||
value = av_clip_uint16_c(value_norm * 65535);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static uint16_t av_always_inline dng_process_color8(uint16_t value,
|
||||
const uint16_t *lut,
|
||||
uint16_t black_level,
|
||||
float scale_factor)
|
||||
{
|
||||
return dng_process_color16(value, lut, black_level, scale_factor) >> 8;
|
||||
}
|
||||
|
||||
static void av_always_inline dng_blit(TiffContext *s, uint8_t *dst, int dst_stride,
|
||||
const uint8_t *src, int src_stride, int width, int height,
|
||||
int is_single_comp, int is_u16);
|
||||
int is_single_comp, int is_u16)
|
||||
{
|
||||
int line, col;
|
||||
float scale_factor;
|
||||
|
||||
scale_factor = 1.0f / (s->white_level - s->black_level);
|
||||
|
||||
if (is_single_comp) {
|
||||
if (!is_u16)
|
||||
return; /* <= 8bpp unsupported */
|
||||
|
||||
/* Image is double the width and half the height we need, each row comprises 2 rows of the output
|
||||
(split vertically in the middle). */
|
||||
for (line = 0; line < height / 2; line++) {
|
||||
uint16_t *dst_u16 = (uint16_t *)dst;
|
||||
uint16_t *src_u16 = (uint16_t *)src;
|
||||
|
||||
/* Blit first half of input row row to initial row of output */
|
||||
for (col = 0; col < width; col++)
|
||||
*dst_u16++ = dng_process_color16(*src_u16++, s->dng_lut, s->black_level, scale_factor);
|
||||
|
||||
/* Advance the destination pointer by a row (source pointer remains in the same place) */
|
||||
dst += dst_stride * sizeof(uint16_t);
|
||||
dst_u16 = (uint16_t *)dst;
|
||||
|
||||
/* Blit second half of input row row to next row of output */
|
||||
for (col = 0; col < width; col++)
|
||||
*dst_u16++ = dng_process_color16(*src_u16++, s->dng_lut, s->black_level, scale_factor);
|
||||
|
||||
dst += dst_stride * sizeof(uint16_t);
|
||||
src += src_stride * sizeof(uint16_t);
|
||||
}
|
||||
} else {
|
||||
/* Input and output image are the same size and the MJpeg decoder has done per-component
|
||||
deinterleaving, so blitting here is straightforward. */
|
||||
if (is_u16) {
|
||||
for (line = 0; line < height; line++) {
|
||||
uint16_t *dst_u16 = (uint16_t *)dst;
|
||||
uint16_t *src_u16 = (uint16_t *)src;
|
||||
|
||||
for (col = 0; col < width; col++)
|
||||
*dst_u16++ = dng_process_color16(*src_u16++, s->dng_lut, s->black_level, scale_factor);
|
||||
|
||||
dst += dst_stride * sizeof(uint16_t);
|
||||
src += src_stride * sizeof(uint16_t);
|
||||
}
|
||||
} else {
|
||||
for (line = 0; line < height; line++) {
|
||||
uint8_t *dst_u8 = dst;
|
||||
const uint8_t *src_u8 = src;
|
||||
|
||||
for (col = 0; col < width; col++)
|
||||
*dst_u8++ = dng_process_color8(*src_u8++, s->dng_lut, s->black_level, scale_factor);
|
||||
|
||||
dst += dst_stride;
|
||||
src += src_stride;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void av_always_inline horizontal_fill(TiffContext *s,
|
||||
unsigned int bpp, uint8_t* dst,
|
||||
@@ -553,7 +645,108 @@ static int tiff_unpack_fax(TiffContext *s, uint8_t *dst, int stride,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int dng_decode_strip(AVCodecContext *avctx, AVFrame *frame);
|
||||
static int dng_decode_jpeg(AVCodecContext *avctx, AVFrame *frame,
|
||||
int tile_byte_count, int dst_x, int dst_y, int w, int h)
|
||||
{
|
||||
TiffContext *s = avctx->priv_data;
|
||||
uint8_t *dst_data, *src_data;
|
||||
uint32_t dst_offset; /* offset from dst buffer in pixels */
|
||||
int is_single_comp, is_u16, pixel_size;
|
||||
int ret;
|
||||
|
||||
if (tile_byte_count < 0 || tile_byte_count > bytestream2_get_bytes_left(&s->gb))
|
||||
return AVERROR_INVALIDDATA;
|
||||
|
||||
/* Prepare a packet and send to the MJPEG decoder */
|
||||
av_packet_unref(s->jpkt);
|
||||
s->jpkt->data = (uint8_t*)s->gb.buffer;
|
||||
s->jpkt->size = tile_byte_count;
|
||||
|
||||
if (s->is_bayer) {
|
||||
MJpegDecodeContext *mjpegdecctx = s->avctx_mjpeg->priv_data;
|
||||
/* We have to set this information here, there is no way to know if a given JPEG is a DNG-embedded
|
||||
image or not from its own data (and we need that information when decoding it). */
|
||||
mjpegdecctx->bayer = 1;
|
||||
}
|
||||
|
||||
ret = avcodec_send_packet(s->avctx_mjpeg, s->jpkt);
|
||||
if (ret < 0) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Error submitting a packet for decoding\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = avcodec_receive_frame(s->avctx_mjpeg, s->jpgframe);
|
||||
if (ret < 0) {
|
||||
av_log(avctx, AV_LOG_ERROR, "JPEG decoding error: %s.\n", av_err2str(ret));
|
||||
|
||||
/* Normally skip, error if explode */
|
||||
if (avctx->err_recognition & AV_EF_EXPLODE)
|
||||
return AVERROR_INVALIDDATA;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
is_u16 = (s->bpp > 8);
|
||||
|
||||
/* Copy the outputted tile's pixels from 'jpgframe' to 'frame' (final buffer) */
|
||||
|
||||
if (s->jpgframe->width != s->avctx_mjpeg->width ||
|
||||
s->jpgframe->height != s->avctx_mjpeg->height ||
|
||||
s->jpgframe->format != s->avctx_mjpeg->pix_fmt)
|
||||
return AVERROR_INVALIDDATA;
|
||||
|
||||
/* See dng_blit for explanation */
|
||||
if (s->avctx_mjpeg->width == w * 2 &&
|
||||
s->avctx_mjpeg->height == h / 2 &&
|
||||
s->avctx_mjpeg->pix_fmt == AV_PIX_FMT_GRAY16LE) {
|
||||
is_single_comp = 1;
|
||||
} else if (s->avctx_mjpeg->width >= w &&
|
||||
s->avctx_mjpeg->height >= h &&
|
||||
s->avctx_mjpeg->pix_fmt == (is_u16 ? AV_PIX_FMT_GRAY16 : AV_PIX_FMT_GRAY8)
|
||||
) {
|
||||
is_single_comp = 0;
|
||||
} else
|
||||
return AVERROR_INVALIDDATA;
|
||||
|
||||
pixel_size = (is_u16 ? sizeof(uint16_t) : sizeof(uint8_t));
|
||||
|
||||
if (is_single_comp && !is_u16) {
|
||||
av_log(s->avctx, AV_LOG_ERROR, "DNGs with bpp <= 8 and 1 component are unsupported\n");
|
||||
av_frame_unref(s->jpgframe);
|
||||
return AVERROR_PATCHWELCOME;
|
||||
}
|
||||
|
||||
dst_offset = dst_x + frame->linesize[0] * dst_y / pixel_size;
|
||||
dst_data = frame->data[0] + dst_offset * pixel_size;
|
||||
src_data = s->jpgframe->data[0];
|
||||
|
||||
dng_blit(s,
|
||||
dst_data,
|
||||
frame->linesize[0] / pixel_size,
|
||||
src_data,
|
||||
s->jpgframe->linesize[0] / pixel_size,
|
||||
w,
|
||||
h,
|
||||
is_single_comp,
|
||||
is_u16);
|
||||
|
||||
av_frame_unref(s->jpgframe);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dng_decode_strip(AVCodecContext *avctx, AVFrame *frame)
|
||||
{
|
||||
TiffContext *s = avctx->priv_data;
|
||||
|
||||
s->jpgframe->width = s->width;
|
||||
s->jpgframe->height = s->height;
|
||||
|
||||
s->avctx_mjpeg->width = s->width;
|
||||
s->avctx_mjpeg->height = s->height;
|
||||
|
||||
return dng_decode_jpeg(avctx, frame, s->stripsize, 0, 0, s->width, s->height);
|
||||
}
|
||||
|
||||
static int tiff_unpack_strip(TiffContext *s, AVFrame *p, uint8_t *dst, int stride,
|
||||
const uint8_t *src, int size, int strip_start, int lines)
|
||||
@@ -780,190 +973,6 @@ static int tiff_unpack_strip(TiffContext *s, AVFrame *p, uint8_t *dst, int strid
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Map stored raw sensor values into linear reference values (see: DNG Specification - Chapter 5)
|
||||
*/
|
||||
static uint16_t av_always_inline dng_process_color16(uint16_t value,
|
||||
const uint16_t *lut,
|
||||
uint16_t black_level,
|
||||
float scale_factor) {
|
||||
float value_norm;
|
||||
|
||||
// Lookup table lookup
|
||||
if (lut)
|
||||
value = lut[value];
|
||||
|
||||
// Black level subtraction
|
||||
value = av_clip_uint16_c((unsigned)value - black_level);
|
||||
|
||||
// Color scaling
|
||||
value_norm = (float)value * scale_factor;
|
||||
|
||||
value = av_clip_uint16_c(value_norm * 65535);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static uint16_t av_always_inline dng_process_color8(uint16_t value,
|
||||
const uint16_t *lut,
|
||||
uint16_t black_level,
|
||||
float scale_factor) {
|
||||
return dng_process_color16(value, lut, black_level, scale_factor) >> 8;
|
||||
}
|
||||
|
||||
static void dng_blit(TiffContext *s, uint8_t *dst, int dst_stride,
|
||||
const uint8_t *src, int src_stride,
|
||||
int width, int height, int is_single_comp, int is_u16)
|
||||
{
|
||||
int line, col;
|
||||
float scale_factor;
|
||||
|
||||
scale_factor = 1.0f / (s->white_level - s->black_level);
|
||||
|
||||
if (is_single_comp) {
|
||||
if (!is_u16)
|
||||
return; /* <= 8bpp unsupported */
|
||||
|
||||
/* Image is double the width and half the height we need, each row comprises 2 rows of the output
|
||||
(split vertically in the middle). */
|
||||
for (line = 0; line < height / 2; line++) {
|
||||
uint16_t *dst_u16 = (uint16_t *)dst;
|
||||
uint16_t *src_u16 = (uint16_t *)src;
|
||||
|
||||
/* Blit first half of input row row to initial row of output */
|
||||
for (col = 0; col < width; col++)
|
||||
*dst_u16++ = dng_process_color16(*src_u16++, s->dng_lut, s->black_level, scale_factor);
|
||||
|
||||
/* Advance the destination pointer by a row (source pointer remains in the same place) */
|
||||
dst += dst_stride * sizeof(uint16_t);
|
||||
dst_u16 = (uint16_t *)dst;
|
||||
|
||||
/* Blit second half of input row row to next row of output */
|
||||
for (col = 0; col < width; col++)
|
||||
*dst_u16++ = dng_process_color16(*src_u16++, s->dng_lut, s->black_level, scale_factor);
|
||||
|
||||
dst += dst_stride * sizeof(uint16_t);
|
||||
src += src_stride * sizeof(uint16_t);
|
||||
}
|
||||
} else {
|
||||
/* Input and output image are the same size and the MJpeg decoder has done per-component
|
||||
deinterleaving, so blitting here is straightforward. */
|
||||
if (is_u16) {
|
||||
for (line = 0; line < height; line++) {
|
||||
uint16_t *dst_u16 = (uint16_t *)dst;
|
||||
uint16_t *src_u16 = (uint16_t *)src;
|
||||
|
||||
for (col = 0; col < width; col++)
|
||||
*dst_u16++ = dng_process_color16(*src_u16++, s->dng_lut, s->black_level, scale_factor);
|
||||
|
||||
dst += dst_stride * sizeof(uint16_t);
|
||||
src += src_stride * sizeof(uint16_t);
|
||||
}
|
||||
} else {
|
||||
for (line = 0; line < height; line++) {
|
||||
uint8_t *dst_u8 = dst;
|
||||
const uint8_t *src_u8 = src;
|
||||
|
||||
for (col = 0; col < width; col++)
|
||||
*dst_u8++ = dng_process_color8(*src_u8++, s->dng_lut, s->black_level, scale_factor);
|
||||
|
||||
dst += dst_stride;
|
||||
src += src_stride;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int dng_decode_jpeg(AVCodecContext *avctx, AVFrame *frame,
|
||||
int tile_byte_count, int dst_x, int dst_y, int w, int h)
|
||||
{
|
||||
TiffContext *s = avctx->priv_data;
|
||||
uint8_t *dst_data, *src_data;
|
||||
uint32_t dst_offset; /* offset from dst buffer in pixels */
|
||||
int is_single_comp, is_u16, pixel_size;
|
||||
int ret;
|
||||
|
||||
if (tile_byte_count < 0 || tile_byte_count > bytestream2_get_bytes_left(&s->gb))
|
||||
return AVERROR_INVALIDDATA;
|
||||
|
||||
/* Prepare a packet and send to the MJPEG decoder */
|
||||
av_packet_unref(s->jpkt);
|
||||
s->jpkt->data = (uint8_t*)s->gb.buffer;
|
||||
s->jpkt->size = tile_byte_count;
|
||||
|
||||
if (s->is_bayer) {
|
||||
MJpegDecodeContext *mjpegdecctx = s->avctx_mjpeg->priv_data;
|
||||
/* We have to set this information here, there is no way to know if a given JPEG is a DNG-embedded
|
||||
image or not from its own data (and we need that information when decoding it). */
|
||||
mjpegdecctx->bayer = 1;
|
||||
}
|
||||
|
||||
ret = avcodec_send_packet(s->avctx_mjpeg, s->jpkt);
|
||||
if (ret < 0) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Error submitting a packet for decoding\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = avcodec_receive_frame(s->avctx_mjpeg, s->jpgframe);
|
||||
if (ret < 0) {
|
||||
av_log(avctx, AV_LOG_ERROR, "JPEG decoding error: %s.\n", av_err2str(ret));
|
||||
|
||||
/* Normally skip, error if explode */
|
||||
if (avctx->err_recognition & AV_EF_EXPLODE)
|
||||
return AVERROR_INVALIDDATA;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
is_u16 = (s->bpp > 8);
|
||||
|
||||
/* Copy the outputted tile's pixels from 'jpgframe' to 'frame' (final buffer) */
|
||||
|
||||
if (s->jpgframe->width != s->avctx_mjpeg->width ||
|
||||
s->jpgframe->height != s->avctx_mjpeg->height ||
|
||||
s->jpgframe->format != s->avctx_mjpeg->pix_fmt)
|
||||
return AVERROR_INVALIDDATA;
|
||||
|
||||
/* See dng_blit for explanation */
|
||||
if (s->avctx_mjpeg->width == w * 2 &&
|
||||
s->avctx_mjpeg->height == h / 2 &&
|
||||
s->avctx_mjpeg->pix_fmt == AV_PIX_FMT_GRAY16LE) {
|
||||
is_single_comp = 1;
|
||||
} else if (s->avctx_mjpeg->width >= w &&
|
||||
s->avctx_mjpeg->height >= h &&
|
||||
s->avctx_mjpeg->pix_fmt == (is_u16 ? AV_PIX_FMT_GRAY16 : AV_PIX_FMT_GRAY8)
|
||||
) {
|
||||
is_single_comp = 0;
|
||||
} else
|
||||
return AVERROR_INVALIDDATA;
|
||||
|
||||
pixel_size = (is_u16 ? sizeof(uint16_t) : sizeof(uint8_t));
|
||||
|
||||
if (is_single_comp && !is_u16) {
|
||||
av_log(s->avctx, AV_LOG_ERROR, "DNGs with bpp <= 8 and 1 component are unsupported\n");
|
||||
av_frame_unref(s->jpgframe);
|
||||
return AVERROR_PATCHWELCOME;
|
||||
}
|
||||
|
||||
dst_offset = dst_x + frame->linesize[0] * dst_y / pixel_size;
|
||||
dst_data = frame->data[0] + dst_offset * pixel_size;
|
||||
src_data = s->jpgframe->data[0];
|
||||
|
||||
dng_blit(s,
|
||||
dst_data,
|
||||
frame->linesize[0] / pixel_size,
|
||||
src_data,
|
||||
s->jpgframe->linesize[0] / pixel_size,
|
||||
w,
|
||||
h,
|
||||
is_single_comp,
|
||||
is_u16);
|
||||
|
||||
av_frame_unref(s->jpgframe);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dng_decode_tiles(AVCodecContext *avctx, AVFrame *frame,
|
||||
const AVPacket *avpkt)
|
||||
{
|
||||
@@ -1040,19 +1049,6 @@ static int dng_decode_tiles(AVCodecContext *avctx, AVFrame *frame,
|
||||
return avpkt->size;
|
||||
}
|
||||
|
||||
static int dng_decode_strip(AVCodecContext *avctx, AVFrame *frame)
|
||||
{
|
||||
TiffContext *s = avctx->priv_data;
|
||||
|
||||
s->jpgframe->width = s->width;
|
||||
s->jpgframe->height = s->height;
|
||||
|
||||
s->avctx_mjpeg->width = s->width;
|
||||
s->avctx_mjpeg->height = s->height;
|
||||
|
||||
return dng_decode_jpeg(avctx, frame, s->stripsize, 0, 0, s->width, s->height);
|
||||
}
|
||||
|
||||
static int init_image(TiffContext *s, ThreadFrame *frame)
|
||||
{
|
||||
int ret;
|
||||
|
||||
+8
-14
@@ -384,7 +384,7 @@ av_cold int ff_vc1_decode_init_alloc_tables(VC1Context *v)
|
||||
if (s->avctx->codec_id == AV_CODEC_ID_WMV3IMAGE || s->avctx->codec_id == AV_CODEC_ID_VC1IMAGE) {
|
||||
for (i = 0; i < 4; i++)
|
||||
if (!(v->sr_rows[i >> 1][i & 1] = av_malloc(v->output_width)))
|
||||
return AVERROR(ENOMEM);
|
||||
goto error;
|
||||
}
|
||||
|
||||
ret = ff_intrax8_common_init(s->avctx, &v->x8, &s->idsp,
|
||||
@@ -539,12 +539,6 @@ static av_cold int vc1_decode_init(AVCodecContext *avctx)
|
||||
ff_h264chroma_init(&v->h264chroma, 8);
|
||||
ff_qpeldsp_init(&s->qdsp);
|
||||
|
||||
// Must happen after calling ff_vc1_decode_end
|
||||
// to avoid de-allocating the sprite_output_frame
|
||||
v->sprite_output_frame = av_frame_alloc();
|
||||
if (!v->sprite_output_frame)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
avctx->has_b_frames = !!avctx->max_b_frames;
|
||||
|
||||
if (v->color_prim == 1 || v->color_prim == 5 || v->color_prim == 6)
|
||||
@@ -577,20 +571,15 @@ static av_cold int vc1_decode_init(AVCodecContext *avctx)
|
||||
v->sprite_height > 1 << 14 ||
|
||||
v->output_width > 1 << 14 ||
|
||||
v->output_height > 1 << 14) {
|
||||
ret = AVERROR_INVALIDDATA;
|
||||
goto error;
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
if ((v->sprite_width&1) || (v->sprite_height&1)) {
|
||||
avpriv_request_sample(avctx, "odd sprites support");
|
||||
ret = AVERROR_PATCHWELCOME;
|
||||
goto error;
|
||||
return AVERROR_PATCHWELCOME;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
error:
|
||||
av_frame_free(&v->sprite_output_frame);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Close a VC1/WMV3 decoder
|
||||
@@ -1147,6 +1136,11 @@ image:
|
||||
avctx->height = avctx->coded_height = v->output_height;
|
||||
if (avctx->skip_frame >= AVDISCARD_NONREF)
|
||||
goto end;
|
||||
if (!v->sprite_output_frame &&
|
||||
!(v->sprite_output_frame = av_frame_alloc())) {
|
||||
ret = AVERROR(ENOMEM);
|
||||
goto err;
|
||||
}
|
||||
#if CONFIG_WMV3IMAGE_DECODER || CONFIG_VC1IMAGE_DECODER
|
||||
if ((ret = vc1_decode_sprites(v, &s->gb)) < 0)
|
||||
goto err;
|
||||
|
||||
+12
-7
@@ -194,7 +194,7 @@ static int vmd_decode(VmdVideoContext *s, AVFrame *frame)
|
||||
unsigned char len;
|
||||
int ofs;
|
||||
|
||||
int frame_x, frame_y;
|
||||
int frame_x, frame_y, prev_linesize;
|
||||
int frame_width, frame_height;
|
||||
|
||||
frame_x = AV_RL16(&s->buf[6]);
|
||||
@@ -282,7 +282,13 @@ static int vmd_decode(VmdVideoContext *s, AVFrame *frame)
|
||||
}
|
||||
|
||||
dp = &frame->data[0][frame_y * frame->linesize[0] + frame_x];
|
||||
pp = &s->prev_frame->data[0][frame_y * s->prev_frame->linesize[0] + frame_x];
|
||||
if (s->prev_frame->data[0]) {
|
||||
prev_linesize = s->prev_frame->linesize[0];
|
||||
pp = s->prev_frame->data[0] + frame_y * prev_linesize + frame_x;
|
||||
} else {
|
||||
pp = NULL;
|
||||
prev_linesize = 0;
|
||||
}
|
||||
switch (meth) {
|
||||
case 1:
|
||||
for (i = 0; i < frame_height; i++) {
|
||||
@@ -298,7 +304,7 @@ static int vmd_decode(VmdVideoContext *s, AVFrame *frame)
|
||||
ofs += len;
|
||||
} else {
|
||||
/* interframe pixel copy */
|
||||
if (ofs + len + 1 > frame_width || !s->prev_frame->data[0])
|
||||
if (ofs + len + 1 > frame_width || !pp)
|
||||
return AVERROR_INVALIDDATA;
|
||||
memcpy(&dp[ofs], &pp[ofs], len + 1);
|
||||
ofs += len + 1;
|
||||
@@ -311,7 +317,7 @@ static int vmd_decode(VmdVideoContext *s, AVFrame *frame)
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
dp += frame->linesize[0];
|
||||
pp += s->prev_frame->linesize[0];
|
||||
pp = FF_PTR_ADD(pp, prev_linesize);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -319,7 +325,6 @@ static int vmd_decode(VmdVideoContext *s, AVFrame *frame)
|
||||
for (i = 0; i < frame_height; i++) {
|
||||
bytestream2_get_buffer(&gb, dp, frame_width);
|
||||
dp += frame->linesize[0];
|
||||
pp += s->prev_frame->linesize[0];
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -347,7 +352,7 @@ static int vmd_decode(VmdVideoContext *s, AVFrame *frame)
|
||||
}
|
||||
} else {
|
||||
/* interframe pixel copy */
|
||||
if (ofs + len + 1 > frame_width || !s->prev_frame->data[0])
|
||||
if (ofs + len + 1 > frame_width || !pp)
|
||||
return AVERROR_INVALIDDATA;
|
||||
memcpy(&dp[ofs], &pp[ofs], len + 1);
|
||||
ofs += len + 1;
|
||||
@@ -360,7 +365,7 @@ static int vmd_decode(VmdVideoContext *s, AVFrame *frame)
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
dp += frame->linesize[0];
|
||||
pp += s->prev_frame->linesize[0];
|
||||
pp = FF_PTR_ADD(pp, prev_linesize);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -367,7 +367,7 @@ static av_cold void wmavoice_flush(AVCodecContext *ctx)
|
||||
static av_cold int wmavoice_decode_init(AVCodecContext *ctx)
|
||||
{
|
||||
static AVOnce init_static_once = AV_ONCE_INIT;
|
||||
int n, flags, pitch_range, lsp16_flag;
|
||||
int n, flags, pitch_range, lsp16_flag, ret;
|
||||
WMAVoiceContext *s = ctx->priv_data;
|
||||
|
||||
ff_thread_once(&init_static_once, wmavoice_init_static_data);
|
||||
@@ -395,10 +395,11 @@ static av_cold int wmavoice_decode_init(AVCodecContext *ctx)
|
||||
s->spillover_bitsize = 3 + av_ceil_log2(ctx->block_align);
|
||||
s->do_apf = flags & 0x1;
|
||||
if (s->do_apf) {
|
||||
ff_rdft_init(&s->rdft, 7, DFT_R2C);
|
||||
ff_rdft_init(&s->irdft, 7, IDFT_C2R);
|
||||
ff_dct_init(&s->dct, 6, DCT_I);
|
||||
ff_dct_init(&s->dst, 6, DST_I);
|
||||
if ((ret = ff_rdft_init(&s->rdft, 7, DFT_R2C)) < 0 ||
|
||||
(ret = ff_rdft_init(&s->irdft, 7, IDFT_C2R)) < 0 ||
|
||||
(ret = ff_dct_init (&s->dct, 6, DCT_I)) < 0 ||
|
||||
(ret = ff_dct_init (&s->dst, 6, DST_I)) < 0)
|
||||
return ret;
|
||||
|
||||
ff_sine_window_init(s->cos, 256);
|
||||
memcpy(&s->sin[255], s->cos, 256 * sizeof(s->cos[0]));
|
||||
|
||||
@@ -1053,7 +1053,7 @@ static int hdcd_integrate(HDCDContext *ctx, hdcd_state *states, int channels, in
|
||||
|
||||
for (j = result - 1; j >= 0; j--) {
|
||||
for (i = 0; i < channels; i++)
|
||||
bits[i] |= (*(samples++) & 1) << j;
|
||||
bits[i] |= (*(samples++) & 1U) << j;
|
||||
samples += stride - channels;
|
||||
}
|
||||
|
||||
@@ -1210,7 +1210,7 @@ static int hdcd_analyze(int32_t *samples, int count, int stride, int gain, int t
|
||||
int32_t *samples_end = samples + stride * count;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
samples[i * stride] <<= 15;
|
||||
samples[i * stride] *= 1 << 15;
|
||||
if (mode == HDCD_ANA_PE) {
|
||||
int pel = (samples[i * stride] >> 16) & 1;
|
||||
int32_t sample = samples[i * stride];
|
||||
@@ -1284,13 +1284,13 @@ static int hdcd_envelope(int32_t *samples, int count, int stride, int vbits, int
|
||||
av_assert0(asample <= max_asample);
|
||||
sample = sample >= 0 ? peaktab[asample] : -peaktab[asample];
|
||||
} else
|
||||
sample <<= shft;
|
||||
sample *= (1 << shft);
|
||||
|
||||
samples[i * stride] = sample;
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < count; i++)
|
||||
samples[i * stride] <<= shft;
|
||||
samples[i * stride] *= (1 << shft);
|
||||
}
|
||||
|
||||
if (gain <= target_gain) {
|
||||
|
||||
@@ -247,7 +247,7 @@ static int request_frame(AVFilterLink *outlink)
|
||||
samples[i] = sine->sin[sine->phi >> (32 - LOG_PERIOD)];
|
||||
sine->phi += sine->dphi;
|
||||
if (sine->beep_index < sine->beep_length) {
|
||||
samples[i] += sine->sin[sine->phi_beep >> (32 - LOG_PERIOD)] << 1;
|
||||
samples[i] += sine->sin[sine->phi_beep >> (32 - LOG_PERIOD)] * 2;
|
||||
sine->phi_beep += sine->dphi_beep;
|
||||
}
|
||||
if (++sine->beep_index == sine->beep_period)
|
||||
|
||||
@@ -141,7 +141,7 @@ static void draw_line(uint8_t *buf, int sx, int sy, int ex, int ey,
|
||||
}
|
||||
buf += sx + sy * stride;
|
||||
ex -= sx;
|
||||
f = ((ey - sy) << 16) / ex;
|
||||
f = ((ey - sy) * (1 << 16)) / ex;
|
||||
for (x = 0; x <= ex; x++) {
|
||||
y = (x * f) >> 16;
|
||||
fr = (x * f) & 0xFFFF;
|
||||
@@ -156,7 +156,7 @@ static void draw_line(uint8_t *buf, int sx, int sy, int ex, int ey,
|
||||
buf += sx + sy * stride;
|
||||
ey -= sy;
|
||||
if (ey)
|
||||
f = ((ex - sx) << 16) / ey;
|
||||
f = ((ex - sx) * (1 << 16)) / ey;
|
||||
else
|
||||
f = 0;
|
||||
for(y= 0; y <= ey; y++){
|
||||
@@ -199,8 +199,8 @@ static void draw_arrow(uint8_t *buf, int sx, int sy, int ex,
|
||||
int length = sqrt((rx * rx + ry * ry) << 8);
|
||||
|
||||
// FIXME subpixel accuracy
|
||||
rx = ROUNDED_DIV(rx * 3 << 4, length);
|
||||
ry = ROUNDED_DIV(ry * 3 << 4, length);
|
||||
rx = ROUNDED_DIV(rx * (3 << 4), length);
|
||||
ry = ROUNDED_DIV(ry * (3 << 4), length);
|
||||
|
||||
if (tail) {
|
||||
rx = -rx;
|
||||
|
||||
@@ -57,7 +57,7 @@ static int cudaupload_query_formats(AVFilterContext *ctx)
|
||||
int ret;
|
||||
|
||||
static const enum AVPixelFormat input_pix_fmts[] = {
|
||||
AV_PIX_FMT_NV12, AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV444P,
|
||||
AV_PIX_FMT_NV12, AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUV444P,
|
||||
AV_PIX_FMT_P010, AV_PIX_FMT_P016, AV_PIX_FMT_YUV444P16,
|
||||
AV_PIX_FMT_0RGB32, AV_PIX_FMT_0BGR32,
|
||||
#if CONFIG_VULKAN
|
||||
|
||||
@@ -157,9 +157,12 @@ static int overlay_cuda_blend(FFFrameSync *fs)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (!input_main || !input_overlay)
|
||||
if (!input_main)
|
||||
return AVERROR_BUG;
|
||||
|
||||
if (!input_overlay)
|
||||
return ff_filter_frame(outlink, input_main);
|
||||
|
||||
ret = av_frame_make_writable(input_main);
|
||||
if (ret < 0) {
|
||||
av_frame_free(&input_main);
|
||||
|
||||
@@ -152,9 +152,10 @@ static int query_formats(AVFilterContext *ctx)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static av_always_inline int dither_color(uint32_t px, int er, int eg, int eb, int scale, int shift)
|
||||
static av_always_inline uint32_t dither_color(uint32_t px, int er, int eg,
|
||||
int eb, int scale, int shift)
|
||||
{
|
||||
return av_clip_uint8( px >> 24 ) << 24
|
||||
return px >> 24 << 24
|
||||
| av_clip_uint8((px >> 16 & 0xff) + ((er * scale) / (1<<shift))) << 16
|
||||
| av_clip_uint8((px >> 8 & 0xff) + ((eg * scale) / (1<<shift))) << 8
|
||||
| av_clip_uint8((px & 0xff) + ((eb * scale) / (1<<shift)));
|
||||
|
||||
@@ -635,8 +635,8 @@ static int scale_slice(AVFilterLink *link, AVFrame *out_buf, AVFrame *cur_pic, s
|
||||
int vsub= ((i+1)&2) ? scale->vsub : 0;
|
||||
in_stride[i] = cur_pic->linesize[i] * mul;
|
||||
out_stride[i] = out_buf->linesize[i] * mul;
|
||||
in[i] = cur_pic->data[i] + ((y>>vsub)+field) * cur_pic->linesize[i];
|
||||
out[i] = out_buf->data[i] + field * out_buf->linesize[i];
|
||||
in[i] = FF_PTR_ADD(cur_pic->data[i], ((y>>vsub)+field) * cur_pic->linesize[i]);
|
||||
out[i] = FF_PTR_ADD(out_buf->data[i], field * out_buf->linesize[i]);
|
||||
}
|
||||
if (scale->input_is_pal)
|
||||
in[1] = cur_pic->data[1];
|
||||
|
||||
+5
-2
@@ -229,8 +229,11 @@ static int aa_read_header(AVFormatContext *s)
|
||||
chapter_pos -= start + CHAPTER_HEADER_SIZE * chapter_idx;
|
||||
avio_skip(pb, 4 + chapter_size);
|
||||
if (!avpriv_new_chapter(s, chapter_idx, st->time_base,
|
||||
chapter_pos * TIMEPREC, (chapter_pos + chapter_size) * TIMEPREC, NULL))
|
||||
return AVERROR(ENOMEM);
|
||||
chapter_pos * TIMEPREC,
|
||||
(chapter_pos + chapter_size) * TIMEPREC, NULL)) {
|
||||
av_freep(&c->tea_ctx);
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
}
|
||||
|
||||
st->duration = (largest_size - CHAPTER_HEADER_SIZE * s->nb_chapters) * TIMEPREC;
|
||||
|
||||
+32
-18
@@ -72,38 +72,39 @@ static int alp_read_header(AVFormatContext *s)
|
||||
{
|
||||
int ret;
|
||||
AVStream *st;
|
||||
ALPHeader hdr;
|
||||
ALPHeader *hdr = s->priv_data;
|
||||
AVCodecParameters *par;
|
||||
|
||||
if ((hdr.magic = avio_rl32(s->pb)) != ALP_TAG)
|
||||
if ((hdr->magic = avio_rl32(s->pb)) != ALP_TAG)
|
||||
return AVERROR_INVALIDDATA;
|
||||
|
||||
hdr.header_size = avio_rl32(s->pb);
|
||||
hdr->header_size = avio_rl32(s->pb);
|
||||
|
||||
if (hdr.header_size != 8 && hdr.header_size != 12) {
|
||||
if (hdr->header_size != 8 && hdr->header_size != 12) {
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
if ((ret = avio_read(s->pb, hdr.adpcm, sizeof(hdr.adpcm))) < 0)
|
||||
if ((ret = avio_read(s->pb, hdr->adpcm, sizeof(hdr->adpcm))) < 0)
|
||||
return ret;
|
||||
else if (ret != sizeof(hdr.adpcm))
|
||||
else if (ret != sizeof(hdr->adpcm))
|
||||
return AVERROR(EIO);
|
||||
|
||||
if (strncmp("ADPCM", hdr.adpcm, sizeof(hdr.adpcm)) != 0)
|
||||
if (strncmp("ADPCM", hdr->adpcm, sizeof(hdr->adpcm)) != 0)
|
||||
return AVERROR_INVALIDDATA;
|
||||
|
||||
hdr.unk1 = avio_r8(s->pb);
|
||||
hdr.num_channels = avio_r8(s->pb);
|
||||
hdr->unk1 = avio_r8(s->pb);
|
||||
hdr->num_channels = avio_r8(s->pb);
|
||||
|
||||
if (hdr.header_size == 8) {
|
||||
if (hdr->header_size == 8) {
|
||||
/* .TUN music file */
|
||||
hdr.sample_rate = 22050;
|
||||
hdr->sample_rate = 22050;
|
||||
|
||||
} else {
|
||||
/* .PCM sound file */
|
||||
hdr.sample_rate = avio_rl32(s->pb);
|
||||
hdr->sample_rate = avio_rl32(s->pb);
|
||||
}
|
||||
|
||||
if (hdr.sample_rate > 44100) {
|
||||
if (hdr->sample_rate > 44100) {
|
||||
avpriv_request_sample(s, "Sample Rate > 44100");
|
||||
return AVERROR_PATCHWELCOME;
|
||||
}
|
||||
@@ -115,12 +116,12 @@ static int alp_read_header(AVFormatContext *s)
|
||||
par->codec_type = AVMEDIA_TYPE_AUDIO;
|
||||
par->codec_id = AV_CODEC_ID_ADPCM_IMA_ALP;
|
||||
par->format = AV_SAMPLE_FMT_S16;
|
||||
par->sample_rate = hdr.sample_rate;
|
||||
par->channels = hdr.num_channels;
|
||||
par->sample_rate = hdr->sample_rate;
|
||||
par->channels = hdr->num_channels;
|
||||
|
||||
if (hdr.num_channels == 1)
|
||||
if (hdr->num_channels == 1)
|
||||
par->channel_layout = AV_CH_LAYOUT_MONO;
|
||||
else if (hdr.num_channels == 2)
|
||||
else if (hdr->num_channels == 2)
|
||||
par->channel_layout = AV_CH_LAYOUT_STEREO;
|
||||
else
|
||||
return AVERROR_INVALIDDATA;
|
||||
@@ -151,12 +152,25 @@ static int alp_read_packet(AVFormatContext *s, AVPacket *pkt)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int alp_seek(AVFormatContext *s, int stream_index,
|
||||
int64_t pts, int flags)
|
||||
{
|
||||
const ALPHeader *hdr = s->priv_data;
|
||||
|
||||
if (pts != 0)
|
||||
return AVERROR(EINVAL);
|
||||
|
||||
return avio_seek(s->pb, hdr->header_size + 8, SEEK_SET);
|
||||
}
|
||||
|
||||
AVInputFormat ff_alp_demuxer = {
|
||||
.name = "alp",
|
||||
.long_name = NULL_IF_CONFIG_SMALL("LEGO Racers ALP"),
|
||||
.priv_data_size = sizeof(ALPHeader),
|
||||
.read_probe = alp_probe,
|
||||
.read_header = alp_read_header,
|
||||
.read_packet = alp_read_packet
|
||||
.read_packet = alp_read_packet,
|
||||
.read_seek = alp_seek,
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
+1
-1
@@ -444,7 +444,7 @@ static int ape_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp
|
||||
if (index < 0)
|
||||
return -1;
|
||||
|
||||
if ((ret = avio_seek(s->pb, st->internal->index_entries[index].pos, SEEK_SET)) < 0)
|
||||
if ((ret = avio_seek(s->pb, st->index_entries[index].pos, SEEK_SET)) < 0)
|
||||
return ret;
|
||||
ape->currentframe = index;
|
||||
return 0;
|
||||
|
||||
@@ -1690,11 +1690,11 @@ static int asf_read_seek(AVFormatContext *s, int stream_index,
|
||||
asf->index_read = -1;
|
||||
}
|
||||
|
||||
if (asf->index_read > 0 && st->internal->index_entries) {
|
||||
if (asf->index_read > 0 && st->index_entries) {
|
||||
int index = av_index_search_timestamp(st, pts, flags);
|
||||
if (index >= 0) {
|
||||
/* find the position */
|
||||
uint64_t pos = st->internal->index_entries[index].pos;
|
||||
uint64_t pos = st->index_entries[index].pos;
|
||||
|
||||
/* do the seek */
|
||||
av_log(s, AV_LOG_DEBUG, "SEEKTO: %"PRId64"\n", pos);
|
||||
|
||||
@@ -1636,11 +1636,11 @@ static int asf_read_seek(AVFormatContext *s, int stream_index,
|
||||
ASFContext *asf = s->priv_data;
|
||||
int idx, ret;
|
||||
|
||||
if (s->streams[stream_index]->internal->nb_index_entries && asf->is_simple_index) {
|
||||
if (s->streams[stream_index]->nb_index_entries && asf->is_simple_index) {
|
||||
idx = av_index_search_timestamp(s->streams[stream_index], timestamp, flags);
|
||||
if (idx < 0 || idx >= s->streams[stream_index]->internal->nb_index_entries)
|
||||
if (idx < 0 || idx >= s->streams[stream_index]->nb_index_entries)
|
||||
return AVERROR_INVALIDDATA;
|
||||
avio_seek(s->pb, s->streams[stream_index]->internal->index_entries[idx].pos, SEEK_SET);
|
||||
avio_seek(s->pb, s->streams[stream_index]->index_entries[idx].pos, SEEK_SET);
|
||||
} else {
|
||||
if ((ret = ff_seek_frame_binary(s, stream_index, timestamp, flags)) < 0)
|
||||
return ret;
|
||||
|
||||
@@ -954,11 +954,7 @@ typedef struct AVStream {
|
||||
* decoding: set by libavformat, must not be modified by the caller.
|
||||
* encoding: unused
|
||||
*/
|
||||
#if FF_API_INIT_PACKET
|
||||
AVPacket attached_pic;
|
||||
#else
|
||||
AVPacket *attached_pic;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* An array of side data that applies to the whole stream (i.e. the
|
||||
@@ -1092,10 +1088,11 @@ typedef struct AVStream {
|
||||
void *unused7;
|
||||
AVProbeData unused6;
|
||||
int64_t unused5[16+1];
|
||||
void *unused2;
|
||||
int unused3;
|
||||
unsigned int unused4;
|
||||
#endif
|
||||
AVIndexEntry *index_entries; /**< Only used if the format does not
|
||||
support seeking natively. */
|
||||
int nb_index_entries;
|
||||
unsigned int index_entries_allocated_size;
|
||||
|
||||
/**
|
||||
* Stream Identifier
|
||||
|
||||
+51
-51
@@ -281,7 +281,7 @@ static void clean_index(AVFormatContext *s)
|
||||
for (i = 0; i < s->nb_streams; i++) {
|
||||
AVStream *st = s->streams[i];
|
||||
AVIStream *ast = st->priv_data;
|
||||
int n = st->internal->nb_index_entries;
|
||||
int n = st->nb_index_entries;
|
||||
int max = ast->sample_size;
|
||||
int64_t pos, size, ts;
|
||||
|
||||
@@ -291,9 +291,9 @@ static void clean_index(AVFormatContext *s)
|
||||
while (max < 1024)
|
||||
max += max;
|
||||
|
||||
pos = st->internal->index_entries[0].pos;
|
||||
size = st->internal->index_entries[0].size;
|
||||
ts = st->internal->index_entries[0].timestamp;
|
||||
pos = st->index_entries[0].pos;
|
||||
size = st->index_entries[0].size;
|
||||
ts = st->index_entries[0].timestamp;
|
||||
|
||||
for (j = 0; j < size; j += max)
|
||||
av_add_index_entry(st, pos + j, ts + j, FFMIN(max, size - j), 0,
|
||||
@@ -441,12 +441,12 @@ static int calculate_bitrate(AVFormatContext *s)
|
||||
int64_t len = 0;
|
||||
AVStream *st = s->streams[i];
|
||||
|
||||
if (!st->internal->nb_index_entries)
|
||||
if (!st->nb_index_entries)
|
||||
continue;
|
||||
|
||||
for (j = 0; j < st->internal->nb_index_entries; j++)
|
||||
len += st->internal->index_entries[j].size;
|
||||
maxpos = FFMAX(maxpos, st->internal->index_entries[j-1].pos);
|
||||
for (j = 0; j < st->nb_index_entries; j++)
|
||||
len += st->index_entries[j].size;
|
||||
maxpos = FFMAX(maxpos, st->index_entries[j-1].pos);
|
||||
lensum += len;
|
||||
}
|
||||
if (maxpos < av_rescale(avi->io_fsize, 9, 10)) // index does not cover the whole file
|
||||
@@ -460,12 +460,12 @@ static int calculate_bitrate(AVFormatContext *s)
|
||||
int64_t duration;
|
||||
int64_t bitrate;
|
||||
|
||||
for (j = 0; j < st->internal->nb_index_entries; j++)
|
||||
len += st->internal->index_entries[j].size;
|
||||
for (j = 0; j < st->nb_index_entries; j++)
|
||||
len += st->index_entries[j].size;
|
||||
|
||||
if (st->internal->nb_index_entries < 2 || st->codecpar->bit_rate > 0)
|
||||
if (st->nb_index_entries < 2 || st->codecpar->bit_rate > 0)
|
||||
continue;
|
||||
duration = st->internal->index_entries[j-1].timestamp - st->internal->index_entries[0].timestamp;
|
||||
duration = st->index_entries[j-1].timestamp - st->index_entries[0].timestamp;
|
||||
bitrate = av_rescale(8*len, st->time_base.den, duration * st->time_base.num);
|
||||
if (bitrate > 0) {
|
||||
st->codecpar->bit_rate = bitrate;
|
||||
@@ -1057,7 +1057,7 @@ end_of_header:
|
||||
|
||||
for (i = 0; i < s->nb_streams; i++) {
|
||||
AVStream *st = s->streams[i];
|
||||
if (st->internal->nb_index_entries)
|
||||
if (st->nb_index_entries)
|
||||
break;
|
||||
}
|
||||
// DV-in-AVI cannot be non-interleaved, if set this must be
|
||||
@@ -1288,7 +1288,7 @@ start_sync:
|
||||
AVStream *st1 = s->streams[1];
|
||||
AVIStream *ast1 = st1->priv_data;
|
||||
// workaround for broken small-file-bug402.avi
|
||||
if ( d[2] == 'w' && d[3] == 'b'
|
||||
if (ast1 && d[2] == 'w' && d[3] == 'b'
|
||||
&& n == 0
|
||||
&& st ->codecpar->codec_type == AVMEDIA_TYPE_VIDEO
|
||||
&& st1->codecpar->codec_type == AVMEDIA_TYPE_AUDIO
|
||||
@@ -1347,8 +1347,8 @@ start_sync:
|
||||
|
||||
if (size) {
|
||||
uint64_t pos = avio_tell(pb) - 8;
|
||||
if (!st->internal->index_entries || !st->internal->nb_index_entries ||
|
||||
st->internal->index_entries[st->internal->nb_index_entries - 1].pos < pos) {
|
||||
if (!st->index_entries || !st->nb_index_entries ||
|
||||
st->index_entries[st->nb_index_entries - 1].pos < pos) {
|
||||
av_add_index_entry(st, pos, ast->frame_offset, size,
|
||||
0, AVINDEX_KEYFRAME);
|
||||
}
|
||||
@@ -1378,10 +1378,10 @@ static int ni_prepare_read(AVFormatContext *s)
|
||||
int64_t ts = ast->frame_offset;
|
||||
int64_t last_ts;
|
||||
|
||||
if (!st->internal->nb_index_entries)
|
||||
if (!st->nb_index_entries)
|
||||
continue;
|
||||
|
||||
last_ts = st->internal->index_entries[st->internal->nb_index_entries - 1].timestamp;
|
||||
last_ts = st->index_entries[st->nb_index_entries - 1].timestamp;
|
||||
if (!ast->remaining && ts > last_ts)
|
||||
continue;
|
||||
|
||||
@@ -1410,11 +1410,11 @@ static int ni_prepare_read(AVFormatContext *s)
|
||||
} else {
|
||||
i = av_index_search_timestamp(best_st, best_ts, AVSEEK_FLAG_ANY);
|
||||
if (i >= 0)
|
||||
best_ast->frame_offset = best_st->internal->index_entries[i].timestamp;
|
||||
best_ast->frame_offset = best_st->index_entries[i].timestamp;
|
||||
}
|
||||
|
||||
if (i >= 0) {
|
||||
int64_t pos = best_st->internal->index_entries[i].pos;
|
||||
int64_t pos = best_st->index_entries[i].pos;
|
||||
pos += best_ast->packet_size - best_ast->remaining;
|
||||
if (avio_seek(s->pb, pos + 8, SEEK_SET) < 0)
|
||||
return AVERROR_EOF;
|
||||
@@ -1424,7 +1424,7 @@ static int ni_prepare_read(AVFormatContext *s)
|
||||
avi->stream_index = best_stream_index;
|
||||
if (!best_ast->remaining)
|
||||
best_ast->packet_size =
|
||||
best_ast->remaining = best_st->internal->index_entries[i].size;
|
||||
best_ast->remaining = best_st->index_entries[i].size;
|
||||
}
|
||||
else
|
||||
return AVERROR_EOF;
|
||||
@@ -1515,15 +1515,15 @@ resync:
|
||||
pkt->dts /= ast->sample_size;
|
||||
pkt->stream_index = avi->stream_index;
|
||||
|
||||
if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && st->internal->index_entries) {
|
||||
if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && st->index_entries) {
|
||||
AVIndexEntry *e;
|
||||
int index;
|
||||
|
||||
index = av_index_search_timestamp(st, ast->frame_offset, AVSEEK_FLAG_ANY);
|
||||
e = &st->internal->index_entries[index];
|
||||
e = &st->index_entries[index];
|
||||
|
||||
if (index >= 0 && e->timestamp == ast->frame_offset) {
|
||||
if (index == st->internal->nb_index_entries-1) {
|
||||
if (index == st->nb_index_entries-1) {
|
||||
int key=1;
|
||||
uint32_t state=-1;
|
||||
if (st->codecpar->codec_id == AV_CODEC_ID_MPEG4) {
|
||||
@@ -1559,7 +1559,7 @@ resync:
|
||||
}
|
||||
ast->seek_pos= 0;
|
||||
|
||||
if (!avi->non_interleaved && st->internal->nb_index_entries>1 && avi->index_loaded>1) {
|
||||
if (!avi->non_interleaved && st->nb_index_entries>1 && avi->index_loaded>1) {
|
||||
int64_t dts= av_rescale_q(pkt->dts, st->time_base, AV_TIME_BASE_Q);
|
||||
|
||||
if (avi->dts_max < dts) {
|
||||
@@ -1659,8 +1659,8 @@ static int avi_read_idx1(AVFormatContext *s, int size)
|
||||
if (!anykey) {
|
||||
for (index = 0; index < s->nb_streams; index++) {
|
||||
st = s->streams[index];
|
||||
if (st->internal->nb_index_entries)
|
||||
st->internal->index_entries[0].flags |= AVINDEX_KEYFRAME;
|
||||
if (st->nb_index_entries)
|
||||
st->index_entries[0].flags |= AVINDEX_KEYFRAME;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
@@ -1685,16 +1685,16 @@ static int check_stream_max_drift(AVFormatContext *s)
|
||||
for (i = 0; i < s->nb_streams; i++) {
|
||||
AVStream *st = s->streams[i];
|
||||
AVIStream *ast = st->priv_data;
|
||||
int n = st->internal->nb_index_entries;
|
||||
while (idx[i] < n && st->internal->index_entries[idx[i]].pos < pos)
|
||||
int n = st->nb_index_entries;
|
||||
while (idx[i] < n && st->index_entries[idx[i]].pos < pos)
|
||||
idx[i]++;
|
||||
if (idx[i] < n) {
|
||||
int64_t dts;
|
||||
dts = av_rescale_q(st->internal->index_entries[idx[i]].timestamp /
|
||||
dts = av_rescale_q(st->index_entries[idx[i]].timestamp /
|
||||
FFMAX(ast->sample_size, 1),
|
||||
st->time_base, AV_TIME_BASE_Q);
|
||||
min_dts = FFMIN(min_dts, dts);
|
||||
min_pos = FFMIN(min_pos, st->internal->index_entries[idx[i]].pos);
|
||||
min_pos = FFMIN(min_pos, st->index_entries[idx[i]].pos);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < s->nb_streams; i++) {
|
||||
@@ -1703,7 +1703,7 @@ static int check_stream_max_drift(AVFormatContext *s)
|
||||
|
||||
if (idx[i] && min_dts != INT64_MAX / 2) {
|
||||
int64_t dts, delta_dts;
|
||||
dts = av_rescale_q(st->internal->index_entries[idx[i] - 1].timestamp /
|
||||
dts = av_rescale_q(st->index_entries[idx[i] - 1].timestamp /
|
||||
FFMAX(ast->sample_size, 1),
|
||||
st->time_base, AV_TIME_BASE_Q);
|
||||
delta_dts = av_sat_sub64(dts, min_dts);
|
||||
@@ -1733,30 +1733,30 @@ static int guess_ni_flag(AVFormatContext *s)
|
||||
|
||||
for (i = 0; i < s->nb_streams; i++) {
|
||||
AVStream *st = s->streams[i];
|
||||
int n = st->internal->nb_index_entries;
|
||||
int n = st->nb_index_entries;
|
||||
unsigned int size;
|
||||
|
||||
if (n <= 0)
|
||||
continue;
|
||||
|
||||
if (n >= 2) {
|
||||
int64_t pos = st->internal->index_entries[0].pos;
|
||||
int64_t pos = st->index_entries[0].pos;
|
||||
unsigned tag[2];
|
||||
avio_seek(s->pb, pos, SEEK_SET);
|
||||
tag[0] = avio_r8(s->pb);
|
||||
tag[1] = avio_r8(s->pb);
|
||||
avio_rl16(s->pb);
|
||||
size = avio_rl32(s->pb);
|
||||
if (get_stream_idx(tag) == i && pos + size > st->internal->index_entries[1].pos)
|
||||
if (get_stream_idx(tag) == i && pos + size > st->index_entries[1].pos)
|
||||
last_start = INT64_MAX;
|
||||
if (get_stream_idx(tag) == i && size == st->internal->index_entries[0].size + 8)
|
||||
if (get_stream_idx(tag) == i && size == st->index_entries[0].size + 8)
|
||||
last_start = INT64_MAX;
|
||||
}
|
||||
|
||||
if (st->internal->index_entries[0].pos > last_start)
|
||||
last_start = st->internal->index_entries[0].pos;
|
||||
if (st->internal->index_entries[n - 1].pos < first_end)
|
||||
first_end = st->internal->index_entries[n - 1].pos;
|
||||
if (st->index_entries[0].pos > last_start)
|
||||
last_start = st->index_entries[0].pos;
|
||||
if (st->index_entries[n - 1].pos < first_end)
|
||||
first_end = st->index_entries[n - 1].pos;
|
||||
}
|
||||
avio_seek(s->pb, oldpos, SEEK_SET);
|
||||
|
||||
@@ -1844,20 +1844,20 @@ static int avi_read_seek(AVFormatContext *s, int stream_index,
|
||||
timestamp * FFMAX(ast->sample_size, 1),
|
||||
flags);
|
||||
if (index < 0) {
|
||||
if (st->internal->nb_index_entries > 0)
|
||||
if (st->nb_index_entries > 0)
|
||||
av_log(s, AV_LOG_DEBUG, "Failed to find timestamp %"PRId64 " in index %"PRId64 " .. %"PRId64 "\n",
|
||||
timestamp * FFMAX(ast->sample_size, 1),
|
||||
st->internal->index_entries[0].timestamp,
|
||||
st->internal->index_entries[st->internal->nb_index_entries - 1].timestamp);
|
||||
st->index_entries[0].timestamp,
|
||||
st->index_entries[st->nb_index_entries - 1].timestamp);
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
/* find the position */
|
||||
pos = st->internal->index_entries[index].pos;
|
||||
timestamp = st->internal->index_entries[index].timestamp / FFMAX(ast->sample_size, 1);
|
||||
pos = st->index_entries[index].pos;
|
||||
timestamp = st->index_entries[index].timestamp / FFMAX(ast->sample_size, 1);
|
||||
|
||||
av_log(s, AV_LOG_TRACE, "XX %"PRId64" %d %"PRId64"\n",
|
||||
timestamp, index, st->internal->index_entries[index].timestamp);
|
||||
timestamp, index, st->index_entries[index].timestamp);
|
||||
|
||||
if (CONFIG_DV_DEMUXER && avi->dv_demux) {
|
||||
/* One and only one real stream for DV in AVI, and it has video */
|
||||
@@ -1888,7 +1888,7 @@ static int avi_read_seek(AVFormatContext *s, int stream_index,
|
||||
continue;
|
||||
}
|
||||
|
||||
if (st2->internal->nb_index_entries <= 0)
|
||||
if (st2->nb_index_entries <= 0)
|
||||
continue;
|
||||
|
||||
// av_assert1(st2->codecpar->block_align);
|
||||
@@ -1902,14 +1902,14 @@ static int avi_read_seek(AVFormatContext *s, int stream_index,
|
||||
(st2->codecpar->codec_type != AVMEDIA_TYPE_VIDEO ? AVSEEK_FLAG_ANY : 0));
|
||||
if (index < 0)
|
||||
index = 0;
|
||||
ast2->seek_pos = st2->internal->index_entries[index].pos;
|
||||
ast2->seek_pos = st2->index_entries[index].pos;
|
||||
pos_min = FFMIN(pos_min,ast2->seek_pos);
|
||||
}
|
||||
for (i = 0; i < s->nb_streams; i++) {
|
||||
AVStream *st2 = s->streams[i];
|
||||
AVIStream *ast2 = st2->priv_data;
|
||||
|
||||
if (ast2->sub_ctx || st2->internal->nb_index_entries <= 0)
|
||||
if (ast2->sub_ctx || st2->nb_index_entries <= 0)
|
||||
continue;
|
||||
|
||||
index = av_index_search_timestamp(
|
||||
@@ -1918,9 +1918,9 @@ static int avi_read_seek(AVFormatContext *s, int stream_index,
|
||||
flags | AVSEEK_FLAG_BACKWARD | (st2->codecpar->codec_type != AVMEDIA_TYPE_VIDEO ? AVSEEK_FLAG_ANY : 0));
|
||||
if (index < 0)
|
||||
index = 0;
|
||||
while (!avi->non_interleaved && index>0 && st2->internal->index_entries[index-1].pos >= pos_min)
|
||||
while (!avi->non_interleaved && index>0 && st2->index_entries[index-1].pos >= pos_min)
|
||||
index--;
|
||||
ast2->frame_offset = st2->internal->index_entries[index].timestamp;
|
||||
ast2->frame_offset = st2->index_entries[index].timestamp;
|
||||
}
|
||||
|
||||
/* do the seek */
|
||||
|
||||
+5
-5
@@ -225,8 +225,8 @@ static int read_header(AVFormatContext *s)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (vst->internal->index_entries)
|
||||
avio_seek(pb, vst->internal->index_entries[0].pos + bink->smush_size, SEEK_SET);
|
||||
if (vst->index_entries)
|
||||
avio_seek(pb, vst->index_entries[0].pos + bink->smush_size, SEEK_SET);
|
||||
else
|
||||
avio_skip(pb, 4);
|
||||
|
||||
@@ -256,8 +256,8 @@ static int read_packet(AVFormatContext *s, AVPacket *pkt)
|
||||
return AVERROR(EIO);
|
||||
}
|
||||
|
||||
bink->remain_packet_size = st->internal->index_entries[index_entry].size;
|
||||
bink->flags = st->internal->index_entries[index_entry].flags;
|
||||
bink->remain_packet_size = st->index_entries[index_entry].size;
|
||||
bink->flags = st->index_entries[index_entry].flags;
|
||||
bink->current_track = 0;
|
||||
}
|
||||
|
||||
@@ -313,7 +313,7 @@ static int read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, in
|
||||
return -1;
|
||||
|
||||
/* seek to the first frame */
|
||||
ret = avio_seek(s->pb, vst->internal->index_entries[0].pos + bink->smush_size, SEEK_SET);
|
||||
ret = avio_seek(s->pb, vst->index_entries[0].pos + bink->smush_size, SEEK_SET);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
||||
+25
-20
@@ -204,15 +204,20 @@ static int read_pakt_chunk(AVFormatContext *s, int64_t size)
|
||||
st->nb_frames += avio_rb32(pb); /* priming frames */
|
||||
st->nb_frames += avio_rb32(pb); /* remainder frames */
|
||||
|
||||
st->duration = 0;
|
||||
for (i = 0; i < num_packets; i++) {
|
||||
if (avio_feof(pb))
|
||||
return AVERROR_INVALIDDATA;
|
||||
ret = av_add_index_entry(s->streams[0], pos, st->duration, 0, 0, AVINDEX_KEYFRAME);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
pos += caf->bytes_per_packet ? caf->bytes_per_packet : ff_mp4_read_descr_len(pb);
|
||||
st->duration += caf->frames_per_packet ? caf->frames_per_packet : ff_mp4_read_descr_len(pb);
|
||||
if (caf->bytes_per_packet > 0 && caf->frames_per_packet > 0) {
|
||||
st->duration = caf->frames_per_packet * num_packets;
|
||||
pos = caf-> bytes_per_packet * num_packets;
|
||||
} else {
|
||||
st->duration = 0;
|
||||
for (i = 0; i < num_packets; i++) {
|
||||
if (avio_feof(pb))
|
||||
return AVERROR_INVALIDDATA;
|
||||
ret = av_add_index_entry(s->streams[0], pos, st->duration, 0, 0, AVINDEX_KEYFRAME);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
pos += caf->bytes_per_packet ? caf->bytes_per_packet : ff_mp4_read_descr_len(pb);
|
||||
st->duration += caf->frames_per_packet ? caf->frames_per_packet : ff_mp4_read_descr_len(pb);
|
||||
}
|
||||
}
|
||||
|
||||
if (avio_tell(pb) - ccount > size) {
|
||||
@@ -337,7 +342,7 @@ found_data:
|
||||
if (caf->bytes_per_packet > 0 && caf->frames_per_packet > 0) {
|
||||
if (caf->data_size > 0)
|
||||
st->nb_frames = (caf->data_size / caf->bytes_per_packet) * caf->frames_per_packet;
|
||||
} else if (st->internal->nb_index_entries && st->duration > 0) {
|
||||
} else if (st->nb_index_entries && st->duration > 0) {
|
||||
if (st->codecpar->sample_rate && caf->data_size / st->duration > INT64_MAX / st->codecpar->sample_rate / 8) {
|
||||
av_log(s, AV_LOG_ERROR, "Overflow during bit rate calculation %d * 8 * %"PRId64"\n",
|
||||
st->codecpar->sample_rate, caf->data_size / st->duration);
|
||||
@@ -390,13 +395,13 @@ static int read_packet(AVFormatContext *s, AVPacket *pkt)
|
||||
pkt_size = (CAF_MAX_PKT_SIZE / pkt_size) * pkt_size;
|
||||
pkt_size = FFMIN(pkt_size, left);
|
||||
pkt_frames = pkt_size / caf->bytes_per_packet;
|
||||
} else if (st->internal->nb_index_entries) {
|
||||
if (caf->packet_cnt < st->internal->nb_index_entries - 1) {
|
||||
pkt_size = st->internal->index_entries[caf->packet_cnt + 1].pos - st->internal->index_entries[caf->packet_cnt].pos;
|
||||
pkt_frames = st->internal->index_entries[caf->packet_cnt + 1].timestamp - st->internal->index_entries[caf->packet_cnt].timestamp;
|
||||
} else if (caf->packet_cnt == st->internal->nb_index_entries - 1) {
|
||||
pkt_size = caf->num_bytes - st->internal->index_entries[caf->packet_cnt].pos;
|
||||
pkt_frames = st->duration - st->internal->index_entries[caf->packet_cnt].timestamp;
|
||||
} else if (st->nb_index_entries) {
|
||||
if (caf->packet_cnt < st->nb_index_entries - 1) {
|
||||
pkt_size = st->index_entries[caf->packet_cnt + 1].pos - st->index_entries[caf->packet_cnt].pos;
|
||||
pkt_frames = st->index_entries[caf->packet_cnt + 1].timestamp - st->index_entries[caf->packet_cnt].timestamp;
|
||||
} else if (caf->packet_cnt == st->nb_index_entries - 1) {
|
||||
pkt_size = caf->num_bytes - st->index_entries[caf->packet_cnt].pos;
|
||||
pkt_frames = st->duration - st->index_entries[caf->packet_cnt].timestamp;
|
||||
} else {
|
||||
return AVERROR(EIO);
|
||||
}
|
||||
@@ -435,10 +440,10 @@ static int read_seek(AVFormatContext *s, int stream_index,
|
||||
pos = FFMIN(pos, caf->data_size);
|
||||
packet_cnt = pos / caf->bytes_per_packet;
|
||||
frame_cnt = caf->frames_per_packet * packet_cnt;
|
||||
} else if (st->internal->nb_index_entries) {
|
||||
} else if (st->nb_index_entries) {
|
||||
packet_cnt = av_index_search_timestamp(st, timestamp, flags);
|
||||
frame_cnt = st->internal->index_entries[packet_cnt].timestamp;
|
||||
pos = st->internal->index_entries[packet_cnt].pos;
|
||||
frame_cnt = st->index_entries[packet_cnt].timestamp;
|
||||
pos = st->index_entries[packet_cnt].pos;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -288,10 +288,10 @@ static int cine_read_packet(AVFormatContext *avctx, AVPacket *pkt)
|
||||
AVIOContext *pb = avctx->pb;
|
||||
int n, size, ret;
|
||||
|
||||
if (cine->pts >= st->internal->nb_index_entries)
|
||||
if (cine->pts >= st->nb_index_entries)
|
||||
return AVERROR_EOF;
|
||||
|
||||
avio_seek(pb, st->internal->index_entries[cine->pts].pos, SEEK_SET);
|
||||
avio_seek(pb, st->index_entries[cine->pts].pos, SEEK_SET);
|
||||
n = avio_rl32(pb);
|
||||
if (n < 8)
|
||||
return AVERROR_INVALIDDATA;
|
||||
|
||||
+2
-2
@@ -434,10 +434,10 @@ static int dhav_read_seek(AVFormatContext *s, int stream_index,
|
||||
|
||||
if (index < 0)
|
||||
return -1;
|
||||
if (avio_seek(s->pb, st->internal->index_entries[index].pos, SEEK_SET) < 0)
|
||||
if (avio_seek(s->pb, st->index_entries[index].pos, SEEK_SET) < 0)
|
||||
return -1;
|
||||
|
||||
pts = st->internal->index_entries[index].timestamp;
|
||||
pts = st->index_entries[index].timestamp;
|
||||
|
||||
for (int n = 0; n < s->nb_streams; n++) {
|
||||
AVStream *st = s->streams[n];
|
||||
|
||||
+17
-20
@@ -219,7 +219,6 @@ static int dss_sp_read_packet(AVFormatContext *s, AVPacket *pkt)
|
||||
} else
|
||||
read_size = DSS_FRAME_SIZE;
|
||||
|
||||
ctx->counter -= read_size;
|
||||
ctx->packet_size = DSS_FRAME_SIZE - 1;
|
||||
|
||||
ret = av_new_packet(pkt, DSS_FRAME_SIZE);
|
||||
@@ -231,17 +230,16 @@ static int dss_sp_read_packet(AVFormatContext *s, AVPacket *pkt)
|
||||
pkt->stream_index = 0;
|
||||
s->bit_rate = 8LL * ctx->packet_size * st->codecpar->sample_rate * 512 / (506 * pkt->duration);
|
||||
|
||||
if (ctx->counter < 0) {
|
||||
int size2 = ctx->counter + read_size;
|
||||
|
||||
ret = avio_read(s->pb, ctx->dss_sp_buf + offset + buff_offset,
|
||||
size2 - offset);
|
||||
if (ret < size2 - offset)
|
||||
if (ctx->counter < read_size) {
|
||||
ret = avio_read(s->pb, ctx->dss_sp_buf + buff_offset,
|
||||
ctx->counter);
|
||||
if (ret < ctx->counter)
|
||||
goto error_eof;
|
||||
|
||||
offset = ctx->counter;
|
||||
dss_skip_audio_header(s, pkt);
|
||||
offset = size2;
|
||||
}
|
||||
ctx->counter -= read_size;
|
||||
|
||||
ret = avio_read(s->pb, ctx->dss_sp_buf + offset + buff_offset,
|
||||
read_size - offset);
|
||||
@@ -278,7 +276,7 @@ static int dss_723_1_read_packet(AVFormatContext *s, AVPacket *pkt)
|
||||
size = frame_size[byte & 3];
|
||||
|
||||
ctx->packet_size = size;
|
||||
ctx->counter -= size;
|
||||
ctx->counter--;
|
||||
|
||||
ret = av_new_packet(pkt, size);
|
||||
if (ret < 0)
|
||||
@@ -288,27 +286,26 @@ static int dss_723_1_read_packet(AVFormatContext *s, AVPacket *pkt)
|
||||
pkt->data[0] = byte;
|
||||
offset = 1;
|
||||
pkt->duration = 240;
|
||||
s->bit_rate = 8LL * size * st->codecpar->sample_rate * 512 / (506 * pkt->duration);
|
||||
s->bit_rate = 8LL * size-- * st->codecpar->sample_rate * 512 / (506 * pkt->duration);
|
||||
|
||||
pkt->stream_index = 0;
|
||||
|
||||
if (ctx->counter < 0) {
|
||||
int size2 = ctx->counter + size;
|
||||
|
||||
if (ctx->counter < size) {
|
||||
ret = avio_read(s->pb, pkt->data + offset,
|
||||
size2 - offset);
|
||||
if (ret < size2 - offset) {
|
||||
ctx->counter);
|
||||
if (ret < ctx->counter)
|
||||
return ret < 0 ? ret : AVERROR_EOF;
|
||||
}
|
||||
|
||||
offset += ctx->counter;
|
||||
size -= ctx->counter;
|
||||
ctx->counter = 0;
|
||||
dss_skip_audio_header(s, pkt);
|
||||
offset = size2;
|
||||
}
|
||||
ctx->counter -= size;
|
||||
|
||||
ret = avio_read(s->pb, pkt->data + offset, size - offset);
|
||||
if (ret < size - offset) {
|
||||
ret = avio_read(s->pb, pkt->data + offset, size);
|
||||
if (ret < size)
|
||||
return ret < 0 ? ret : AVERROR_EOF;
|
||||
}
|
||||
|
||||
return pkt->size;
|
||||
}
|
||||
|
||||
@@ -40,8 +40,8 @@ static void reset_index_position(int64_t metadata_head_size, AVStream *st)
|
||||
{
|
||||
/* the real seek index offset should be the size of metadata blocks with the offset in the frame blocks */
|
||||
int i;
|
||||
for(i=0; i<st->internal->nb_index_entries; i++) {
|
||||
st->internal->index_entries[i].pos += metadata_head_size;
|
||||
for(i=0; i<st->nb_index_entries; i++) {
|
||||
st->index_entries[i].pos += metadata_head_size;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -318,10 +318,10 @@ static int flac_seek(AVFormatContext *s, int stream_index, int64_t timestamp, in
|
||||
}
|
||||
|
||||
index = av_index_search_timestamp(s->streams[0], timestamp, flags);
|
||||
if(index<0 || index >= s->streams[0]->internal->nb_index_entries)
|
||||
if(index<0 || index >= s->streams[0]->nb_index_entries)
|
||||
return -1;
|
||||
|
||||
e = s->streams[0]->internal->index_entries[index];
|
||||
e = s->streams[0]->index_entries[index];
|
||||
pos = avio_seek(s->pb, e.pos, SEEK_SET);
|
||||
if (pos >= 0) {
|
||||
return 0;
|
||||
|
||||
+3
-3
@@ -268,7 +268,7 @@ static int flic_read_seek(AVFormatContext *s, int stream_index,
|
||||
int64_t pos, ts;
|
||||
int index;
|
||||
|
||||
if (!st->internal->index_entries || stream_index != flic->video_stream_index)
|
||||
if (!st->index_entries || stream_index != flic->video_stream_index)
|
||||
return -1;
|
||||
|
||||
index = av_index_search_timestamp(st, pts, flags);
|
||||
@@ -278,8 +278,8 @@ static int flic_read_seek(AVFormatContext *s, int stream_index,
|
||||
if (index < 0)
|
||||
return -1;
|
||||
|
||||
pos = st->internal->index_entries[index].pos;
|
||||
ts = st->internal->index_entries[index].timestamp;
|
||||
pos = st->index_entries[index].pos;
|
||||
ts = st->index_entries[index].timestamp;
|
||||
flic->frame_number = ts;
|
||||
avio_seek(s->pb, pos, SEEK_SET);
|
||||
return 0;
|
||||
|
||||
@@ -142,7 +142,7 @@ static void add_keyframes_index(AVFormatContext *s)
|
||||
av_assert0(flv->last_keyframe_stream_index <= s->nb_streams);
|
||||
stream = s->streams[flv->last_keyframe_stream_index];
|
||||
|
||||
if (stream->internal->nb_index_entries == 0) {
|
||||
if (stream->nb_index_entries == 0) {
|
||||
for (i = 0; i < flv->keyframe_count; i++) {
|
||||
av_log(s, AV_LOG_TRACE, "keyframe filepositions = %"PRId64" times = %"PRId64"\n",
|
||||
flv->keyframe_filepositions[i], flv->keyframe_times[i] * 1000);
|
||||
@@ -844,10 +844,10 @@ static void clear_index_entries(AVFormatContext *s, int64_t pos)
|
||||
AVStream *st = s->streams[i];
|
||||
/* Remove all index entries that point to >= pos */
|
||||
out = 0;
|
||||
for (j = 0; j < st->internal->nb_index_entries; j++)
|
||||
if (st->internal->index_entries[j].pos < pos)
|
||||
st->internal->index_entries[out++] = st->internal->index_entries[j];
|
||||
st->internal->nb_index_entries = out;
|
||||
for (j = 0; j < st->nb_index_entries; j++)
|
||||
if (st->index_entries[j].pos < pos)
|
||||
st->index_entries[out++] = st->index_entries[j];
|
||||
st->nb_index_entries = out;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -875,6 +875,8 @@ static int amf_skip_tag(AVIOContext *pb, AMFDataType type, int depth)
|
||||
parse_name = 0;
|
||||
case AMF_DATA_TYPE_MIXEDARRAY:
|
||||
nb = avio_rb32(pb);
|
||||
if (nb < 0)
|
||||
return AVERROR_INVALIDDATA;
|
||||
case AMF_DATA_TYPE_OBJECT:
|
||||
while(!pb->eof_reached && (nb-- > 0 || type != AMF_DATA_TYPE_ARRAY)) {
|
||||
if (parse_name) {
|
||||
|
||||
+3
-3
@@ -575,9 +575,9 @@ static int gxf_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int
|
||||
AVSEEK_FLAG_ANY | AVSEEK_FLAG_BACKWARD);
|
||||
if (idx < 0)
|
||||
return -1;
|
||||
pos = st->internal->index_entries[idx].pos;
|
||||
if (idx < st->internal->nb_index_entries - 2)
|
||||
maxlen = st->internal->index_entries[idx + 2].pos - pos;
|
||||
pos = st->index_entries[idx].pos;
|
||||
if (idx < st->nb_index_entries - 2)
|
||||
maxlen = st->index_entries[idx + 2].pos - pos;
|
||||
maxlen = FFMAX(maxlen, 200 * 1024);
|
||||
res = avio_seek(s->pb, pos, SEEK_SET);
|
||||
if (res < 0)
|
||||
|
||||
+4
-4
@@ -195,15 +195,15 @@ static int ifv_read_packet(AVFormatContext *s, AVPacket *pkt)
|
||||
|
||||
if (ifv->next_video_index < ifv->total_vframes) {
|
||||
st = s->streams[ifv->video_stream_index];
|
||||
if (ifv->next_video_index < st->internal->nb_index_entries)
|
||||
e_next = ev = &st->internal->index_entries[ifv->next_video_index];
|
||||
if (ifv->next_video_index < st->nb_index_entries)
|
||||
e_next = ev = &st->index_entries[ifv->next_video_index];
|
||||
}
|
||||
|
||||
if (ifv->is_audio_present &&
|
||||
ifv->next_audio_index < ifv->total_aframes) {
|
||||
st = s->streams[ifv->audio_stream_index];
|
||||
if (ifv->next_audio_index < st->internal->nb_index_entries) {
|
||||
ea = &st->internal->index_entries[ifv->next_audio_index];
|
||||
if (ifv->next_audio_index < st->nb_index_entries) {
|
||||
ea = &st->index_entries[ifv->next_audio_index];
|
||||
if (!ev || ea->timestamp < ev->timestamp)
|
||||
e_next = ea;
|
||||
}
|
||||
|
||||
@@ -590,7 +590,7 @@ static int img_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp
|
||||
int index = av_index_search_timestamp(st, timestamp, flags);
|
||||
if(index < 0)
|
||||
return -1;
|
||||
s1->img_number = st->internal->index_entries[index].pos;
|
||||
s1->img_number = st->index_entries[index].pos;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -113,6 +113,8 @@ retry:
|
||||
imx->first_video_packet_pos = pos;
|
||||
break;
|
||||
case 0xAA98:
|
||||
if (chunk_size > 256 * 3)
|
||||
return AVERROR_INVALIDDATA;
|
||||
for (int i = 0; i < chunk_size / 3; i++) {
|
||||
unsigned r = avio_r8(pb) << 18;
|
||||
unsigned g = avio_r8(pb) << 10;
|
||||
|
||||
@@ -236,11 +236,6 @@ struct AVStreamInternal {
|
||||
|
||||
} *info;
|
||||
|
||||
AVIndexEntry *index_entries; /**< Only used if the format does not
|
||||
support seeking natively. */
|
||||
int nb_index_entries;
|
||||
unsigned int index_entries_allocated_size;
|
||||
|
||||
int64_t interleaver_chunk_size;
|
||||
int64_t interleaver_chunk_duration;
|
||||
|
||||
|
||||
@@ -125,8 +125,8 @@ static const char *read_ts(JACOsubContext *jacosub, const char *buf,
|
||||
return NULL;
|
||||
|
||||
shift_and_ret:
|
||||
ts_start64 = (ts_start + jacosub->shift) * 100LL / jacosub->timeres;
|
||||
ts_end64 = (ts_end + jacosub->shift) * 100LL / jacosub->timeres;
|
||||
ts_start64 = (ts_start + (int64_t)jacosub->shift) * 100LL / jacosub->timeres;
|
||||
ts_end64 = (ts_end + (int64_t)jacosub->shift) * 100LL / jacosub->timeres;
|
||||
*start = ts_start64;
|
||||
*duration = ts_end64 - ts_start64;
|
||||
return buf + len;
|
||||
@@ -199,6 +199,7 @@ static int jacosub_read_header(AVFormatContext *s)
|
||||
|
||||
sub = ff_subtitles_queue_insert(&jacosub->q, line, len, merge_line);
|
||||
if (!sub) {
|
||||
av_bprint_finalize(&header, NULL);
|
||||
ret = AVERROR(ENOMEM);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
+14
-14
@@ -92,7 +92,7 @@ static int read_header(AVFormatContext *s)
|
||||
vst->codecpar->height = avio_rl16(pb);
|
||||
vst->duration =
|
||||
vst->nb_frames =
|
||||
ast->internal->nb_index_entries = avio_rl16(pb);
|
||||
ast->nb_index_entries = avio_rl16(pb);
|
||||
avpriv_set_pts_info(vst, 64, avio_rl16(pb), 1000);
|
||||
|
||||
avio_skip(pb, 4);
|
||||
@@ -107,19 +107,19 @@ static int read_header(AVFormatContext *s)
|
||||
|
||||
avio_skip(pb, 10);
|
||||
|
||||
ast->internal->index_entries = av_malloc(ast->internal->nb_index_entries *
|
||||
sizeof(*ast->internal->index_entries));
|
||||
if (!ast->internal->index_entries)
|
||||
ast->index_entries = av_malloc(ast->nb_index_entries *
|
||||
sizeof(*ast->index_entries));
|
||||
if (!ast->index_entries)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
jv->frames = av_malloc(ast->internal->nb_index_entries * sizeof(JVFrame));
|
||||
jv->frames = av_malloc(ast->nb_index_entries * sizeof(JVFrame));
|
||||
if (!jv->frames) {
|
||||
av_freep(&ast->internal->index_entries);
|
||||
av_freep(&ast->index_entries);
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
offset = 0x68 + ast->internal->nb_index_entries * 16;
|
||||
for (i = 0; i < ast->internal->nb_index_entries; i++) {
|
||||
AVIndexEntry *e = ast->internal->index_entries + i;
|
||||
offset = 0x68 + ast->nb_index_entries * 16;
|
||||
for (i = 0; i < ast->nb_index_entries; i++) {
|
||||
AVIndexEntry *e = ast->index_entries + i;
|
||||
JVFrame *jvf = jv->frames + i;
|
||||
|
||||
/* total frame size including audio, video, palette data and padding */
|
||||
@@ -139,7 +139,7 @@ static int read_header(AVFormatContext *s)
|
||||
if (s->error_recognition & AV_EF_EXPLODE) {
|
||||
read_close(s);
|
||||
av_freep(&jv->frames);
|
||||
av_freep(&ast->internal->index_entries);
|
||||
av_freep(&ast->index_entries);
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
jvf->audio_size =
|
||||
@@ -170,8 +170,8 @@ static int read_packet(AVFormatContext *s, AVPacket *pkt)
|
||||
AVStream *ast = s->streams[0];
|
||||
int ret;
|
||||
|
||||
while (!avio_feof(s->pb) && jv->pts < ast->internal->nb_index_entries) {
|
||||
const AVIndexEntry *e = ast->internal->index_entries + jv->pts;
|
||||
while (!avio_feof(s->pb) && jv->pts < ast->nb_index_entries) {
|
||||
const AVIndexEntry *e = ast->index_entries + jv->pts;
|
||||
const JVFrame *jvf = jv->frames + jv->pts;
|
||||
|
||||
switch (jv->state) {
|
||||
@@ -244,9 +244,9 @@ static int read_seek(AVFormatContext *s, int stream_index,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (i < 0 || i >= ast->internal->nb_index_entries)
|
||||
if (i < 0 || i >= ast->nb_index_entries)
|
||||
return 0;
|
||||
if (avio_seek(s->pb, ast->internal->index_entries[i].pos, SEEK_SET) < 0)
|
||||
if (avio_seek(s->pb, ast->index_entries[i].pos, SEEK_SET) < 0)
|
||||
return -1;
|
||||
|
||||
jv->state = JV_AUDIO;
|
||||
|
||||
+11
-1
@@ -110,12 +110,22 @@ static int kvag_read_packet(AVFormatContext *s, AVPacket *pkt)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kvag_seek(AVFormatContext *s, int stream_index,
|
||||
int64_t pts, int flags)
|
||||
{
|
||||
if (pts != 0)
|
||||
return AVERROR(EINVAL);
|
||||
|
||||
return avio_seek(s->pb, KVAG_HEADER_SIZE, SEEK_SET);
|
||||
}
|
||||
|
||||
AVInputFormat ff_kvag_demuxer = {
|
||||
.name = "kvag",
|
||||
.long_name = NULL_IF_CONFIG_SMALL("Simon & Schuster Interactive VAG"),
|
||||
.read_probe = kvag_probe,
|
||||
.read_header = kvag_read_header,
|
||||
.read_packet = kvag_read_packet
|
||||
.read_packet = kvag_read_packet,
|
||||
.read_seek = kvag_seek,
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
+29
-19
@@ -31,7 +31,6 @@
|
||||
typedef struct GMEContext {
|
||||
const AVClass *class;
|
||||
Music_Emu *music_emu;
|
||||
gme_info_t *info; ///< selected track
|
||||
|
||||
/* options */
|
||||
int track_index;
|
||||
@@ -55,12 +54,16 @@ static void add_meta(AVFormatContext *s, const char *name, const char *value)
|
||||
av_dict_set(&s->metadata, name, value, 0);
|
||||
}
|
||||
|
||||
static int load_metadata(AVFormatContext *s)
|
||||
static int load_metadata(AVFormatContext *s, int64_t *duration)
|
||||
{
|
||||
GMEContext *gme = s->priv_data;
|
||||
gme_info_t *info = gme->info;
|
||||
gme_info_t *info = NULL;
|
||||
char buf[30];
|
||||
|
||||
if (gme_track_info(gme->music_emu, &info, gme->track_index))
|
||||
return AVERROR_STREAM_NOT_FOUND;
|
||||
|
||||
*duration = info->length;
|
||||
add_meta(s, "system", info->system);
|
||||
add_meta(s, "game", info->game);
|
||||
add_meta(s, "song", info->song);
|
||||
@@ -71,20 +74,30 @@ static int load_metadata(AVFormatContext *s)
|
||||
|
||||
snprintf(buf, sizeof(buf), "%d", (int)gme_track_count(gme->music_emu));
|
||||
add_meta(s, "tracks", buf);
|
||||
gme_free_info(info);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define AUDIO_PKT_SIZE 512
|
||||
|
||||
static int read_close_gme(AVFormatContext *s)
|
||||
{
|
||||
GMEContext *gme = s->priv_data;
|
||||
gme_delete(gme->music_emu);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int read_header_gme(AVFormatContext *s)
|
||||
{
|
||||
AVStream *st;
|
||||
AVIOContext *pb = s->pb;
|
||||
GMEContext *gme = s->priv_data;
|
||||
int64_t sz = avio_size(pb);
|
||||
int64_t duration;
|
||||
char *buf;
|
||||
char dummy;
|
||||
int ret;
|
||||
|
||||
if (sz < 0) {
|
||||
av_log(s, AV_LOG_WARNING, "Could not determine file size\n");
|
||||
@@ -103,6 +116,7 @@ static int read_header_gme(AVFormatContext *s)
|
||||
av_log(s, AV_LOG_ERROR, "File size is larger than max_size option "
|
||||
"value %"PRIi64", consider increasing the max_size option\n",
|
||||
gme->max_size);
|
||||
av_freep(&buf);
|
||||
return AVERROR_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
@@ -112,20 +126,24 @@ static int read_header_gme(AVFormatContext *s)
|
||||
}
|
||||
av_freep(&buf);
|
||||
|
||||
if (gme_track_info(gme->music_emu, &gme->info, gme->track_index))
|
||||
return AVERROR_STREAM_NOT_FOUND;
|
||||
|
||||
if (gme_start_track(gme->music_emu, gme->track_index))
|
||||
ret = load_metadata(s, &duration);
|
||||
if (ret < 0) {
|
||||
read_close_gme(s);
|
||||
return ret;
|
||||
}
|
||||
if (gme_start_track(gme->music_emu, gme->track_index)) {
|
||||
read_close_gme(s);
|
||||
return AVERROR_UNKNOWN;
|
||||
|
||||
load_metadata(s);
|
||||
}
|
||||
|
||||
st = avformat_new_stream(s, NULL);
|
||||
if (!st)
|
||||
if (!st) {
|
||||
read_close_gme(s);
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
avpriv_set_pts_info(st, 64, 1, 1000);
|
||||
if (st->duration > 0)
|
||||
st->duration = gme->info->length;
|
||||
st->duration = duration;
|
||||
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
|
||||
st->codecpar->codec_id = AV_NE(AV_CODEC_ID_PCM_S16BE, AV_CODEC_ID_PCM_S16LE);
|
||||
st->codecpar->channels = 2;
|
||||
@@ -153,14 +171,6 @@ static int read_packet_gme(AVFormatContext *s, AVPacket *pkt)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int read_close_gme(AVFormatContext *s)
|
||||
{
|
||||
GMEContext *gme = s->priv_data;
|
||||
gme_free_info(gme->info);
|
||||
gme_delete(gme->music_emu);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int read_seek_gme(AVFormatContext *s, int stream_idx, int64_t ts, int flags)
|
||||
{
|
||||
GMEContext *gme = s->priv_data;
|
||||
|
||||
+24
-13
@@ -99,6 +99,14 @@ static const AVOption options[] = {
|
||||
{NULL},
|
||||
};
|
||||
|
||||
static int modplug_read_close(AVFormatContext *s)
|
||||
{
|
||||
ModPlugContext *modplug = s->priv_data;
|
||||
ModPlug_Unload(modplug->f);
|
||||
av_freep(&modplug->buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define SET_OPT_IF_REQUESTED(libopt, opt, flag) do { \
|
||||
if (modplug->opt) { \
|
||||
settings.libopt = modplug->opt; \
|
||||
@@ -168,6 +176,7 @@ static int modplug_read_header(AVFormatContext *s)
|
||||
ModPlug_Settings settings;
|
||||
ModPlugContext *modplug = s->priv_data;
|
||||
int64_t sz = avio_size(pb);
|
||||
int ret;
|
||||
|
||||
if (sz < 0) {
|
||||
av_log(s, AV_LOG_WARNING, "Could not determine file size\n");
|
||||
@@ -221,8 +230,10 @@ static int modplug_read_header(AVFormatContext *s)
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
st = avformat_new_stream(s, NULL);
|
||||
if (!st)
|
||||
return AVERROR(ENOMEM);
|
||||
if (!st) {
|
||||
ret = AVERROR(ENOMEM);
|
||||
goto fail;
|
||||
}
|
||||
avpriv_set_pts_info(st, 64, 1, 1000);
|
||||
st->duration = ModPlug_GetLength(modplug->f);
|
||||
st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
|
||||
@@ -235,8 +246,10 @@ static int modplug_read_header(AVFormatContext *s)
|
||||
|
||||
if (modplug->video_stream) {
|
||||
AVStream *vst = avformat_new_stream(s, NULL);
|
||||
if (!vst)
|
||||
return AVERROR(ENOMEM);
|
||||
if (!vst) {
|
||||
ret = AVERROR(ENOMEM);
|
||||
goto fail;
|
||||
}
|
||||
avpriv_set_pts_info(vst, 64, 1, 1000);
|
||||
vst->duration = st->duration;
|
||||
vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
|
||||
@@ -247,7 +260,13 @@ static int modplug_read_header(AVFormatContext *s)
|
||||
modplug->fsize = modplug->linesize * modplug->h;
|
||||
}
|
||||
|
||||
return modplug_load_metadata(s);
|
||||
ret = modplug_load_metadata(s);
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
return 0;
|
||||
fail:
|
||||
modplug_read_close(s);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void write_text(uint8_t *dst, const char *s, int linesize, int x, int y)
|
||||
@@ -332,14 +351,6 @@ static int modplug_read_packet(AVFormatContext *s, AVPacket *pkt)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int modplug_read_close(AVFormatContext *s)
|
||||
{
|
||||
ModPlugContext *modplug = s->priv_data;
|
||||
ModPlug_Unload(modplug->f);
|
||||
av_freep(&modplug->buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int modplug_read_seek(AVFormatContext *s, int stream_idx, int64_t ts, int flags)
|
||||
{
|
||||
ModPlugContext *modplug = s->priv_data;
|
||||
|
||||
+20
-20
@@ -3845,13 +3845,13 @@ static int matroska_read_seek(AVFormatContext *s, int stream_index,
|
||||
matroska_parse_cues(matroska);
|
||||
}
|
||||
|
||||
if (!st->internal->nb_index_entries)
|
||||
if (!st->nb_index_entries)
|
||||
goto err;
|
||||
timestamp = FFMAX(timestamp, st->internal->index_entries[0].timestamp);
|
||||
timestamp = FFMAX(timestamp, st->index_entries[0].timestamp);
|
||||
|
||||
if ((index = av_index_search_timestamp(st, timestamp, flags)) < 0 || index == st->internal->nb_index_entries - 1) {
|
||||
matroska_reset_status(matroska, 0, st->internal->index_entries[st->internal->nb_index_entries - 1].pos);
|
||||
while ((index = av_index_search_timestamp(st, timestamp, flags)) < 0 || index == st->internal->nb_index_entries - 1) {
|
||||
if ((index = av_index_search_timestamp(st, timestamp, flags)) < 0 || index == st->nb_index_entries - 1) {
|
||||
matroska_reset_status(matroska, 0, st->index_entries[st->nb_index_entries - 1].pos);
|
||||
while ((index = av_index_search_timestamp(st, timestamp, flags)) < 0 || index == st->nb_index_entries - 1) {
|
||||
matroska_clear_queue(matroska);
|
||||
if (matroska_parse_cluster(matroska) < 0)
|
||||
break;
|
||||
@@ -3859,7 +3859,7 @@ static int matroska_read_seek(AVFormatContext *s, int stream_index,
|
||||
}
|
||||
|
||||
matroska_clear_queue(matroska);
|
||||
if (index < 0 || (matroska->cues_parsing_deferred < 0 && index == st->internal->nb_index_entries - 1))
|
||||
if (index < 0 || (matroska->cues_parsing_deferred < 0 && index == st->nb_index_entries - 1))
|
||||
goto err;
|
||||
|
||||
tracks = matroska->tracks.elem;
|
||||
@@ -3871,17 +3871,17 @@ static int matroska_read_seek(AVFormatContext *s, int stream_index,
|
||||
}
|
||||
|
||||
/* We seek to a level 1 element, so set the appropriate status. */
|
||||
matroska_reset_status(matroska, 0, st->internal->index_entries[index].pos);
|
||||
matroska_reset_status(matroska, 0, st->index_entries[index].pos);
|
||||
if (flags & AVSEEK_FLAG_ANY) {
|
||||
st->internal->skip_to_keyframe = 0;
|
||||
matroska->skip_to_timecode = timestamp;
|
||||
} else {
|
||||
st->internal->skip_to_keyframe = 1;
|
||||
matroska->skip_to_timecode = st->internal->index_entries[index].timestamp;
|
||||
matroska->skip_to_timecode = st->index_entries[index].timestamp;
|
||||
}
|
||||
matroska->skip_to_keyframe = 1;
|
||||
matroska->done = 0;
|
||||
ff_update_cur_dts(s, st, st->internal->index_entries[index].timestamp);
|
||||
ff_update_cur_dts(s, st, st->index_entries[index].timestamp);
|
||||
return 0;
|
||||
err:
|
||||
// slightly hackish but allows proper fallback to
|
||||
@@ -3927,8 +3927,8 @@ static CueDesc get_cue_desc(AVFormatContext *s, int64_t ts, int64_t cues_start)
|
||||
MatroskaDemuxContext *matroska = s->priv_data;
|
||||
CueDesc cue_desc;
|
||||
int i;
|
||||
int nb_index_entries = s->streams[0]->internal->nb_index_entries;
|
||||
AVIndexEntry *index_entries = s->streams[0]->internal->index_entries;
|
||||
int nb_index_entries = s->streams[0]->nb_index_entries;
|
||||
AVIndexEntry *index_entries = s->streams[0]->index_entries;
|
||||
if (ts >= matroska->duration * matroska->time_scale) return (CueDesc) {-1, -1, -1, -1};
|
||||
for (i = 1; i < nb_index_entries; i++) {
|
||||
if (index_entries[i - 1].timestamp * matroska->time_scale <= ts &&
|
||||
@@ -3958,11 +3958,11 @@ static int webm_clusters_start_with_keyframe(AVFormatContext *s)
|
||||
uint32_t id = matroska->current_id;
|
||||
int64_t cluster_pos, before_pos;
|
||||
int index, rv = 1;
|
||||
if (s->streams[0]->internal->nb_index_entries <= 0) return 0;
|
||||
if (s->streams[0]->nb_index_entries <= 0) return 0;
|
||||
// seek to the first cluster using cues.
|
||||
index = av_index_search_timestamp(s->streams[0], 0, 0);
|
||||
if (index < 0) return 0;
|
||||
cluster_pos = s->streams[0]->internal->index_entries[index].pos;
|
||||
cluster_pos = s->streams[0]->index_entries[index].pos;
|
||||
before_pos = avio_tell(s->pb);
|
||||
while (1) {
|
||||
uint64_t cluster_id, cluster_length;
|
||||
@@ -4086,9 +4086,9 @@ static int64_t webm_dash_manifest_compute_bandwidth(AVFormatContext *s, int64_t
|
||||
double bandwidth = 0.0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < st->internal->nb_index_entries; i++) {
|
||||
for (i = 0; i < st->nb_index_entries; i++) {
|
||||
int64_t prebuffer_ns = 1000000000;
|
||||
int64_t time_ns = st->internal->index_entries[i].timestamp * matroska->time_scale;
|
||||
int64_t time_ns = st->index_entries[i].timestamp * matroska->time_scale;
|
||||
double nano_seconds_per_second = 1000000000.0;
|
||||
int64_t prebuffered_ns = time_ns + prebuffer_ns;
|
||||
double prebuffer_bytes = 0.0;
|
||||
@@ -4226,14 +4226,14 @@ static int webm_dash_manifest_cues(AVFormatContext *s, int64_t init_range)
|
||||
|
||||
// store cue point timestamps as a comma separated list for checking subsegment alignment in
|
||||
// the muxer. assumes that each timestamp cannot be more than 20 characters long.
|
||||
buf = av_malloc_array(s->streams[0]->internal->nb_index_entries, 20);
|
||||
buf = av_malloc_array(s->streams[0]->nb_index_entries, 20);
|
||||
if (!buf) return -1;
|
||||
strcpy(buf, "");
|
||||
for (i = 0; i < s->streams[0]->internal->nb_index_entries; i++) {
|
||||
for (i = 0; i < s->streams[0]->nb_index_entries; i++) {
|
||||
int ret = snprintf(buf + end, 20,
|
||||
"%" PRId64"%s", s->streams[0]->internal->index_entries[i].timestamp,
|
||||
i != s->streams[0]->internal->nb_index_entries - 1 ? "," : "");
|
||||
if (ret <= 0 || (ret == 20 && i == s->streams[0]->internal->nb_index_entries - 1)) {
|
||||
"%" PRId64"%s", s->streams[0]->index_entries[i].timestamp,
|
||||
i != s->streams[0]->nb_index_entries - 1 ? "," : "");
|
||||
if (ret <= 0 || (ret == 20 && i == s->streams[0]->nb_index_entries - 1)) {
|
||||
av_log(s, AV_LOG_ERROR, "timestamp too long.\n");
|
||||
av_free(buf);
|
||||
return AVERROR_INVALIDDATA;
|
||||
|
||||
+10
-10
@@ -191,12 +191,12 @@ static int scan_file(AVFormatContext *avctx, AVStream *vst, AVStream *ast, int f
|
||||
}
|
||||
} else if (vst && type == MKTAG('V', 'I', 'D', 'F') && size >= 4) {
|
||||
uint64_t pts = avio_rl32(pb);
|
||||
ff_add_index_entry(&vst->internal->index_entries, &vst->internal->nb_index_entries, &vst->internal->index_entries_allocated_size,
|
||||
ff_add_index_entry(&vst->index_entries, &vst->nb_index_entries, &vst->index_entries_allocated_size,
|
||||
avio_tell(pb) - 20, pts, file, 0, AVINDEX_KEYFRAME);
|
||||
size -= 4;
|
||||
} else if (ast && type == MKTAG('A', 'U', 'D', 'F') && size >= 4) {
|
||||
uint64_t pts = avio_rl32(pb);
|
||||
ff_add_index_entry(&ast->internal->index_entries, &ast->internal->nb_index_entries, &ast->internal->index_entries_allocated_size,
|
||||
ff_add_index_entry(&ast->index_entries, &ast->nb_index_entries, &ast->index_entries_allocated_size,
|
||||
avio_tell(pb) - 20, pts, file, 0, AVINDEX_KEYFRAME);
|
||||
size -= 4;
|
||||
} else if (vst && type == MKTAG('W','B','A','L') && size >= 28) {
|
||||
@@ -374,22 +374,22 @@ static int read_header(AVFormatContext *avctx)
|
||||
}
|
||||
|
||||
if (vst)
|
||||
vst->duration = vst->internal->nb_index_entries;
|
||||
vst->duration = vst->nb_index_entries;
|
||||
if (ast)
|
||||
ast->duration = ast->internal->nb_index_entries;
|
||||
ast->duration = ast->nb_index_entries;
|
||||
|
||||
if ((vst && !vst->internal->nb_index_entries) || (ast && !ast->internal->nb_index_entries)) {
|
||||
if ((vst && !vst->nb_index_entries) || (ast && !ast->nb_index_entries)) {
|
||||
av_log(avctx, AV_LOG_ERROR, "no index entries found\n");
|
||||
read_close(avctx);
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
if (vst && ast)
|
||||
avio_seek(pb, FFMIN(vst->internal->index_entries[0].pos, ast->internal->index_entries[0].pos), SEEK_SET);
|
||||
avio_seek(pb, FFMIN(vst->index_entries[0].pos, ast->index_entries[0].pos), SEEK_SET);
|
||||
else if (vst)
|
||||
avio_seek(pb, vst->internal->index_entries[0].pos, SEEK_SET);
|
||||
avio_seek(pb, vst->index_entries[0].pos, SEEK_SET);
|
||||
else if (ast)
|
||||
avio_seek(pb, ast->internal->index_entries[0].pos, SEEK_SET);
|
||||
avio_seek(pb, ast->index_entries[0].pos, SEEK_SET);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -415,12 +415,12 @@ static int read_packet(AVFormatContext *avctx, AVPacket *pkt)
|
||||
return AVERROR(EIO);
|
||||
}
|
||||
|
||||
pb = mlv->pb[st->internal->index_entries[index].size];
|
||||
pb = mlv->pb[st->index_entries[index].size];
|
||||
if (!pb) {
|
||||
ret = FFERROR_REDO;
|
||||
goto next_packet;
|
||||
}
|
||||
avio_seek(pb, st->internal->index_entries[index].pos, SEEK_SET);
|
||||
avio_seek(pb, st->index_entries[index].pos, SEEK_SET);
|
||||
|
||||
avio_skip(pb, 4); // blockType
|
||||
size = avio_rl32(pb);
|
||||
|
||||
+111
-105
@@ -2037,8 +2037,10 @@ static int mov_read_stco(MOVContext *c, AVIOContext *pb, MOVAtom atom)
|
||||
if (!entries)
|
||||
return 0;
|
||||
|
||||
if (sc->chunk_offsets)
|
||||
av_log(c->fc, AV_LOG_WARNING, "Duplicated STCO atom\n");
|
||||
if (sc->chunk_offsets) {
|
||||
av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicated STCO atom\n");
|
||||
return 0;
|
||||
}
|
||||
av_free(sc->chunk_offsets);
|
||||
sc->chunk_count = 0;
|
||||
sc->chunk_offsets = av_malloc_array(entries, sizeof(*sc->chunk_offsets));
|
||||
@@ -2263,7 +2265,7 @@ static void mov_parse_stsd_audio(MOVContext *c, AVIOContext *pb,
|
||||
}
|
||||
|
||||
bits_per_sample = av_get_bits_per_sample(st->codecpar->codec_id);
|
||||
if (bits_per_sample) {
|
||||
if (bits_per_sample && (bits_per_sample >> 3) * (uint64_t)st->codecpar->channels <= INT_MAX) {
|
||||
st->codecpar->bits_per_coded_sample = bits_per_sample;
|
||||
sc->sample_size = (bits_per_sample >> 3) * st->codecpar->channels;
|
||||
}
|
||||
@@ -2671,8 +2673,10 @@ static int mov_read_stsc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
|
||||
|
||||
if (!entries)
|
||||
return 0;
|
||||
if (sc->stsc_data)
|
||||
av_log(c->fc, AV_LOG_WARNING, "Duplicated STSC atom\n");
|
||||
if (sc->stsc_data) {
|
||||
av_log(c->fc, AV_LOG_WARNING, "Ignoring duplicated STSC atom\n");
|
||||
return 0;
|
||||
}
|
||||
av_free(sc->stsc_data);
|
||||
sc->stsc_count = 0;
|
||||
sc->stsc_data = av_malloc_array(entries, sizeof(*sc->stsc_data));
|
||||
@@ -3018,7 +3022,7 @@ static int mov_read_sdtp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
|
||||
av_freep(&sc->sdtp_data);
|
||||
sc->sdtp_count = 0;
|
||||
|
||||
sc->sdtp_data = av_mallocz(entries);
|
||||
sc->sdtp_data = av_malloc(entries);
|
||||
if (!sc->sdtp_data)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
@@ -3210,8 +3214,8 @@ static int find_prev_closest_index(AVStream *st,
|
||||
int64_t* ctts_sample)
|
||||
{
|
||||
MOVStreamContext *msc = st->priv_data;
|
||||
AVIndexEntry *e_keep = st->internal->index_entries;
|
||||
int nb_keep = st->internal->nb_index_entries;
|
||||
AVIndexEntry *e_keep = st->index_entries;
|
||||
int nb_keep = st->nb_index_entries;
|
||||
int64_t i = 0;
|
||||
int64_t index_ctts_count;
|
||||
|
||||
@@ -3224,8 +3228,8 @@ static int find_prev_closest_index(AVStream *st,
|
||||
timestamp_pts -= msc->dts_shift;
|
||||
}
|
||||
|
||||
st->internal->index_entries = e_old;
|
||||
st->internal->nb_index_entries = nb_old;
|
||||
st->index_entries = e_old;
|
||||
st->nb_index_entries = nb_old;
|
||||
*index = av_index_search_timestamp(st, timestamp_pts, flag | AVSEEK_FLAG_BACKWARD);
|
||||
|
||||
// Keep going backwards in the index entries until the timestamp is the same.
|
||||
@@ -3278,14 +3282,14 @@ static int find_prev_closest_index(AVStream *st,
|
||||
}
|
||||
|
||||
/* restore AVStream state*/
|
||||
st->internal->index_entries = e_keep;
|
||||
st->internal->nb_index_entries = nb_keep;
|
||||
st->index_entries = e_keep;
|
||||
st->nb_index_entries = nb_keep;
|
||||
return *index >= 0 ? 0 : -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add index entry with the given values, to the end of st->internal->index_entries.
|
||||
* Returns the new size st->internal->index_entries if successful, else returns -1.
|
||||
* Add index entry with the given values, to the end of st->index_entries.
|
||||
* Returns the new size st->index_entries if successful, else returns -1.
|
||||
*
|
||||
* This function is similar to ff_add_index_entry in libavformat/utils.c
|
||||
* except that here we are always unconditionally adding an index entry to
|
||||
@@ -3299,27 +3303,27 @@ static int64_t add_index_entry(AVStream *st, int64_t pos, int64_t timestamp,
|
||||
{
|
||||
AVIndexEntry *entries, *ie;
|
||||
int64_t index = -1;
|
||||
const size_t min_size_needed = (st->internal->nb_index_entries + 1) * sizeof(AVIndexEntry);
|
||||
const size_t min_size_needed = (st->nb_index_entries + 1) * sizeof(AVIndexEntry);
|
||||
|
||||
// Double the allocation each time, to lower memory fragmentation.
|
||||
// Another difference from ff_add_index_entry function.
|
||||
const size_t requested_size =
|
||||
min_size_needed > st->internal->index_entries_allocated_size ?
|
||||
FFMAX(min_size_needed, 2 * st->internal->index_entries_allocated_size) :
|
||||
min_size_needed > st->index_entries_allocated_size ?
|
||||
FFMAX(min_size_needed, 2 * st->index_entries_allocated_size) :
|
||||
min_size_needed;
|
||||
|
||||
if (st->internal->nb_index_entries + 1U >= UINT_MAX / sizeof(AVIndexEntry))
|
||||
if (st->nb_index_entries + 1U >= UINT_MAX / sizeof(AVIndexEntry))
|
||||
return -1;
|
||||
|
||||
entries = av_fast_realloc(st->internal->index_entries,
|
||||
&st->internal->index_entries_allocated_size,
|
||||
entries = av_fast_realloc(st->index_entries,
|
||||
&st->index_entries_allocated_size,
|
||||
requested_size);
|
||||
if (!entries)
|
||||
return -1;
|
||||
|
||||
st->internal->index_entries= entries;
|
||||
st->index_entries= entries;
|
||||
|
||||
index= st->internal->nb_index_entries++;
|
||||
index= st->nb_index_entries++;
|
||||
ie= &entries[index];
|
||||
|
||||
ie->pos = pos;
|
||||
@@ -3338,10 +3342,10 @@ static void fix_index_entry_timestamps(AVStream* st, int end_index, int64_t end_
|
||||
int64_t* frame_duration_buffer,
|
||||
int frame_duration_buffer_size) {
|
||||
int i = 0;
|
||||
av_assert0(end_index >= 0 && end_index <= st->internal->nb_index_entries);
|
||||
av_assert0(end_index >= 0 && end_index <= st->nb_index_entries);
|
||||
for (i = 0; i < frame_duration_buffer_size; i++) {
|
||||
end_ts -= frame_duration_buffer[frame_duration_buffer_size - 1 - i];
|
||||
st->internal->index_entries[end_index - 1 - i].timestamp = end_ts;
|
||||
st->index_entries[end_index - 1 - i].timestamp = end_ts;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3393,14 +3397,14 @@ static void mov_estimate_video_delay(MOVContext *c, AVStream* st)
|
||||
if (st->codecpar->video_delay <= 0 && msc->ctts_data &&
|
||||
st->codecpar->codec_id == AV_CODEC_ID_H264) {
|
||||
st->codecpar->video_delay = 0;
|
||||
for (ind = 0; ind < st->internal->nb_index_entries && ctts_ind < msc->ctts_count; ++ind) {
|
||||
for (ind = 0; ind < st->nb_index_entries && ctts_ind < msc->ctts_count; ++ind) {
|
||||
// Point j to the last elem of the buffer and insert the current pts there.
|
||||
j = buf_start;
|
||||
buf_start = (buf_start + 1);
|
||||
if (buf_start == MAX_REORDER_DELAY + 1)
|
||||
buf_start = 0;
|
||||
|
||||
pts_buf[j] = st->internal->index_entries[ind].timestamp + msc->ctts_data[ctts_ind].duration;
|
||||
pts_buf[j] = st->index_entries[ind].timestamp + msc->ctts_data[ctts_ind].duration;
|
||||
|
||||
// The timestamps that are already in the sorted buffer, and are greater than the
|
||||
// current pts, are exactly the timestamps that need to be buffered to output PTS
|
||||
@@ -3480,7 +3484,7 @@ static void mov_current_sample_set(MOVStreamContext *sc, int current_sample)
|
||||
}
|
||||
|
||||
/**
|
||||
* Fix st->internal->index_entries, so that it contains only the entries (and the entries
|
||||
* Fix st->index_entries, so that it contains only the entries (and the entries
|
||||
* which are needed to decode them) that fall in the edit list time ranges.
|
||||
* Also fixes the timestamps of the index entries to match the timeline
|
||||
* specified the edit lists.
|
||||
@@ -3488,8 +3492,8 @@ static void mov_current_sample_set(MOVStreamContext *sc, int current_sample)
|
||||
static void mov_fix_index(MOVContext *mov, AVStream *st)
|
||||
{
|
||||
MOVStreamContext *msc = st->priv_data;
|
||||
AVIndexEntry *e_old = st->internal->index_entries;
|
||||
int nb_old = st->internal->nb_index_entries;
|
||||
AVIndexEntry *e_old = st->index_entries;
|
||||
int nb_old = st->nb_index_entries;
|
||||
const AVIndexEntry *e_old_end = e_old + nb_old;
|
||||
const AVIndexEntry *current = NULL;
|
||||
MOVStts *ctts_data_old = msc->ctts_data;
|
||||
@@ -3534,9 +3538,9 @@ static void mov_fix_index(MOVContext *mov, AVStream *st)
|
||||
current_index_range = msc->index_ranges - 1;
|
||||
|
||||
// Clean AVStream from traces of old index
|
||||
st->internal->index_entries = NULL;
|
||||
st->internal->index_entries_allocated_size = 0;
|
||||
st->internal->nb_index_entries = 0;
|
||||
st->index_entries = NULL;
|
||||
st->index_entries_allocated_size = 0;
|
||||
st->nb_index_entries = 0;
|
||||
|
||||
// Clean ctts fields of MOVStreamContext
|
||||
msc->ctts_data = NULL;
|
||||
@@ -3665,7 +3669,7 @@ static void mov_fix_index(MOVContext *mov, AVStream *st)
|
||||
// Make timestamps strictly monotonically increasing for audio, by rewriting timestamps for
|
||||
// discarded packets.
|
||||
if (frame_duration_buffer) {
|
||||
fix_index_entry_timestamps(st, st->internal->nb_index_entries, edit_list_dts_counter,
|
||||
fix_index_entry_timestamps(st, st->nb_index_entries, edit_list_dts_counter,
|
||||
frame_duration_buffer, num_discarded_begin);
|
||||
av_freep(&frame_duration_buffer);
|
||||
}
|
||||
@@ -3704,7 +3708,7 @@ static void mov_fix_index(MOVContext *mov, AVStream *st)
|
||||
// Make timestamps strictly monotonically increasing by rewriting timestamps for
|
||||
// discarded packets.
|
||||
if (frame_duration_buffer) {
|
||||
fix_index_entry_timestamps(st, st->internal->nb_index_entries, edit_list_dts_counter,
|
||||
fix_index_entry_timestamps(st, st->nb_index_entries, edit_list_dts_counter,
|
||||
frame_duration_buffer, num_discarded_begin);
|
||||
av_freep(&frame_duration_buffer);
|
||||
}
|
||||
@@ -3765,8 +3769,8 @@ static void mov_fix_index(MOVContext *mov, AVStream *st)
|
||||
if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
|
||||
if (msc->min_corrected_pts > 0) {
|
||||
av_log(mov->fc, AV_LOG_DEBUG, "Offset DTS by %"PRId64" to make first pts zero.\n", msc->min_corrected_pts);
|
||||
for (i = 0; i < st->internal->nb_index_entries; ++i) {
|
||||
st->internal->index_entries[i].timestamp -= msc->min_corrected_pts;
|
||||
for (i = 0; i < st->nb_index_entries; ++i) {
|
||||
st->index_entries[i].timestamp -= msc->min_corrected_pts;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3859,17 +3863,17 @@ static void mov_build_index(MOVContext *mov, AVStream *st)
|
||||
current_dts -= sc->dts_shift;
|
||||
last_dts = current_dts;
|
||||
|
||||
if (!sc->sample_count || st->internal->nb_index_entries)
|
||||
if (!sc->sample_count || st->nb_index_entries)
|
||||
return;
|
||||
if (sc->sample_count >= UINT_MAX / sizeof(*st->internal->index_entries) - st->internal->nb_index_entries)
|
||||
if (sc->sample_count >= UINT_MAX / sizeof(*st->index_entries) - st->nb_index_entries)
|
||||
return;
|
||||
if (av_reallocp_array(&st->internal->index_entries,
|
||||
st->internal->nb_index_entries + sc->sample_count,
|
||||
sizeof(*st->internal->index_entries)) < 0) {
|
||||
st->internal->nb_index_entries = 0;
|
||||
if (av_reallocp_array(&st->index_entries,
|
||||
st->nb_index_entries + sc->sample_count,
|
||||
sizeof(*st->index_entries)) < 0) {
|
||||
st->nb_index_entries = 0;
|
||||
return;
|
||||
}
|
||||
st->internal->index_entries_allocated_size = (st->internal->nb_index_entries + sc->sample_count) * sizeof(*st->internal->index_entries);
|
||||
st->index_entries_allocated_size = (st->nb_index_entries + sc->sample_count) * sizeof(*st->index_entries);
|
||||
|
||||
if (ctts_data_old) {
|
||||
// Expand ctts entries such that we have a 1-1 mapping with samples
|
||||
@@ -3952,7 +3956,7 @@ static void mov_build_index(MOVContext *mov, AVStream *st)
|
||||
av_log(mov->fc, AV_LOG_ERROR, "Sample size %u is too large\n", sample_size);
|
||||
return;
|
||||
}
|
||||
e = &st->internal->index_entries[st->internal->nb_index_entries++];
|
||||
e = &st->index_entries[st->nb_index_entries++];
|
||||
e->pos = current_offset;
|
||||
e->timestamp = current_dts;
|
||||
e->size = sample_size;
|
||||
@@ -3961,7 +3965,7 @@ static void mov_build_index(MOVContext *mov, AVStream *st)
|
||||
av_log(mov->fc, AV_LOG_TRACE, "AVIndex stream %d, sample %u, offset %"PRIx64", dts %"PRId64", "
|
||||
"size %u, distance %u, keyframe %d\n", st->index, current_sample,
|
||||
current_offset, current_dts, sample_size, distance, keyframe);
|
||||
if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && st->internal->nb_index_entries < 100)
|
||||
if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && st->nb_index_entries < 100)
|
||||
ff_rfps_add_frame(mov->fc, st, current_dts);
|
||||
}
|
||||
|
||||
@@ -4033,15 +4037,15 @@ static void mov_build_index(MOVContext *mov, AVStream *st)
|
||||
}
|
||||
|
||||
av_log(mov->fc, AV_LOG_TRACE, "chunk count %u\n", total);
|
||||
if (total >= UINT_MAX / sizeof(*st->internal->index_entries) - st->internal->nb_index_entries)
|
||||
if (total >= UINT_MAX / sizeof(*st->index_entries) - st->nb_index_entries)
|
||||
return;
|
||||
if (av_reallocp_array(&st->internal->index_entries,
|
||||
st->internal->nb_index_entries + total,
|
||||
sizeof(*st->internal->index_entries)) < 0) {
|
||||
st->internal->nb_index_entries = 0;
|
||||
if (av_reallocp_array(&st->index_entries,
|
||||
st->nb_index_entries + total,
|
||||
sizeof(*st->index_entries)) < 0) {
|
||||
st->nb_index_entries = 0;
|
||||
return;
|
||||
}
|
||||
st->internal->index_entries_allocated_size = (st->internal->nb_index_entries + total) * sizeof(*st->internal->index_entries);
|
||||
st->index_entries_allocated_size = (st->nb_index_entries + total) * sizeof(*st->index_entries);
|
||||
|
||||
// populate index
|
||||
for (i = 0; i < sc->chunk_count; i++) {
|
||||
@@ -4076,7 +4080,7 @@ static void mov_build_index(MOVContext *mov, AVStream *st)
|
||||
}
|
||||
}
|
||||
|
||||
if (st->internal->nb_index_entries >= total) {
|
||||
if (st->nb_index_entries >= total) {
|
||||
av_log(mov->fc, AV_LOG_ERROR, "wrong chunk count %u\n", total);
|
||||
return;
|
||||
}
|
||||
@@ -4084,7 +4088,7 @@ static void mov_build_index(MOVContext *mov, AVStream *st)
|
||||
av_log(mov->fc, AV_LOG_ERROR, "Sample size %u is too large\n", size);
|
||||
return;
|
||||
}
|
||||
e = &st->internal->index_entries[st->internal->nb_index_entries++];
|
||||
e = &st->index_entries[st->nb_index_entries++];
|
||||
e->pos = current_offset;
|
||||
e->timestamp = current_dts;
|
||||
e->size = size;
|
||||
@@ -4107,8 +4111,8 @@ static void mov_build_index(MOVContext *mov, AVStream *st)
|
||||
}
|
||||
|
||||
// Update start time of the stream.
|
||||
if (st->start_time == AV_NOPTS_VALUE && st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && st->internal->nb_index_entries > 0) {
|
||||
st->start_time = st->internal->index_entries[0].timestamp + sc->dts_shift;
|
||||
if (st->start_time == AV_NOPTS_VALUE && st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && st->nb_index_entries > 0) {
|
||||
st->start_time = st->index_entries[0].timestamp + sc->dts_shift;
|
||||
if (sc->ctts_data) {
|
||||
st->start_time += sc->ctts_data[0].duration;
|
||||
}
|
||||
@@ -4806,7 +4810,7 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom)
|
||||
// A valid index_entry means the trun for the fragment was read
|
||||
// and it's samples are in index_entries at the given position.
|
||||
// New index entries will be inserted before the index_entry found.
|
||||
index_entry_pos = st->internal->nb_index_entries;
|
||||
index_entry_pos = st->nb_index_entries;
|
||||
for (i = c->frag_index.current + 1; i < c->frag_index.nb_items; i++) {
|
||||
frag_stream_info = get_frag_stream_info(&c->frag_index, i, frag->track_id);
|
||||
if (frag_stream_info && frag_stream_info->index_entry >= 0) {
|
||||
@@ -4815,7 +4819,7 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom)
|
||||
break;
|
||||
}
|
||||
}
|
||||
av_assert0(index_entry_pos <= st->internal->nb_index_entries);
|
||||
av_assert0(index_entry_pos <= st->nb_index_entries);
|
||||
|
||||
avio_r8(pb); /* version */
|
||||
flags = avio_rb24(pb);
|
||||
@@ -4866,22 +4870,22 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom)
|
||||
av_log(c->fc, AV_LOG_TRACE, "first sample flags 0x%x\n", first_sample_flags);
|
||||
|
||||
// realloc space for new index entries
|
||||
if((uint64_t)st->internal->nb_index_entries + entries >= UINT_MAX / sizeof(AVIndexEntry)) {
|
||||
entries = UINT_MAX / sizeof(AVIndexEntry) - st->internal->nb_index_entries;
|
||||
if((uint64_t)st->nb_index_entries + entries >= UINT_MAX / sizeof(AVIndexEntry)) {
|
||||
entries = UINT_MAX / sizeof(AVIndexEntry) - st->nb_index_entries;
|
||||
av_log(c->fc, AV_LOG_ERROR, "Failed to add index entry\n");
|
||||
}
|
||||
if (entries == 0)
|
||||
return 0;
|
||||
|
||||
requested_size = (st->internal->nb_index_entries + entries) * sizeof(AVIndexEntry);
|
||||
new_entries = av_fast_realloc(st->internal->index_entries,
|
||||
&st->internal->index_entries_allocated_size,
|
||||
requested_size = (st->nb_index_entries + entries) * sizeof(AVIndexEntry);
|
||||
new_entries = av_fast_realloc(st->index_entries,
|
||||
&st->index_entries_allocated_size,
|
||||
requested_size);
|
||||
if (!new_entries)
|
||||
return AVERROR(ENOMEM);
|
||||
st->internal->index_entries= new_entries;
|
||||
st->index_entries= new_entries;
|
||||
|
||||
requested_size = (st->internal->nb_index_entries + entries) * sizeof(*sc->ctts_data);
|
||||
requested_size = (st->nb_index_entries + entries) * sizeof(*sc->ctts_data);
|
||||
old_ctts_allocated_size = sc->ctts_allocated_size;
|
||||
ctts_data = av_fast_realloc(sc->ctts_data, &sc->ctts_allocated_size,
|
||||
requested_size);
|
||||
@@ -4895,12 +4899,12 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom)
|
||||
memset((uint8_t*)(sc->ctts_data) + old_ctts_allocated_size, 0,
|
||||
sc->ctts_allocated_size - old_ctts_allocated_size);
|
||||
|
||||
if (index_entry_pos < st->internal->nb_index_entries) {
|
||||
if (index_entry_pos < st->nb_index_entries) {
|
||||
// Make hole in index_entries and ctts_data for new samples
|
||||
memmove(st->internal->index_entries + index_entry_pos + entries,
|
||||
st->internal->index_entries + index_entry_pos,
|
||||
sizeof(*st->internal->index_entries) *
|
||||
(st->internal->nb_index_entries - index_entry_pos));
|
||||
memmove(st->index_entries + index_entry_pos + entries,
|
||||
st->index_entries + index_entry_pos,
|
||||
sizeof(*st->index_entries) *
|
||||
(st->nb_index_entries - index_entry_pos));
|
||||
memmove(sc->ctts_data + index_entry_pos + entries,
|
||||
sc->ctts_data + index_entry_pos,
|
||||
sizeof(*sc->ctts_data) * (sc->ctts_count - index_entry_pos));
|
||||
@@ -4909,15 +4913,15 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom)
|
||||
}
|
||||
}
|
||||
|
||||
st->internal->nb_index_entries += entries;
|
||||
sc->ctts_count = st->internal->nb_index_entries;
|
||||
st->nb_index_entries += entries;
|
||||
sc->ctts_count = st->nb_index_entries;
|
||||
|
||||
// Record the index_entry position in frag_index of this fragment
|
||||
if (frag_stream_info)
|
||||
frag_stream_info->index_entry = index_entry_pos;
|
||||
|
||||
if (index_entry_pos > 0)
|
||||
prev_dts = st->internal->index_entries[index_entry_pos-1].timestamp;
|
||||
prev_dts = st->index_entries[index_entry_pos-1].timestamp;
|
||||
|
||||
for (i = 0; i < entries && !pb->eof_reached; i++) {
|
||||
unsigned sample_size = frag->size;
|
||||
@@ -4966,11 +4970,11 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom)
|
||||
if (prev_dts >= dts)
|
||||
index_entry_flags |= AVINDEX_DISCARD_FRAME;
|
||||
|
||||
st->internal->index_entries[index_entry_pos].pos = offset;
|
||||
st->internal->index_entries[index_entry_pos].timestamp = dts;
|
||||
st->internal->index_entries[index_entry_pos].size= sample_size;
|
||||
st->internal->index_entries[index_entry_pos].min_distance= distance;
|
||||
st->internal->index_entries[index_entry_pos].flags = index_entry_flags;
|
||||
st->index_entries[index_entry_pos].pos = offset;
|
||||
st->index_entries[index_entry_pos].timestamp = dts;
|
||||
st->index_entries[index_entry_pos].size= sample_size;
|
||||
st->index_entries[index_entry_pos].min_distance= distance;
|
||||
st->index_entries[index_entry_pos].flags = index_entry_flags;
|
||||
|
||||
sc->ctts_data[index_entry_pos].count = 1;
|
||||
sc->ctts_data[index_entry_pos].duration = ctts_duration;
|
||||
@@ -4997,16 +5001,16 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom)
|
||||
// EOF found before reading all entries. Fix the hole this would
|
||||
// leave in index_entries and ctts_data
|
||||
int gap = entries - i;
|
||||
memmove(st->internal->index_entries + index_entry_pos,
|
||||
st->internal->index_entries + index_entry_pos + gap,
|
||||
sizeof(*st->internal->index_entries) *
|
||||
(st->internal->nb_index_entries - (index_entry_pos + gap)));
|
||||
memmove(st->index_entries + index_entry_pos,
|
||||
st->index_entries + index_entry_pos + gap,
|
||||
sizeof(*st->index_entries) *
|
||||
(st->nb_index_entries - (index_entry_pos + gap)));
|
||||
memmove(sc->ctts_data + index_entry_pos,
|
||||
sc->ctts_data + index_entry_pos + gap,
|
||||
sizeof(*sc->ctts_data) *
|
||||
(sc->ctts_count - (index_entry_pos + gap)));
|
||||
|
||||
st->internal->nb_index_entries -= gap;
|
||||
st->nb_index_entries -= gap;
|
||||
sc->ctts_count -= gap;
|
||||
if (index_entry_pos < sc->current_sample) {
|
||||
sc->current_sample -= gap;
|
||||
@@ -5019,11 +5023,11 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom)
|
||||
// fragment that overlap with AVINDEX_DISCARD_FRAME
|
||||
prev_dts = AV_NOPTS_VALUE;
|
||||
if (index_entry_pos > 0)
|
||||
prev_dts = st->internal->index_entries[index_entry_pos-1].timestamp;
|
||||
for (i = index_entry_pos; i < st->internal->nb_index_entries; i++) {
|
||||
if (prev_dts < st->internal->index_entries[i].timestamp)
|
||||
prev_dts = st->index_entries[index_entry_pos-1].timestamp;
|
||||
for (i = index_entry_pos; i < st->nb_index_entries; i++) {
|
||||
if (prev_dts < st->index_entries[i].timestamp)
|
||||
break;
|
||||
st->internal->index_entries[i].flags |= AVINDEX_DISCARD_FRAME;
|
||||
st->index_entries[i].flags |= AVINDEX_DISCARD_FRAME;
|
||||
}
|
||||
|
||||
// If a hole was created to insert the new index_entries into,
|
||||
@@ -7118,10 +7122,10 @@ static int mov_probe(const AVProbeData *p)
|
||||
int64_t size;
|
||||
int minsize = 8;
|
||||
/* ignore invalid offset */
|
||||
if ((offset + 8) > (unsigned int)p->buf_size)
|
||||
if ((offset + 8ULL) > (unsigned int)p->buf_size)
|
||||
break;
|
||||
size = AV_RB32(p->buf + offset);
|
||||
if (size == 1 && offset + 16 > (unsigned int)p->buf_size) {
|
||||
if (size == 1 && offset + 16 <= (unsigned int)p->buf_size) {
|
||||
size = AV_RB64(p->buf+offset + 8);
|
||||
minsize = 16;
|
||||
} else if (size == 0) {
|
||||
@@ -7165,6 +7169,8 @@ static int mov_probe(const AVProbeData *p)
|
||||
score = FFMAX(score, AVPROBE_SCORE_EXTENSION);
|
||||
break;
|
||||
}
|
||||
if (size > INT64_MAX - offset)
|
||||
break;
|
||||
offset += size;
|
||||
}
|
||||
if (score > AVPROBE_SCORE_MAX - 50 && moov_offset != -1) {
|
||||
@@ -7221,9 +7227,9 @@ static void mov_read_chapters(AVFormatContext *s)
|
||||
|
||||
if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
|
||||
st->disposition |= AV_DISPOSITION_ATTACHED_PIC | AV_DISPOSITION_TIMED_THUMBNAILS;
|
||||
if (st->internal->nb_index_entries) {
|
||||
if (st->nb_index_entries) {
|
||||
// Retrieve the first frame, if possible
|
||||
AVIndexEntry *sample = &st->internal->index_entries[0];
|
||||
AVIndexEntry *sample = &st->index_entries[0];
|
||||
if (avio_seek(sc->pb, sample->pos, SEEK_SET) != sample->pos) {
|
||||
av_log(s, AV_LOG_ERROR, "Failed to retrieve first frame\n");
|
||||
goto finish;
|
||||
@@ -7239,9 +7245,9 @@ static void mov_read_chapters(AVFormatContext *s)
|
||||
st->codecpar->codec_type = AVMEDIA_TYPE_DATA;
|
||||
st->codecpar->codec_id = AV_CODEC_ID_BIN_DATA;
|
||||
st->discard = AVDISCARD_ALL;
|
||||
for (i = 0; i < st->internal->nb_index_entries; i++) {
|
||||
AVIndexEntry *sample = &st->internal->index_entries[i];
|
||||
int64_t end = i+1 < st->internal->nb_index_entries ? st->internal->index_entries[i+1].timestamp : st->duration;
|
||||
for (i = 0; i < st->nb_index_entries; i++) {
|
||||
AVIndexEntry *sample = &st->index_entries[i];
|
||||
int64_t end = i+1 < st->nb_index_entries ? st->index_entries[i+1].timestamp : st->duration;
|
||||
uint8_t *title;
|
||||
uint16_t ch;
|
||||
int len, title_len;
|
||||
@@ -7314,10 +7320,10 @@ static int mov_read_rtmd_track(AVFormatContext *s, AVStream *st)
|
||||
int64_t cur_pos = avio_tell(sc->pb);
|
||||
int hh, mm, ss, ff, drop;
|
||||
|
||||
if (!st->internal->nb_index_entries)
|
||||
if (!st->nb_index_entries)
|
||||
return -1;
|
||||
|
||||
avio_seek(sc->pb, st->internal->index_entries->pos, SEEK_SET);
|
||||
avio_seek(sc->pb, st->index_entries->pos, SEEK_SET);
|
||||
avio_skip(s->pb, 13);
|
||||
hh = avio_r8(s->pb);
|
||||
mm = avio_r8(s->pb);
|
||||
@@ -7339,10 +7345,10 @@ static int mov_read_timecode_track(AVFormatContext *s, AVStream *st)
|
||||
int64_t cur_pos = avio_tell(sc->pb);
|
||||
uint32_t value;
|
||||
|
||||
if (!st->internal->nb_index_entries)
|
||||
if (!st->nb_index_entries)
|
||||
return -1;
|
||||
|
||||
avio_seek(sc->pb, st->internal->index_entries->pos, SEEK_SET);
|
||||
avio_seek(sc->pb, st->index_entries->pos, SEEK_SET);
|
||||
value = avio_rb32(s->pb);
|
||||
|
||||
if (sc->tmcd_flags & 0x0001) flags |= AV_TIMECODE_FLAG_DROPFRAME;
|
||||
@@ -7807,8 +7813,8 @@ static AVIndexEntry *mov_find_next_sample(AVFormatContext *s, AVStream **st)
|
||||
for (i = 0; i < s->nb_streams; i++) {
|
||||
AVStream *avst = s->streams[i];
|
||||
MOVStreamContext *msc = avst->priv_data;
|
||||
if (msc->pb && msc->current_sample < avst->internal->nb_index_entries) {
|
||||
AVIndexEntry *current_sample = &avst->internal->index_entries[msc->current_sample];
|
||||
if (msc->pb && msc->current_sample < avst->nb_index_entries) {
|
||||
AVIndexEntry *current_sample = &avst->index_entries[msc->current_sample];
|
||||
int64_t dts = av_rescale(current_sample->timestamp, AV_TIME_BASE, msc->time_scale);
|
||||
av_log(s, AV_LOG_TRACE, "stream %d, sample %d, dts %"PRId64"\n", i, msc->current_sample, dts);
|
||||
if (!sample || (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL) && current_sample->pos < sample->pos) ||
|
||||
@@ -8011,8 +8017,8 @@ static int mov_read_packet(AVFormatContext *s, AVPacket *pkt)
|
||||
sc->ctts_sample = 0;
|
||||
}
|
||||
} else {
|
||||
int64_t next_dts = (sc->current_sample < st->internal->nb_index_entries) ?
|
||||
st->internal->index_entries[sc->current_sample].timestamp : st->duration;
|
||||
int64_t next_dts = (sc->current_sample < st->nb_index_entries) ?
|
||||
st->index_entries[sc->current_sample].timestamp : st->duration;
|
||||
|
||||
if (next_dts >= pkt->dts)
|
||||
pkt->duration = next_dts - pkt->dts;
|
||||
@@ -8093,7 +8099,7 @@ static int mov_seek_stream(AVFormatContext *s, AVStream *st, int64_t timestamp,
|
||||
|
||||
sample = av_index_search_timestamp(st, timestamp, flags);
|
||||
av_log(s, AV_LOG_TRACE, "stream %d, timestamp %"PRId64", sample %d\n", st->index, timestamp, sample);
|
||||
if (sample < 0 && st->internal->nb_index_entries && timestamp < st->internal->index_entries[0].timestamp)
|
||||
if (sample < 0 && st->nb_index_entries && timestamp < st->index_entries[0].timestamp)
|
||||
sample = 0;
|
||||
if (sample < 0) /* not sure what to do */
|
||||
return AVERROR_INVALIDDATA;
|
||||
@@ -8134,8 +8140,8 @@ static int mov_seek_stream(AVFormatContext *s, AVStream *st, int64_t timestamp,
|
||||
static int64_t mov_get_skip_samples(AVStream *st, int sample)
|
||||
{
|
||||
MOVStreamContext *sc = st->priv_data;
|
||||
int64_t first_ts = st->internal->index_entries[0].timestamp;
|
||||
int64_t ts = st->internal->index_entries[sample].timestamp;
|
||||
int64_t first_ts = st->index_entries[0].timestamp;
|
||||
int64_t ts = st->index_entries[sample].timestamp;
|
||||
int64_t off;
|
||||
|
||||
if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO)
|
||||
@@ -8164,7 +8170,7 @@ static int mov_read_seek(AVFormatContext *s, int stream_index, int64_t sample_ti
|
||||
|
||||
if (mc->seek_individually) {
|
||||
/* adjust seek timestamp to found sample timestamp */
|
||||
int64_t seek_timestamp = st->internal->index_entries[sample].timestamp;
|
||||
int64_t seek_timestamp = st->index_entries[sample].timestamp;
|
||||
st->internal->skip_samples = mov_get_skip_samples(st, sample);
|
||||
|
||||
for (i = 0; i < s->nb_streams; i++) {
|
||||
|
||||
@@ -5746,11 +5746,12 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt)
|
||||
|
||||
if (trk->entry >= trk->cluster_capacity) {
|
||||
unsigned new_capacity = trk->entry + MOV_INDEX_CLUSTER_SIZE;
|
||||
if (av_reallocp_array(&trk->cluster, new_capacity,
|
||||
sizeof(*trk->cluster))) {
|
||||
void *cluster = av_realloc_array(trk->cluster, new_capacity, sizeof(*trk->cluster));
|
||||
if (!cluster) {
|
||||
ret = AVERROR(ENOMEM);
|
||||
goto err;
|
||||
}
|
||||
trk->cluster = cluster;
|
||||
trk->cluster_capacity = new_capacity;
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user