static void pullup_release_frame(PullupFrame *f) { int i; for (i = 0; i < f->length; i++) pullup_release_buffer(f->ifields[i], f->parity ^ (i & 1)); pullup_release_buffer(f->ofields[0], 0); pullup_release_buffer(f->ofields[1], 1); if (f->buffer) pullup_release_buffer(f->buffer, 2); f->lock--; }
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) { struct pullup_context *c = vf->priv->ctx; struct pullup_buffer *b; struct pullup_frame *f; mp_image_t *dmpi; int ret; int p; int i; if (!vf->priv->init) init_pullup(vf, mpi); if (mpi->flags & MP_IMGFLAG_DIRECT) { b = mpi->priv; mpi->priv = 0; } else { b = pullup_get_buffer(c, 2); if (!b) { mp_msg(MSGT_VFILTER,MSGL_ERR,"Could not get buffer from pullup!\n"); f = pullup_get_frame(c); pullup_release_frame(f); return 0; } memcpy_pic(b->planes[0], mpi->planes[0], mpi->w, mpi->h, c->stride[0], mpi->stride[0]); if (mpi->flags & MP_IMGFLAG_PLANAR) { memcpy_pic(b->planes[1], mpi->planes[1], mpi->chroma_width, mpi->chroma_height, c->stride[1], mpi->stride[1]); memcpy_pic(b->planes[2], mpi->planes[2], mpi->chroma_width, mpi->chroma_height, c->stride[2], mpi->stride[2]); } } if (mpi->qscale) { fast_memcpy(b->planes[3], mpi->qscale, c->w[3]); fast_memcpy(b->planes[3]+c->w[3], mpi->qscale, c->w[3]); } p = mpi->fields & MP_IMGFIELD_TOP_FIRST ? 0 : (mpi->fields & MP_IMGFIELD_ORDERED ? 1 : 0); pullup_submit_field(c, b, p); pullup_submit_field(c, b, p^1); if (mpi->fields & MP_IMGFIELD_REPEAT_FIRST) pullup_submit_field(c, b, p); pullup_release_buffer(b, 2); f = pullup_get_frame(c); /* Fake yes for first few frames (buffer depth) to keep from * breaking A/V sync with G1's bad architecture... */ if (!f) return vf->priv->fakecount ? (--vf->priv->fakecount,1) : 0; if (f->length < 2) { pullup_release_frame(f); f = pullup_get_frame(c); if (!f) return 0; if (f->length < 2) { pullup_release_frame(f); if (!(mpi->fields & MP_IMGFIELD_REPEAT_FIRST)) return 0; f = pullup_get_frame(c); if (!f) return 0; if (f->length < 2) { pullup_release_frame(f); return 0; } } } #if 0 /* Average qscale tables from both frames. */ if (mpi->qscale) { for (i=0; i<c->w[3]; i++) { vf->priv->qbuf[i] = (f->ofields[0]->planes[3][i] + f->ofields[1]->planes[3][i+c->w[3]])>>1; } } #else /* Take worst of qscale tables from both frames. */ if (mpi->qscale) { for (i=0; i<c->w[3]; i++) { vf->priv->qbuf[i] = MAX(f->ofields[0]->planes[3][i], f->ofields[1]->planes[3][i+c->w[3]]); } } #endif /* If the frame isn't already exportable... */ while (!f->buffer) { dmpi = vf_get_image(vf->next, mpi->imgfmt, MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE, mpi->width, mpi->height); /* FIXME: Is it ok to discard dmpi if it's not direct? */ if (!(dmpi->flags & MP_IMGFLAG_DIRECT)) { pullup_pack_frame(c, f); break; } /* Direct render fields into output buffer */ my_memcpy_pic(dmpi->planes[0], f->ofields[0]->planes[0], mpi->w, mpi->h/2, dmpi->stride[0]*2, c->stride[0]*2); my_memcpy_pic(dmpi->planes[0] + dmpi->stride[0], f->ofields[1]->planes[0] + c->stride[0], mpi->w, mpi->h/2, dmpi->stride[0]*2, c->stride[0]*2); if (mpi->flags & MP_IMGFLAG_PLANAR) { my_memcpy_pic(dmpi->planes[1], f->ofields[0]->planes[1], mpi->chroma_width, mpi->chroma_height/2, dmpi->stride[1]*2, c->stride[1]*2); my_memcpy_pic(dmpi->planes[1] + dmpi->stride[1], f->ofields[1]->planes[1] + c->stride[1], mpi->chroma_width, mpi->chroma_height/2, dmpi->stride[1]*2, c->stride[1]*2); my_memcpy_pic(dmpi->planes[2], f->ofields[0]->planes[2], mpi->chroma_width, mpi->chroma_height/2, dmpi->stride[2]*2, c->stride[2]*2); my_memcpy_pic(dmpi->planes[2] + dmpi->stride[2], f->ofields[1]->planes[2] + c->stride[2], mpi->chroma_width, mpi->chroma_height/2, dmpi->stride[2]*2, c->stride[2]*2); } pullup_release_frame(f); if (mpi->qscale) { dmpi->qscale = vf->priv->qbuf; dmpi->qstride = mpi->qstride; dmpi->qscale_type = mpi->qscale_type; } return vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE); } dmpi = vf_get_image(vf->next, mpi->imgfmt, MP_IMGTYPE_EXPORT, MP_IMGFLAG_ACCEPT_STRIDE, mpi->width, mpi->height); dmpi->planes[0] = f->buffer->planes[0]; dmpi->planes[1] = f->buffer->planes[1]; dmpi->planes[2] = f->buffer->planes[2]; dmpi->stride[0] = c->stride[0]; dmpi->stride[1] = c->stride[1]; dmpi->stride[2] = c->stride[2]; if (mpi->qscale) { dmpi->qscale = vf->priv->qbuf; dmpi->qstride = mpi->qstride; dmpi->qscale_type = mpi->qscale_type; } ret = vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE); pullup_release_frame(f); return ret; }
static int IvtcFilter (VideoFilter *vf, VideoFrame *frame, int field) { (void)field; ThisFilter *filter = (ThisFilter *) vf; if (!frame->interlaced_frame) { filter->progressive_frame_seen = 1; } if (filter->progressive_frame_seen && frame->interlaced_frame) { filter->interlaced_frame_seen = 1; } if (!frame->interlaced_frame && !filter->apply_filter && filter->interlaced_frame_seen && filter->progressive_frame_seen) { fprintf(stderr,"turning on inverse telecine filter"); filter->apply_filter = 1; } if (!filter->apply_filter) return 1; SetupFilter(filter, frame->width, frame->height, (int*)frame->pitches); struct pullup_buffer *b; struct pullup_frame *f; int ypitch = filter->context->stride[0]; int height = filter->height; int cpitch = filter->context->stride[1]; int cheight = filter->height >> 1; int p = frame->top_field_first ^ 1; struct pullup_context *c = filter->context; if (c->bpp[0] == 0) c->bpp[0] = c->bpp[1] = c->bpp[2] = frame->bpp; b = pullup_get_buffer(c,2); if (!b) { f = pullup_get_frame(c); pullup_release_frame(f); return 0; } memcpy_pic(b->planes[0], frame->buf + frame->offsets[0], height, ypitch, ypitch); memcpy_pic(b->planes[1], frame->buf + frame->offsets[1], cheight, cpitch, cpitch); memcpy_pic(b->planes[2], frame->buf + frame->offsets[2], cheight, cpitch, cpitch); pullup_submit_field(c, b, p); pullup_submit_field(c, b, p^1); if (frame->repeat_pict) pullup_submit_field(c, b, p); pullup_release_buffer(b, 2); f = pullup_get_frame(c); if (!f) return 0; if (f->length < 2) { pullup_release_frame(f); f = pullup_get_frame(c); if (!f) return 0; if (f->length < 2) { pullup_release_frame(f); if (!frame->repeat_pict) return 0; f = pullup_get_frame(c); if (!f) return 0; if (f->length < 2) { pullup_release_frame(f); return 0; } } } if (!f->buffer) { pullup_pack_frame(c, f); } if (!f->buffer) return 0; memcpy_pic(frame->buf + frame->offsets[0], f->buffer->planes[0], height, ypitch, ypitch); memcpy_pic(frame->buf + frame->offsets[1], f->buffer->planes[1], cheight, cpitch, cpitch); memcpy_pic(frame->buf + frame->offsets[2], f->buffer->planes[2], cheight, cpitch, cpitch); pullup_release_frame(f); return 1; }
static int filter_frame(AVFilterLink *inlink, AVFrame *in) { AVFilterContext *ctx = inlink->dst; AVFilterLink *outlink = ctx->outputs[0]; PullupContext *s = ctx->priv; PullupBuffer *b; PullupFrame *f; AVFrame *out; int p, ret = 0; b = pullup_get_buffer(s, 2); if (!b) { av_log(ctx, AV_LOG_WARNING, "Could not get buffer!\n"); f = pullup_get_frame(s); pullup_release_frame(f); goto end; } av_image_copy(b->planes, s->planewidth, (const uint8_t**)in->data, in->linesize, inlink->format, inlink->w, inlink->h); p = in->interlaced_frame ? !in->top_field_first : 0; pullup_submit_field(s, b, p ); pullup_submit_field(s, b, p^1); if (in->repeat_pict) pullup_submit_field(s, b, p); pullup_release_buffer(b, 2); f = pullup_get_frame(s); if (!f) goto end; if (f->length < 2) { pullup_release_frame(f); f = pullup_get_frame(s); if (!f) goto end; if (f->length < 2) { pullup_release_frame(f); if (!in->repeat_pict) goto end; f = pullup_get_frame(s); if (!f) goto end; if (f->length < 2) { pullup_release_frame(f); goto end; } } } /* If the frame isn't already exportable... */ if (!f->buffer) pullup_pack_frame(s, f); out = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!out) { ret = AVERROR(ENOMEM); goto end; } av_frame_copy_props(out, in); av_image_copy(out->data, out->linesize, (const uint8_t**)f->buffer->planes, s->planewidth, inlink->format, inlink->w, inlink->h); ret = ff_filter_frame(outlink, out); pullup_release_frame(f); end: av_frame_free(&in); return ret; }
static struct mp_image *filter(struct vf_instance *vf, struct mp_image *mpi) { struct pullup_context *c = vf->priv->ctx; struct pullup_buffer *b; struct pullup_frame *f; int p; int i; double pts = mpi->pts; struct mp_image *dmpi = NULL; if (!vf->priv->init) init_pullup(vf, mpi); if (1) { b = pullup_get_buffer(c, 2); if (!b) { mp_msg(MSGT_VFILTER,MSGL_ERR,"Could not get buffer from pullup!\n"); f = pullup_get_frame(c); pullup_release_frame(f); goto skip; } memcpy_pic(b->planes[0], mpi->planes[0], mpi->w, mpi->h, c->stride[0], mpi->stride[0]); memcpy_pic(b->planes[1], mpi->planes[1], mpi->chroma_width, mpi->chroma_height, c->stride[1], mpi->stride[1]); memcpy_pic(b->planes[2], mpi->planes[2], mpi->chroma_width, mpi->chroma_height, c->stride[2], mpi->stride[2]); } if (mpi->qscale) { memcpy(b->planes[3], mpi->qscale, c->w[3]); memcpy(b->planes[3]+c->w[3], mpi->qscale, c->w[3]); } p = mpi->fields & MP_IMGFIELD_TOP_FIRST ? 0 : (mpi->fields & MP_IMGFIELD_ORDERED ? 1 : 0); if (pts == MP_NOPTS_VALUE) { pullup_submit_field(c, b, p, MP_NOPTS_VALUE); pullup_submit_field(c, b, p^1, MP_NOPTS_VALUE); if (mpi->fields & MP_IMGFIELD_REPEAT_FIRST) pullup_submit_field(c, b, p, MP_NOPTS_VALUE); } else { double delta; if (vf->priv->lastpts == MP_NOPTS_VALUE) delta = 1001.0/60000.0; // delta = field time distance else delta = (pts - vf->priv->lastpts) / 2; if (delta <= 0.0 || delta >= 0.5) delta = 0.0; vf->priv->lastpts = pts; if (mpi->fields & MP_IMGFIELD_REPEAT_FIRST) { pullup_submit_field(c, b, p, pts - delta); pullup_submit_field(c, b, p^1, pts); pullup_submit_field(c, b, p, pts + delta); } else { pullup_submit_field(c, b, p, pts - delta * 0.5); pullup_submit_field(c, b, p^1, pts + delta * 0.5); } } pullup_release_buffer(b, 2); f = pullup_get_frame(c); /* Fake yes for first few frames (buffer depth) to keep from * breaking A/V sync with G1's bad architecture... */ //if (!f) return vf->priv->fakecount ? (--vf->priv->fakecount,1) : 0; if (!f) goto skip; if (f->length < 2) { pullup_release_frame(f); f = pullup_get_frame(c); if (!f) goto skip; if (f->length < 2) { pullup_release_frame(f); if (!(mpi->fields & MP_IMGFIELD_REPEAT_FIRST)) goto skip; f = pullup_get_frame(c); if (!f) goto skip; if (f->length < 2) { pullup_release_frame(f); goto skip; } } } #if 0 /* Average qscale tables from both frames. */ if (mpi->qscale) { for (i=0; i<c->w[3]; i++) { vf->priv->qbuf[i] = (f->ofields[0]->planes[3][i] + f->ofields[1]->planes[3][i+c->w[3]])>>1; } } #else /* Take worst of qscale tables from both frames. */ if (mpi->qscale) { for (i=0; i<c->w[3]; i++) { vf->priv->qbuf[i] = MAX(f->ofields[0]->planes[3][i], f->ofields[1]->planes[3][i+c->w[3]]); } } #endif /* If the frame isn't already exportable... */ if (!f->buffer) pullup_pack_frame(c, f); // NOTE: the copy could probably be avoided by changing or using the // pullup internal buffer management. But right now just do the // safe thing and always copy. Code outside the filter might // hold a buffer reference even if the filter chain is destroyed. dmpi = vf_alloc_out_image(vf); mp_image_copy_attributes(dmpi, mpi); struct mp_image data = *dmpi; data.planes[0] = f->buffer->planes[0]; data.planes[1] = f->buffer->planes[1]; data.planes[2] = f->buffer->planes[2]; data.stride[0] = c->stride[0]; data.stride[1] = c->stride[1]; data.stride[2] = c->stride[2]; mp_image_copy(dmpi, &data); dmpi->pts = f->pts; // Warning: entirely bogus memory management of qscale if (mpi->qscale) { dmpi->qscale = vf->priv->qbuf; dmpi->qstride = mpi->qstride; dmpi->qscale_type = mpi->qscale_type; } pullup_release_frame(f); skip: talloc_free(mpi); return dmpi; }