frame, av_frame_free_unique);
}
+void avcodec_free_context_unique(AVCodecContext *codec_ctx)
+{
+ avcodec_free_context(&codec_ctx);
+}
+
} // namespace
shared_ptr<const ImageInput::Image> ImageInput::load_image_raw(const string &pathname)
int stream_index = -1;
for (unsigned i = 0; i < format_ctx->nb_streams; ++i) {
- if (format_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
+ if (format_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
stream_index = i;
break;
}
return nullptr;
}
- AVCodecContext *codec_ctx = format_ctx->streams[stream_index]->codec;
- AVCodec *codec = avcodec_find_decoder(codec_ctx->codec_id);
+ const AVCodecParameters *codecpar = format_ctx->streams[stream_index]->codecpar;
+ AVCodecContext *codec_ctx = avcodec_alloc_context3(nullptr);
+ unique_ptr<AVCodecContext, decltype(avcodec_free_context_unique)*> codec_ctx_free(
+ codec_ctx, avcodec_free_context_unique);
+ if (avcodec_parameters_to_context(codec_ctx, codecpar) < 0) {
+ fprintf(stderr, "%s: Cannot fill codec parameters\n", pathname.c_str());
+ return nullptr;
+ }
+ AVCodec *codec = avcodec_find_decoder(codecpar->codec_id);
if (codec == nullptr) {
fprintf(stderr, "%s: Cannot find decoder\n", pathname.c_str());
return nullptr;
// Read packets until we have a frame or there are none left.
int frame_finished = 0;
auto frame = av_frame_alloc_unique();
+ bool eof = false;
do {
AVPacket pkt;
unique_ptr<AVPacket, decltype(av_packet_unref)*> pkt_cleanup(
av_init_packet(&pkt);
pkt.data = nullptr;
pkt.size = 0;
- if (av_read_frame(format_ctx.get(), &pkt) < 0) {
- break;
- }
- if (pkt.stream_index != stream_index) {
- continue;
+ if (av_read_frame(format_ctx.get(), &pkt) == 0) {
+ if (pkt.stream_index != stream_index) {
+ continue;
+ }
+ if (avcodec_send_packet(codec_ctx, &pkt) < 0) {
+ fprintf(stderr, "%s: Cannot send packet to codec.\n", pathname.c_str());
+ return nullptr;
+ }
+ } else {
+ eof = true; // Or error, but ignore that for the time being.
}
- if (avcodec_decode_video2(codec_ctx, frame.get(), &frame_finished, &pkt) < 0) {
- fprintf(stderr, "%s: Cannot decode frame\n", pathname.c_str());
+ int err = avcodec_receive_frame(codec_ctx, frame.get());
+ if (err == 0) {
+ frame_finished = true;
+ break;
+ } else if (err != AVERROR(EAGAIN)) {
+ fprintf(stderr, "%s: Cannot receive frame from codec.\n", pathname.c_str());
return nullptr;
}
- } while (!frame_finished);
+ } while (!eof);
- // See if there's a cached frame for us.
- if (!frame_finished) {
- AVPacket pkt;
- pkt.data = nullptr;
- pkt.size = 0;
- if (avcodec_decode_video2(codec_ctx, frame.get(), &frame_finished, &pkt) < 0) {
- fprintf(stderr, "%s: Cannot decode frame\n", pathname.c_str());
- return nullptr;
- }
- }
if (!frame_finished) {
fprintf(stderr, "%s: Decoder did not output frame.\n", pathname.c_str());
return nullptr;