static int movie_push_frame(AVFilterContext *ctx, unsigned out_id) { MovieContext *movie = ctx->priv; AVPacket *pkt = &movie->pkt; enum AVMediaType frame_type; MovieStream *st; int ret, got_frame = 0, pkt_out_id; AVFilterLink *outlink; AVFrame *frame; if (!pkt->size) { if (movie->eof) { if (movie->st[out_id].done) { if (movie->loop_count != 1) { ret = rewind_file(ctx); if (ret < 0) return ret; movie->loop_count -= movie->loop_count > 1; av_log(ctx, AV_LOG_VERBOSE, "Stream finished, looping.\n"); return 0; /* retry */ } return AVERROR_EOF; } pkt->stream_index = movie->st[out_id].st->index; /* packet is already ready for flushing */ } else { ret = av_read_frame(movie->format_ctx, &movie->pkt0); if (ret < 0) { av_init_packet(&movie->pkt0); /* ready for flushing */ *pkt = movie->pkt0; if (ret == AVERROR_EOF) { movie->eof = 1; return 0; /* start flushing */ } return ret; } *pkt = movie->pkt0; } } pkt_out_id = pkt->stream_index > movie->max_stream_index ? -1 : movie->out_index[pkt->stream_index]; if (pkt_out_id < 0) { av_free_packet(&movie->pkt0); pkt->size = 0; /* ready for next run */ pkt->data = NULL; return 0; } st = &movie->st[pkt_out_id]; outlink = ctx->outputs[pkt_out_id]; frame = av_frame_alloc(); if (!frame) return AVERROR(ENOMEM); frame_type = st->st->codec->codec_type; switch (frame_type) { case AVMEDIA_TYPE_VIDEO: ret = avcodec_decode_video2(st->st->codec, frame, &got_frame, pkt); break; case AVMEDIA_TYPE_AUDIO: ret = avcodec_decode_audio4(st->st->codec, frame, &got_frame, pkt); break; default: ret = AVERROR(ENOSYS); break; } if (ret < 0) { av_log(ctx, AV_LOG_WARNING, "Decode error: %s\n", av_err2str(ret)); av_frame_free(&frame); av_free_packet(&movie->pkt0); movie->pkt.size = 0; movie->pkt.data = NULL; return 0; } if (!ret || st->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) ret = pkt->size; pkt->data += ret; pkt->size -= ret; if (pkt->size <= 0) { av_free_packet(&movie->pkt0); pkt->size = 0; /* ready for next run */ pkt->data = NULL; } if (!got_frame) { if (!ret) st->done = 1; av_frame_free(&frame); return 0; } frame->pts = av_frame_get_best_effort_timestamp(frame); av_dlog(ctx, "movie_push_frame(): file:'%s' %s\n", movie->file_name, describe_frame_to_str((char[1024]){0}, 1024, frame, frame_type, outlink)); if (st->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { if (frame->format != outlink->format) { av_log(ctx, AV_LOG_ERROR, "Format changed %s -> %s, discarding frame\n", av_get_pix_fmt_name(outlink->format), av_get_pix_fmt_name(frame->format) ); av_frame_free(&frame); return 0; } } ret = ff_filter_frame(outlink, frame); if (ret < 0) return ret; return pkt_out_id == out_id; }
static int movie_push_frame(AVFilterContext *ctx, unsigned out_id) { MovieContext *movie = ctx->priv; AVPacket *pkt = &movie->pkt; enum AVMediaType frame_type; MovieStream *st; int ret, got_frame = 0, pkt_out_id; AVFilterLink *outlink; AVFrame *frame; if (!pkt->size) { if (movie->eof) { if (movie->st[out_id].done) { if (movie->loop_count != 1) { ret = rewind_file(ctx); if (ret < 0) return ret; movie->loop_count -= movie->loop_count > 1; av_log(ctx, AV_LOG_VERBOSE, "Stream finished, looping.\n"); return 0;   } return AVERROR_EOF; } pkt->stream_index = movie->st[out_id].st->index;   } else { ret = av_read_frame(movie->format_ctx, &movie->pkt0); if (ret < 0) { av_init_packet(&movie->pkt0);   *pkt = movie->pkt0; if (ret == AVERROR_EOF) { movie->eof = 1; return 0;   } return ret; } *pkt = movie->pkt0; } } pkt_out_id = pkt->stream_index > movie->max_stream_index ? -1 : movie->out_index[pkt->stream_index]; if (pkt_out_id < 0) { av_free_packet(&movie->pkt0); pkt->size = 0;   pkt->data = NULL; return 0; } st = &movie->st[pkt_out_id]; outlink = ctx->outputs[pkt_out_id]; frame = av_frame_alloc(); if (!frame) return AVERROR(ENOMEM); frame_type = st->st->codec->codec_type; switch (frame_type) { case AVMEDIA_TYPE_VIDEO: ret = avcodec_decode_video2(st->st->codec, frame, &got_frame, pkt); break; case AVMEDIA_TYPE_AUDIO: ret = avcodec_decode_audio4(st->st->codec, frame, &got_frame, pkt); break; default: ret = AVERROR(ENOSYS); break; } if (ret < 0) { av_log(ctx, AV_LOG_WARNING, "Decode error: %s\n", av_err2str(ret)); av_frame_free(&frame); av_free_packet(&movie->pkt0); movie->pkt.size = 0; movie->pkt.data = NULL; return 0; } if (!ret || st->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) ret = pkt->size; pkt->data += ret; pkt->size -= ret; if (pkt->size <= 0) { av_free_packet(&movie->pkt0); pkt->size = 0;   pkt->data = NULL; } if (!got_frame) { if (!ret) st->done = 1; av_frame_free(&frame); return 0; } frame->pts = av_frame_get_best_effort_timestamp(frame); av_dlog(ctx, "movie_push_frame(): file:'%s' %s\n", movie->file_name, describe_frame_to_str((char[1024]){0}, 1024, frame, frame_type, outlink)); if (st->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { if (frame->format != outlink->format) { av_log(ctx, AV_LOG_ERROR, "Format changed %s -> %s, discarding frame\n", av_get_pix_fmt_name(outlink->format), av_get_pix_fmt_name(frame->format) ); av_frame_free(&frame); return 0; } } ret = ff_filter_frame(outlink, frame); if (ret < 0) return ret; return pkt_out_id == out_id; }