static void get_frame_defaults(AVFrame *frame) { if (frame->extended_data != frame->data) av_freep(&frame->extended_data); memset(frame, 0, sizeof(*frame)); frame->pts = frame->pkt_dts = frame->pkt_pts = AV_NOPTS_VALUE; av_frame_set_best_effort_timestamp(frame, AV_NOPTS_VALUE); av_frame_set_pkt_duration (frame, 0); av_frame_set_pkt_pos (frame, -1); av_frame_set_pkt_size (frame, -1); frame->key_frame = 1; frame->sample_aspect_ratio = (AVRational) { 0, 1 }; frame->format = -1; /* unknown */ frame->extended_data = frame->data; frame->color_primaries = AVCOL_PRI_UNSPECIFIED; frame->color_trc = AVCOL_TRC_UNSPECIFIED; frame->colorspace = AVCOL_SPC_UNSPECIFIED; frame->color_range = AVCOL_RANGE_UNSPECIFIED; frame->chroma_location = AVCHROMA_LOC_UNSPECIFIED; }
AVFrame* CFFmpegImage::ExtractFrame() { if (!m_fctx || !m_fctx->streams[0]) { CLog::LogFunction(LOGERROR, __FUNCTION__, "No valid format context or stream"); return nullptr; } AVPacket pkt; AVFrame* frame = av_frame_alloc(); int frame_decoded = 0; int ret = 0; ret = av_read_frame(m_fctx, &pkt); if (ret < 0) { CLog::Log(LOGDEBUG, "Error [%d] while reading frame: %s\n", ret, strerror(AVERROR(ret))); av_frame_free(&frame); av_packet_unref(&pkt); return nullptr; } ret = DecodeFFmpegFrame(m_codec_ctx, frame, &frame_decoded, &pkt); if (ret < 0 || frame_decoded == 0 || !frame) { CLog::Log(LOGDEBUG, "Error [%d] while decoding frame: %s\n", ret, strerror(AVERROR(ret))); av_frame_free(&frame); av_packet_unref(&pkt); return nullptr; } //we need milliseconds av_frame_set_pkt_duration(frame, av_rescale_q(frame->pkt_duration, m_fctx->streams[0]->time_base, AVRational{ 1, 1000 })); m_height = frame->height; m_width = frame->width; m_originalWidth = m_width; m_originalHeight = m_height; const AVPixFmtDescriptor* pixDescriptor = av_pix_fmt_desc_get(static_cast<AVPixelFormat>(frame->format)); if (pixDescriptor && ((pixDescriptor->flags & (AV_PIX_FMT_FLAG_ALPHA | AV_PIX_FMT_FLAG_PAL)) != 0)) m_hasAlpha = true; AVDictionary* dic = av_frame_get_metadata(frame); AVDictionaryEntry* entry = NULL; if (dic) { entry = av_dict_get(dic, "Orientation", NULL, AV_DICT_MATCH_CASE); if (entry && entry->value) { int orientation = atoi(entry->value); // only values between including 0 and including 8 // http://sylvana.net/jpegcrop/exif_orientation.html if (orientation >= 0 && orientation <= 8) m_orientation = (unsigned int)orientation; } } av_packet_unref(&pkt); return frame; }
static int gif_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) { GifState *s = avctx->priv_data; int ret; bytestream2_init(&s->gb, avpkt->data, avpkt->size); s->frame->pts = avpkt->pts; s->frame->pkt_pts = avpkt->pts; s->frame->pkt_dts = avpkt->dts; av_frame_set_pkt_duration(s->frame, avpkt->duration); if (avpkt->size >= 6) { s->keyframe = memcmp(avpkt->data, gif87a_sig, 6) == 0 || memcmp(avpkt->data, gif89a_sig, 6) == 0; } else { s->keyframe = 0; } if (s->keyframe) { s->keyframe_ok = 0; s->gce_prev_disposal = GCE_DISPOSAL_NONE; if ((ret = gif_read_header1(s)) < 0) return ret; if ((ret = ff_set_dimensions(avctx, s->screen_width, s->screen_height)) < 0) return ret; av_frame_unref(s->frame); if ((ret = ff_get_buffer(avctx, s->frame, 0)) < 0) return ret; av_fast_malloc(&s->idx_line, &s->idx_line_size, s->screen_width); if (!s->idx_line) return AVERROR(ENOMEM); s->frame->pict_type = AV_PICTURE_TYPE_I; s->frame->key_frame = 1; s->keyframe_ok = 1; } else { if (!s->keyframe_ok) { av_log(avctx, AV_LOG_ERROR, "cannot decode frame without keyframe\n"); return AVERROR_INVALIDDATA; } if ((ret = ff_reget_buffer(avctx, s->frame)) < 0) return ret; s->frame->pict_type = AV_PICTURE_TYPE_P; s->frame->key_frame = 0; } ret = gif_parse_next_image(s, s->frame); if (ret < 0) return ret; if ((ret = av_frame_ref(data, s->frame)) < 0) return ret; *got_frame = 1; return bytestream2_tell(&s->gb); }