static int lavfi_read_packet(AVFormatContext *avctx, AVPacket *pkt)
{
    LavfiContext *lavfi = avctx->priv_data;
    double min_pts = DBL_MAX;
    int stream_idx, min_pts_sink_idx = 0;
    AVFilterBufferRef *ref;
    AVPicture pict;
    int ret, i;
    int size = 0;

    /* iterate through all the graph sinks. Select the sink with the
     * minimum PTS */
    for (i = 0; i < avctx->nb_streams; i++) {
        AVRational tb = lavfi->sinks[i]->inputs[0]->time_base;
        double d;
        int ret;

        if (lavfi->sink_eof[i])
            continue;

        ret = av_buffersink_get_buffer_ref(lavfi->sinks[i],
                                       &ref, AV_BUFFERSINK_FLAG_PEEK);
        if (ret == AVERROR_EOF) {
            av_dlog(avctx, "EOF sink_idx:%d\n", i);
            lavfi->sink_eof[i] = 1;
            continue;
        } else if (ret < 0)
            return ret;
        d = av_rescale_q(ref->pts, tb, AV_TIME_BASE_Q);
        av_dlog(avctx, "sink_idx:%d time:%f\n", i, d);

        if (d < min_pts) {
            min_pts = d;
            min_pts_sink_idx = i;
        }
    }
    if (min_pts == DBL_MAX)
        return AVERROR_EOF;

    av_dlog(avctx, "min_pts_sink_idx:%i\n", min_pts_sink_idx);

    av_buffersink_get_buffer_ref(lavfi->sinks[min_pts_sink_idx], &ref, 0);
    stream_idx = lavfi->sink_stream_map[min_pts_sink_idx];

    if (ref->video) {
        size = avpicture_get_size(ref->format, ref->video->w, ref->video->h);
        if ((ret = av_new_packet(pkt, size)) < 0)
            return ret;

        memcpy(pict.data,     ref->data,     4*sizeof(ref->data[0]));
        memcpy(pict.linesize, ref->linesize, 4*sizeof(ref->linesize[0]));

        avpicture_layout(&pict, ref->format, ref->video->w,
                         ref->video->h, pkt->data, size);
    } else if (ref->audio) {
        size = ref->audio->nb_samples *
            av_get_bytes_per_sample(ref->format) *
            av_get_channel_layout_nb_channels(ref->audio->channel_layout);
        if ((ret = av_new_packet(pkt, size)) < 0)
            return ret;
        memcpy(pkt->data, ref->data[0], size);
    }

    if (ref->metadata) {
        uint8_t *metadata;
        AVDictionaryEntry *e = NULL;
        AVBPrint meta_buf;

        av_bprint_init(&meta_buf, 0, AV_BPRINT_SIZE_UNLIMITED);
        while ((e = av_dict_get(ref->metadata, "", e, AV_DICT_IGNORE_SUFFIX))) {
            av_bprintf(&meta_buf, "%s", e->key);
            av_bprint_chars(&meta_buf, '\0', 1);
            av_bprintf(&meta_buf, "%s", e->value);
            av_bprint_chars(&meta_buf, '\0', 1);
        }
        if (!av_bprint_is_complete(&meta_buf) ||
            !(metadata = av_packet_new_side_data(pkt, AV_PKT_DATA_STRINGS_METADATA,
                                                 meta_buf.len))) {
            av_bprint_finalize(&meta_buf, NULL);
            return AVERROR(ENOMEM);
        }
        memcpy(metadata, meta_buf.str, meta_buf.len);
        av_bprint_finalize(&meta_buf, NULL);
    }

    pkt->stream_index = stream_idx;
    pkt->pts = ref->pts;
    pkt->pos = ref->pos;
    pkt->size = size;
    avfilter_unref_buffer(ref);
    return size;
}