static int apply_param_change(AVCodecContext *avctx, const AVPacket *avpkt)
{
- int size, ret;
+ int ret;
+ buffer_size_t size;
const uint8_t *data;
uint32_t flags;
int64_t val;
return 0;
}
-int ff_decode_bsfs_init(AVCodecContext *avctx)
+static int decode_bsfs_init(AVCodecContext *avctx)
{
AVCodecInternal *avci = avctx->internal;
int ret;
AVCodecInternal *avci = avctx->internal;
DecodeSimpleContext *ds = &avci->ds;
AVPacket *pkt = ds->in_pkt;
- // copy to ensure we do not change pkt
int got_frame, actual_got_frame;
int ret;
got_frame = 0;
} else if (avctx->codec->type == AVMEDIA_TYPE_AUDIO) {
uint8_t *side;
- int side_size;
+ buffer_size_t side_size;
uint32_t discard_padding = 0;
uint8_t skip_reason = 0;
uint8_t discard_reason = 0;
}
#define UTF8_MAX_BYTES 4 /* 5 and 6 bytes sequences should not be used */
-static int recode_subtitle(AVCodecContext *avctx,
- AVPacket *outpkt, const AVPacket *inpkt)
+static int recode_subtitle(AVCodecContext *avctx, AVPacket **outpkt,
+ AVPacket *inpkt, AVPacket *buf_pkt)
{
#if CONFIG_ICONV
iconv_t cd = (iconv_t)-1;
int ret = 0;
char *inb, *outb;
size_t inl, outl;
- AVPacket tmp;
#endif
- if (avctx->sub_charenc_mode != FF_SUB_CHARENC_MODE_PRE_DECODER || inpkt->size == 0)
+ if (avctx->sub_charenc_mode != FF_SUB_CHARENC_MODE_PRE_DECODER || inpkt->size == 0) {
+ *outpkt = inpkt;
return 0;
+ }
#if CONFIG_ICONV
inb = inpkt->data;
cd = iconv_open("UTF-8", avctx->sub_charenc);
av_assert0(cd != (iconv_t)-1);
- ret = av_new_packet(&tmp, inl * UTF8_MAX_BYTES);
+ ret = av_new_packet(buf_pkt, inl * UTF8_MAX_BYTES);
+ if (ret < 0)
+ goto end;
+ ret = av_packet_copy_props(buf_pkt, inpkt);
if (ret < 0)
goto end;
- outpkt->buf = tmp.buf;
- outpkt->data = tmp.data;
- outpkt->size = tmp.size;
- outb = outpkt->data;
- outl = outpkt->size;
+ outb = buf_pkt->data;
+ outl = buf_pkt->size;
if (iconv(cd, &inb, &inl, &outb, &outl) == (size_t)-1 ||
iconv(cd, NULL, NULL, &outb, &outl) == (size_t)-1 ||
- outl >= outpkt->size || inl != 0) {
+ outl >= buf_pkt->size || inl != 0) {
ret = FFMIN(AVERROR(errno), -1);
av_log(avctx, AV_LOG_ERROR, "Unable to recode subtitle event \"%s\" "
"from %s to UTF-8\n", inpkt->data, avctx->sub_charenc);
- av_packet_unref(&tmp);
goto end;
}
- outpkt->size -= outl;
- memset(outpkt->data + outpkt->size, 0, outl);
+ buf_pkt->size -= outl;
+ memset(buf_pkt->data + buf_pkt->size, 0, outl);
+ *outpkt = buf_pkt;
+ ret = 0;
end:
+ if (ret < 0)
+ av_packet_unref(buf_pkt);
if (cd != (iconv_t)-1)
iconv_close(cd);
return ret;
int *got_sub_ptr,
AVPacket *avpkt)
{
- int i, ret = 0;
+ int ret = 0;
if (!avpkt->data && avpkt->size) {
av_log(avctx, AV_LOG_ERROR, "invalid packet: NULL data, size != 0\n");
get_subtitle_defaults(sub);
if ((avctx->codec->capabilities & AV_CODEC_CAP_DELAY) || avpkt->size) {
- AVPacket pkt_recoded = *avpkt;
+ AVCodecInternal *avci = avctx->internal;
+ AVPacket *pkt;
- ret = recode_subtitle(avctx, &pkt_recoded, avpkt);
+ ret = recode_subtitle(avctx, &pkt, avpkt, avci->buffer_pkt);
if (ret < 0)
return ret;
- ret = extract_packet_props(avctx->internal, &pkt_recoded);
- if (ret < 0)
- return ret;
-
- if (avctx->pkt_timebase.num && avpkt->pts != AV_NOPTS_VALUE)
- sub->pts = av_rescale_q(avpkt->pts,
- avctx->pkt_timebase, AV_TIME_BASE_Q);
- ret = avctx->codec->decode(avctx, sub, got_sub_ptr, &pkt_recoded);
- av_assert1((ret >= 0) >= !!*got_sub_ptr &&
- !!*got_sub_ptr >= !!sub->num_rects);
+ if (avctx->pkt_timebase.num && avpkt->pts != AV_NOPTS_VALUE)
+ sub->pts = av_rescale_q(avpkt->pts,
+ avctx->pkt_timebase, AV_TIME_BASE_Q);
+ ret = avctx->codec->decode(avctx, sub, got_sub_ptr, pkt);
+ av_assert1((ret >= 0) >= !!*got_sub_ptr &&
+ !!*got_sub_ptr >= !!sub->num_rects);
#if FF_API_ASS_TIMING
- if (avctx->sub_text_format == FF_SUB_TEXT_FMT_ASS_WITH_TIMINGS
- && *got_sub_ptr && sub->num_rects) {
- const AVRational tb = avctx->pkt_timebase.num ? avctx->pkt_timebase
- : avctx->time_base;
- int err = convert_sub_to_old_ass_form(sub, avpkt, tb);
- if (err < 0)
- ret = err;
- }
+ if (avctx->sub_text_format == FF_SUB_TEXT_FMT_ASS_WITH_TIMINGS
+ && *got_sub_ptr && sub->num_rects) {
+ const AVRational tb = avctx->pkt_timebase.num ? avctx->pkt_timebase
+ : avctx->time_base;
+ int err = convert_sub_to_old_ass_form(sub, avpkt, tb);
+ if (err < 0)
+ ret = err;
+ }
#endif
- if (sub->num_rects && !sub->end_display_time && avpkt->duration &&
- avctx->pkt_timebase.num) {
- AVRational ms = { 1, 1000 };
- sub->end_display_time = av_rescale_q(avpkt->duration,
- avctx->pkt_timebase, ms);
- }
-
- if (avctx->codec_descriptor->props & AV_CODEC_PROP_BITMAP_SUB)
- sub->format = 0;
- else if (avctx->codec_descriptor->props & AV_CODEC_PROP_TEXT_SUB)
- sub->format = 1;
-
- for (i = 0; i < sub->num_rects; i++) {
- if (avctx->sub_charenc_mode != FF_SUB_CHARENC_MODE_IGNORE &&
- sub->rects[i]->ass && !utf8_check(sub->rects[i]->ass)) {
- av_log(avctx, AV_LOG_ERROR,
- "Invalid UTF-8 in decoded subtitles text; "
- "maybe missing -sub_charenc option\n");
- avsubtitle_free(sub);
- ret = AVERROR_INVALIDDATA;
- break;
- }
- }
-
- if (avpkt->data != pkt_recoded.data) { // did we recode?
- /* prevent from destroying side data from original packet */
- pkt_recoded.side_data = NULL;
- pkt_recoded.side_data_elems = 0;
+ if (sub->num_rects && !sub->end_display_time && avpkt->duration &&
+ avctx->pkt_timebase.num) {
+ AVRational ms = { 1, 1000 };
+ sub->end_display_time = av_rescale_q(avpkt->duration,
+ avctx->pkt_timebase, ms);
+ }
- av_packet_unref(&pkt_recoded);
+ if (avctx->codec_descriptor->props & AV_CODEC_PROP_BITMAP_SUB)
+ sub->format = 0;
+ else if (avctx->codec_descriptor->props & AV_CODEC_PROP_TEXT_SUB)
+ sub->format = 1;
+
+ for (unsigned i = 0; i < sub->num_rects; i++) {
+ if (avctx->sub_charenc_mode != FF_SUB_CHARENC_MODE_IGNORE &&
+ sub->rects[i]->ass && !utf8_check(sub->rects[i]->ass)) {
+ av_log(avctx, AV_LOG_ERROR,
+ "Invalid UTF-8 in decoded subtitles text; "
+ "maybe missing -sub_charenc option\n");
+ avsubtitle_free(sub);
+ ret = AVERROR_INVALIDDATA;
+ break;
}
+ }
if (*got_sub_ptr)
avctx->frame_number++;
+
+ if (pkt == avci->buffer_pkt) // did we recode?
+ av_packet_unref(avci->buffer_pkt);
}
return ret;
static int add_metadata_from_side_data(const AVPacket *avpkt, AVFrame *frame)
{
- int size;
+ buffer_size_t size;
const uint8_t *side_metadata;
AVDictionary **frame_md = &frame->metadata;
int ff_decode_frame_props(AVCodecContext *avctx, AVFrame *frame)
{
AVPacket *pkt = avctx->internal->last_pkt_props;
- int i;
static const struct {
enum AVPacketSideDataType packet;
enum AVFrameSideDataType frame;
av_fifo_generic_read(avctx->internal->pkt_props,
pkt, sizeof(*pkt), NULL);
- if (pkt) {
- frame->pts = pkt->pts;
+ frame->pts = pkt->pts;
#if FF_API_PKT_PTS
FF_DISABLE_DEPRECATION_WARNINGS
- frame->pkt_pts = pkt->pts;
+ frame->pkt_pts = pkt->pts;
FF_ENABLE_DEPRECATION_WARNINGS
#endif
- frame->pkt_pos = pkt->pos;
- frame->pkt_duration = pkt->duration;
- frame->pkt_size = pkt->size;
-
- for (i = 0; i < FF_ARRAY_ELEMS(sd); i++) {
- int size;
- uint8_t *packet_sd = av_packet_get_side_data(pkt, sd[i].packet, &size);
- if (packet_sd) {
- AVFrameSideData *frame_sd = av_frame_new_side_data(frame,
- sd[i].frame,
- size);
- if (!frame_sd)
- return AVERROR(ENOMEM);
-
- memcpy(frame_sd->data, packet_sd, size);
- }
+ frame->pkt_pos = pkt->pos;
+ frame->pkt_duration = pkt->duration;
+ frame->pkt_size = pkt->size;
+
+ for (int i = 0; i < FF_ARRAY_ELEMS(sd); i++) {
+ buffer_size_t size;
+ uint8_t *packet_sd = av_packet_get_side_data(pkt, sd[i].packet, &size);
+ if (packet_sd) {
+ AVFrameSideData *frame_sd = av_frame_new_side_data(frame,
+ sd[i].frame,
+ size);
+ if (!frame_sd)
+ return AVERROR(ENOMEM);
+
+ memcpy(frame_sd->data, packet_sd, size);
}
- add_metadata_from_side_data(pkt, frame);
+ }
+ add_metadata_from_side_data(pkt, frame);
- if (pkt->flags & AV_PKT_FLAG_DISCARD) {
- frame->flags |= AV_FRAME_FLAG_DISCARD;
- } else {
- frame->flags = (frame->flags & ~AV_FRAME_FLAG_DISCARD);
- }
+ if (pkt->flags & AV_PKT_FLAG_DISCARD) {
+ frame->flags |= AV_FRAME_FLAG_DISCARD;
+ } else {
+ frame->flags = (frame->flags & ~AV_FRAME_FLAG_DISCARD);
}
frame->reordered_opaque = avctx->reordered_opaque;
av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
return ret;
}
+
+int ff_decode_preinit(AVCodecContext *avctx)
+{
+ int ret = 0;
+
+ /* if the decoder init function was already called previously,
+ * free the already allocated subtitle_header before overwriting it */
+ av_freep(&avctx->subtitle_header);
+
+#if FF_API_THREAD_SAFE_CALLBACKS
+FF_DISABLE_DEPRECATION_WARNINGS
+ if ((avctx->thread_type & FF_THREAD_FRAME) &&
+ avctx->get_buffer2 != avcodec_default_get_buffer2 &&
+ !avctx->thread_safe_callbacks) {
+ av_log(avctx, AV_LOG_WARNING, "Requested frame threading with a "
+ "custom get_buffer2() implementation which is not marked as "
+ "thread safe. This is not supported anymore, make your "
+ "callback thread-safe.\n");
+ }
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+
+ if (avctx->codec->max_lowres < avctx->lowres || avctx->lowres < 0) {
+ av_log(avctx, AV_LOG_WARNING, "The maximum value for lowres supported by the decoder is %d\n",
+ avctx->codec->max_lowres);
+ avctx->lowres = avctx->codec->max_lowres;
+ }
+
+ avctx->pts_correction_num_faulty_pts =
+ avctx->pts_correction_num_faulty_dts = 0;
+ avctx->pts_correction_last_pts =
+ avctx->pts_correction_last_dts = INT64_MIN;
+
+ if ( !CONFIG_GRAY && avctx->flags & AV_CODEC_FLAG_GRAY
+ && avctx->codec_descriptor->type == AVMEDIA_TYPE_VIDEO)
+ av_log(avctx, AV_LOG_WARNING,
+ "gray decoding requested but not enabled at configuration time\n");
+ if (avctx->flags2 & AV_CODEC_FLAG2_EXPORT_MVS) {
+ avctx->export_side_data |= AV_CODEC_EXPORT_DATA_MVS;
+ }
+
+ ret = decode_bsfs_init(avctx);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}