static int ff_filter_frame_needs_framing(AVFilterLink *link, AVFrame *frame) { int insamples = frame->nb_samples, inpos = 0, nb_samples; AVFrame *pbuf = link->partial_buf; int nb_channels = av_frame_get_channels(frame); int ret = 0; link->flags |= FF_LINK_FLAG_REQUEST_LOOP; /* Handle framing (min_samples, max_samples) */ while (insamples) { if (!pbuf) { AVRational samples_tb = { 1, link->sample_rate }; pbuf = ff_get_audio_buffer(link, link->partial_buf_size); if (!pbuf) { av_log(link->dst, AV_LOG_WARNING, "Samples dropped due to memory allocation failure.\n"); return 0; } av_frame_copy_props(pbuf, frame); pbuf->pts = frame->pts; if (pbuf->pts != AV_NOPTS_VALUE) pbuf->pts += av_rescale_q(inpos, samples_tb, link->time_base); pbuf->nb_samples = 0; } nb_samples = FFMIN(insamples, link->partial_buf_size - pbuf->nb_samples); av_samples_copy(pbuf->extended_data, frame->extended_data, pbuf->nb_samples, inpos, nb_samples, nb_channels, link->format); inpos += nb_samples; insamples -= nb_samples; pbuf->nb_samples += nb_samples; if (pbuf->nb_samples >= link->min_samples) { ret = ff_filter_frame_framed(link, pbuf); pbuf = NULL; } } av_frame_free(&frame); link->partial_buf = pbuf; return ret; }
int av_frame_make_writable(AVFrame *frame) { AVFrame tmp; int ret; if (!frame->buf[0]) return AVERROR(EINVAL); if (av_frame_is_writable(frame)) return 0; memset(&tmp, 0, sizeof(tmp)); tmp.format = frame->format; tmp.width = frame->width; tmp.height = frame->height; tmp.channel_layout = frame->channel_layout; tmp.nb_samples = frame->nb_samples; ret = av_frame_get_buffer(&tmp, 32); if (ret < 0) return ret; ret = av_frame_copy(&tmp, frame); if (ret < 0) { av_frame_unref(&tmp); return ret; } ret = av_frame_copy_props(&tmp, frame); if (ret < 0) { av_frame_unref(&tmp); return ret; } av_frame_unref(frame); *frame = tmp; if (tmp.data == tmp.extended_data) frame->extended_data = frame->data; return 0; }
static int filter_frame(AVFilterLink *inlink, AVFrame *frame) { AVFilterContext *ctx = inlink->dst; MonoPartsContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; int part = s->current_part++; if (part < s->part1) // stereo passthru return ff_filter_frame(outlink, frame); if (!av_frame_is_writable(frame)) { AVFrame *copy = ff_get_audio_buffer(inlink, frame->nb_samples); av_frame_copy_props(copy, frame); av_frame_copy(copy, frame); av_frame_free(&frame); frame = copy; } if (part == s->part1) { if (part == 0) s->full_mono(frame); else s->stereo2mono(frame); } else if (part < s->part2) s->full_mono(frame); else if (part == s->part2) { bool smallframe = frame->nb_samples < inlink->min_samples; bool lastpart = *s->parts == '\0'; if (smallframe && lastpart) s->full_mono(frame); else s->mono2stereo(frame); if (lastpart) s->part1 = s->part2 = INT_MAX; else if (!scan_part(ctx)) return AVERROR(EINVAL); } return ff_filter_frame(outlink, frame); }
static int filter_frame(AVFilterLink *inlink, AVFrame *insamplesref) { AConvertContext *aconvert = inlink->dst->priv; const int n = insamplesref->nb_samples; AVFilterLink *const outlink = inlink->dst->outputs[0]; AVFrame *outsamplesref = ff_get_audio_buffer(outlink, n); int ret; if (!outsamplesref) return AVERROR(ENOMEM); swr_convert(aconvert->swr, outsamplesref->extended_data, n, (void *)insamplesref->extended_data, n); av_frame_copy_props(outsamplesref, insamplesref); av_frame_set_channels(outsamplesref, outlink->channels); outsamplesref->channel_layout = outlink->channel_layout; ret = ff_filter_frame(outlink, outsamplesref); av_frame_free(&insamplesref); return ret; }
static int dxva2_retrieve_data(AVCodecContext *s, AVFrame *frame) { InputStream *ist = s->opaque; DXVA2Context *ctx = ist->hwaccel_ctx; int ret; ret = av_hwframe_transfer_data(ctx->tmp_frame, frame, 0); if (ret < 0) return ret; ret = av_frame_copy_props(ctx->tmp_frame, frame); if (ret < 0) { av_frame_unref(ctx->tmp_frame); return ret; } av_frame_unref(frame); av_frame_move_ref(frame, ctx->tmp_frame); return 0; }
static int filter_frame(AVFilterLink *inlink, AVFrame *in) { Frei0rContext *s = inlink->dst->priv; AVFilterLink *outlink = inlink->dst->outputs[0]; AVFrame *out; out = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!out) { av_frame_free(&in); return AVERROR(ENOMEM); } av_frame_copy_props(out, in); s->update(s->instance, in->pts * av_q2d(inlink->time_base) * 1000, (const uint32_t *)in->data[0], (uint32_t *)out->data[0]); av_frame_free(&in); return ff_filter_frame(outlink, out); }
// replaced by filter_frame... // need refactoring // static void draw_slice(AVFilterLink *link, int y, int h, int slice_dir) static int filter_frame(AVFilterLink *link, AVFrame *in) { OverlayContext *ovl = link->dst->priv; AVFilterLink *outlink = link->dst->outputs[0]; AVFrame *out; int i, j; int lumaFrame, lumaPrint, lumaMask,uPrint,vPrint; int py; int h = link->h; int y = 0; av_log(link->src, AV_LOG_DEBUG, "filter_frame().\n"); py = ovl->printY; // use py to disable the watermark for interval display if (ovl->printINT > 0) { i = (in->pts / AV_TIME_BASE) % ovl->printINT ; if (i >= ovl->printON) py = y+h+1; // hack to turn off water mark } out = ff_get_video_buffer(outlink, outlink->w, outlink->h); av_frame_copy_props(out, in); lumaMask=255; for (j=0; j<h; j++) { if (y+j<py || y+j>=py+ovl->printH) { memcpy((out->data[0])+(j+y)*out->linesize[0],(in->data[0])+(y+j)*in->linesize[0],link->w); if (j%(1<<ovl->vsub)) { memcpy((out->data[1])+((j+y)>>ovl->vsub)*out->linesize[1],(in->data[1])+((j+y)>>ovl->vsub)*in->linesize[1],link->w >> ovl->hsub); memcpy((out->data[2])+((j+y)>>ovl->vsub)*out->linesize[2],(in->data[2])+((j+y)>>ovl->vsub)*in->linesize[2],link->w >> ovl->hsub); } } else {
static int filter_frame(AVFilterLink *inlink, AVFrame *in) { AVFilterContext *ctx = inlink->dst; WeaveContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; AVFrame *out; int i; if (!s->prev) { s->prev = in; return 0; } out = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!out) { av_frame_free(&in); av_frame_free(&s->prev); return AVERROR(ENOMEM); } av_frame_copy_props(out, in); for (i = 0; i < s->nb_planes; i++) { av_image_copy_plane(out->data[i] + out->linesize[i] * s->first_field, out->linesize[i] * 2, in->data[i], in->linesize[i], s->linesize[i], s->planeheight[i]); av_image_copy_plane(out->data[i] + out->linesize[i] * !s->first_field, out->linesize[i] * 2, s->prev->data[i], s->prev->linesize[i], s->linesize[i], s->planeheight[i]); } out->pts = in->pts / 2; out->interlaced_frame = 1; out->top_field_first = !s->first_field; av_frame_free(&in); av_frame_free(&s->prev); return ff_filter_frame(outlink, out); }
static int shuffleplanes_filter_frame(AVFilterLink *inlink, AVFrame *frame) { AVFilterContext *ctx = inlink->dst; ShufflePlanesContext *s = ctx->priv; uint8_t *shuffled_data[4] = { NULL }; int shuffled_linesize[4] = { 0 }; int i, ret; for (i = 0; i < s->planes; i++) { shuffled_data[i] = frame->data[s->map[i]]; shuffled_linesize[i] = frame->linesize[s->map[i]]; } memcpy(frame->data, shuffled_data, sizeof(shuffled_data)); memcpy(frame->linesize, shuffled_linesize, sizeof(shuffled_linesize)); if (s->copy) { AVFrame *copy = ff_get_video_buffer(ctx->outputs[0], frame->width, frame->height); if (!copy) { ret = AVERROR(ENOMEM); goto fail; } av_frame_copy(copy, frame); ret = av_frame_copy_props(copy, frame); if (ret < 0) { av_frame_free(©); goto fail; } av_frame_free(&frame); frame = copy; } return ff_filter_frame(ctx->outputs[0], frame); fail: av_frame_free(&frame); return ret; }
static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref) { RemovelogoContext *s = inlink->dst->priv; AVFilterLink *outlink = inlink->dst->outputs[0]; AVFrame *outpicref; int direct = 0; if (av_frame_is_writable(inpicref)) { direct = 1; outpicref = inpicref; } else { outpicref = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!outpicref) { av_frame_free(&inpicref); return AVERROR(ENOMEM); } av_frame_copy_props(outpicref, inpicref); } blur_image(s->mask, inpicref ->data[0], inpicref ->linesize[0], outpicref->data[0], outpicref->linesize[0], s->full_mask_data, inlink->w, inlink->w, inlink->h, direct, &s->full_mask_bbox); blur_image(s->mask, inpicref ->data[1], inpicref ->linesize[1], outpicref->data[1], outpicref->linesize[1], s->half_mask_data, inlink->w/2, inlink->w/2, inlink->h/2, direct, &s->half_mask_bbox); blur_image(s->mask, inpicref ->data[2], inpicref ->linesize[2], outpicref->data[2], outpicref->linesize[2], s->half_mask_data, inlink->w/2, inlink->w/2, inlink->h/2, direct, &s->half_mask_bbox); if (!direct) av_frame_free(&inpicref); return ff_filter_frame(outlink, outpicref); }
static int return_frame(AVFilterContext *ctx, int is_second) { YADIFContext *yadif = ctx->priv; AVFilterLink *link = ctx->outputs[0]; int tff, ret; if (yadif->parity == -1) { tff = yadif->cur->interlaced_frame ? yadif->cur->top_field_first : 1; } else { tff = yadif->parity ^ 1; } if (is_second) { yadif->out = ff_get_video_buffer(link, link->w, link->h); if (!yadif->out) return AVERROR(ENOMEM); av_frame_copy_props(yadif->out, yadif->cur); yadif->out->interlaced_frame = 0; } yadif->filter(ctx, yadif->out, tff ^ !is_second, tff); if (is_second) { int64_t cur_pts = yadif->cur->pts; int64_t next_pts = yadif->next->pts; if (next_pts != AV_NOPTS_VALUE && cur_pts != AV_NOPTS_VALUE) { yadif->out->pts = cur_pts + next_pts; } else { yadif->out->pts = AV_NOPTS_VALUE; } } ret = ff_filter_frame(ctx->outputs[0], yadif->out); yadif->frame_pending = (yadif->mode&1) && !is_second; return ret; }
static int process_frame(FFFrameSync *fs) { AVFilterContext *ctx = fs->parent; ThresholdContext *s = fs->opaque; AVFilterLink *outlink = ctx->outputs[0]; AVFrame *out, *in, *threshold, *min, *max; ThreadData td; int ret; if ((ret = ff_framesync_get_frame(&s->fs, 0, &in, 0)) < 0 || (ret = ff_framesync_get_frame(&s->fs, 1, &threshold, 0)) < 0 || (ret = ff_framesync_get_frame(&s->fs, 2, &min, 0)) < 0 || (ret = ff_framesync_get_frame(&s->fs, 3, &max, 0)) < 0) return ret; if (ctx->is_disabled) { out = av_frame_clone(in); if (!out) return AVERROR(ENOMEM); } else { out = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!out) return AVERROR(ENOMEM); av_frame_copy_props(out, in); td.out = out; td.in = in; td.threshold = threshold; td.min = min; td.max = max; ctx->internal->execute(ctx, filter_slice, &td, NULL, FFMIN(s->height[2], ff_filter_get_nb_threads(ctx))); } out->pts = av_rescale_q(s->fs.pts, s->fs.time_base, outlink->time_base); return ff_filter_frame(outlink, out); }
static int filter_frame(AVFilterLink *inlink, AVFrame *in) { AVFilterContext *ctx = inlink->dst; AVFilterLink *outlink = ctx->outputs[0]; DebandContext *s = ctx->priv; AVFrame *out; ThreadData td; out = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!out) { av_frame_free(&in); return AVERROR(ENOMEM); } av_frame_copy_props(out, in); td.in = in; td.out = out; ctx->internal->execute(ctx, s->deband, &td, NULL, FFMIN3(s->planeheight[1], s->planeheight[2], ctx->graph->nb_threads)); av_frame_free(&in); return ff_filter_frame(outlink, out); }
static int filter_frame(AVFilterLink *inlink, AVFrame *inbuf) { AudioPhaserContext *p = inlink->dst->priv; AVFilterLink *outlink = inlink->dst->outputs[0]; AVFrame *outbuf; if (av_frame_is_writable(inbuf)) { outbuf = inbuf; } else { outbuf = ff_get_audio_buffer(inlink, inbuf->nb_samples); if (!outbuf) return AVERROR(ENOMEM); av_frame_copy_props(outbuf, inbuf); } p->phaser(p, inbuf->extended_data, outbuf->extended_data, outbuf->nb_samples, av_frame_get_channels(outbuf)); if (inbuf != outbuf) av_frame_free(&inbuf); return ff_filter_frame(outlink, outbuf); }
static int filter_frame(AVFilterLink *inlink, AVFrame *in) { AVFilterContext *ctx = inlink->dst; BoxBlurContext *s = ctx->priv; AVFilterLink *outlink = inlink->dst->outputs[0]; AVFrame *out; int plane; int cw = AV_CEIL_RSHIFT(inlink->w, s->hsub), ch = AV_CEIL_RSHIFT(in->height, s->vsub); int w[4] = { inlink->w, cw, cw, inlink->w }; int h[4] = { in->height, ch, ch, in->height }; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); const int depth = desc->comp[0].depth; const int pixsize = (depth+7)/8; out = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!out) { av_frame_free(&in); return AVERROR(ENOMEM); } av_frame_copy_props(out, in); for (plane = 0; plane < 4 && in->data[plane] && in->linesize[plane]; plane++) hblur(out->data[plane], out->linesize[plane], in ->data[plane], in ->linesize[plane], w[plane], h[plane], s->radius[plane], s->power[plane], s->temp, pixsize); for (plane = 0; plane < 4 && in->data[plane] && in->linesize[plane]; plane++) vblur(out->data[plane], out->linesize[plane], out->data[plane], out->linesize[plane], w[plane], h[plane], s->radius[plane], s->power[plane], s->temp, pixsize); av_frame_free(&in); return ff_filter_frame(outlink, out); }
static int filter_frame(AVFilterLink *inlink, AVFrame *in) { HQDN3DContext *hqdn3d = inlink->dst->priv; AVFilterLink *outlink = inlink->dst->outputs[0]; AVFrame *out; int direct, c; if (av_frame_is_writable(in)) { direct = 1; out = in; } else { direct = 0; out = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!out) { av_frame_free(&in); return AVERROR(ENOMEM); } av_frame_copy_props(out, in); out->width = outlink->w; out->height = outlink->h; } for (c = 0; c < 3; c++) { denoise(hqdn3d, in->data[c], out->data[c], hqdn3d->line, &hqdn3d->frame_prev[c], in->width >> (!!c * hqdn3d->hsub), in->height >> (!!c * hqdn3d->vsub), in->linesize[c], out->linesize[c], hqdn3d->coefs[c?2:0], hqdn3d->coefs[c?3:1]); } if (!direct) av_frame_free(&in); return ff_filter_frame(outlink, out); }
static int cudascale_scale(AVFilterContext *ctx, AVFrame *out, AVFrame *in) { CUDAScaleContext *s = ctx->priv; AVFrame *src = in; int ret; ret = scalecuda_resize(ctx, s->frame, src); if (ret < 0) return ret; src = s->frame; ret = av_hwframe_get_buffer(src->hw_frames_ctx, s->tmp_frame, 0); if (ret < 0) return ret; av_frame_move_ref(out, s->frame); av_frame_move_ref(s->frame, s->tmp_frame); ret = av_frame_copy_props(out, in); if (ret < 0) return ret; return 0; }
static int filter_frame(AVFilterLink *inlink, AVFrame *in) { AVFilterContext *ctx = inlink->dst; AVFilterLink *outlink = ctx->outputs[0]; ThreadData td; AVFrame *out; out = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!out) { av_frame_free(&in); return AVERROR(ENOMEM); } av_frame_copy_props(out, in); /* copy palette if required */ if (av_pix_fmt_desc_get(inlink->format)->flags & AV_PIX_FMT_FLAG_PAL) memcpy(out->data[1], in->data[1], AVPALETTE_SIZE); td.in = in, td.out = out; ctx->internal->execute(ctx, filter_slice, &td, NULL, FFMIN(outlink->h, ctx->graph->nb_threads)); av_frame_free(&in); return ff_filter_frame(outlink, out); }
static int filter_frame(AVFilterLink *inlink, AVFrame *in) { AVFilterContext *ctx = inlink->dst; OCVContext *ocv = ctx->priv; AVFilterLink *outlink= inlink->dst->outputs[0]; AVFrame *out; IplImage inimg, outimg; out = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!out) { av_frame_free(&in); return AVERROR(ENOMEM); } av_frame_copy_props(out, in); fill_iplimage_from_frame(&inimg , in , inlink->format); fill_iplimage_from_frame(&outimg, out, inlink->format); ocv->end_frame_filter(ctx, &inimg, &outimg); fill_frame_from_iplimage(out, &outimg, inlink->format); av_frame_free(&in); return ff_filter_frame(outlink, out); }
static int filter_frame(AVFilterLink *inlink, AVFrame *frame) { AVFilterContext *ctx = inlink->dst; AudioEchoContext *s = ctx->priv; AVFrame *out_frame; if (av_frame_is_writable(frame)) { out_frame = frame; } else { out_frame = ff_get_audio_buffer(inlink, frame->nb_samples); if (!out_frame) return AVERROR(ENOMEM); av_frame_copy_props(out_frame, frame); } s->echo_samples(s, s->delayptrs, frame->data, out_frame->data, frame->nb_samples, inlink->channels); if (frame != out_frame) av_frame_free(&frame); s->next_pts = frame->pts + av_rescale_q(frame->nb_samples, (AVRational){1, inlink->sample_rate}, inlink->time_base); return ff_filter_frame(ctx->outputs[0], out_frame); }
static int filter_frame(AVFilterLink *link, AVFrame *in) { DeshakeContext *deshake = link->dst->priv; AVFilterLink *outlink = link->dst->outputs[0]; AVFrame *out; Transform t = {{0},0}, orig = {{0},0}; float matrix_y[9], matrix_uv[9]; float alpha = 2.0 / deshake->refcount; char tmp[256]; int ret = 0; out = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!out) { av_frame_free(&in); return AVERROR(ENOMEM); } av_frame_copy_props(out, in); if (CONFIG_OPENCL && deshake->opencl) { ret = ff_opencl_deshake_process_inout_buf(link->dst,in, out); if (ret < 0) return ret; } if (deshake->cx < 0 || deshake->cy < 0 || deshake->cw < 0 || deshake->ch < 0) { // Find the most likely global motion for the current frame find_motion(deshake, (deshake->ref == NULL) ? in->data[0] : deshake->ref->data[0], in->data[0], link->w, link->h, in->linesize[0], &t); } else { uint8_t *src1 = (deshake->ref == NULL) ? in->data[0] : deshake->ref->data[0]; uint8_t *src2 = in->data[0]; deshake->cx = FFMIN(deshake->cx, link->w); deshake->cy = FFMIN(deshake->cy, link->h); if ((unsigned)deshake->cx + (unsigned)deshake->cw > link->w) deshake->cw = link->w - deshake->cx; if ((unsigned)deshake->cy + (unsigned)deshake->ch > link->h) deshake->ch = link->h - deshake->cy; // Quadword align right margin deshake->cw &= ~15; src1 += deshake->cy * in->linesize[0] + deshake->cx; src2 += deshake->cy * in->linesize[0] + deshake->cx; find_motion(deshake, src1, src2, deshake->cw, deshake->ch, in->linesize[0], &t); } // Copy transform so we can output it later to compare to the smoothed value orig.vector.x = t.vector.x; orig.vector.y = t.vector.y; orig.angle = t.angle; orig.zoom = t.zoom; // Generate a one-sided moving exponential average deshake->avg.vector.x = alpha * t.vector.x + (1.0 - alpha) * deshake->avg.vector.x; deshake->avg.vector.y = alpha * t.vector.y + (1.0 - alpha) * deshake->avg.vector.y; deshake->avg.angle = alpha * t.angle + (1.0 - alpha) * deshake->avg.angle; deshake->avg.zoom = alpha * t.zoom + (1.0 - alpha) * deshake->avg.zoom; // Remove the average from the current motion to detect the motion that // is not on purpose, just as jitter from bumping the camera t.vector.x -= deshake->avg.vector.x; t.vector.y -= deshake->avg.vector.y; t.angle -= deshake->avg.angle; t.zoom -= deshake->avg.zoom; // Invert the motion to undo it t.vector.x *= -1; t.vector.y *= -1; t.angle *= -1; // Write statistics to file if (deshake->fp) { snprintf(tmp, 256, "%f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f\n", orig.vector.x, deshake->avg.vector.x, t.vector.x, orig.vector.y, deshake->avg.vector.y, t.vector.y, orig.angle, deshake->avg.angle, t.angle, orig.zoom, deshake->avg.zoom, t.zoom); fwrite(tmp, sizeof(char), strlen(tmp), deshake->fp); } // Turn relative current frame motion into absolute by adding it to the // last absolute motion t.vector.x += deshake->last.vector.x; t.vector.y += deshake->last.vector.y; t.angle += deshake->last.angle; t.zoom += deshake->last.zoom; // Shrink motion by 10% to keep things centered in the camera frame t.vector.x *= 0.9; t.vector.y *= 0.9; t.angle *= 0.9; // Store the last absolute motion information deshake->last.vector.x = t.vector.x; deshake->last.vector.y = t.vector.y; deshake->last.angle = t.angle; deshake->last.zoom = t.zoom; // Generate a luma transformation matrix avfilter_get_matrix(t.vector.x, t.vector.y, t.angle, 1.0 + t.zoom / 100.0, matrix_y); // Generate a chroma transformation matrix avfilter_get_matrix(t.vector.x / (link->w / CHROMA_WIDTH(link)), t.vector.y / (link->h / CHROMA_HEIGHT(link)), t.angle, 1.0 + t.zoom / 100.0, matrix_uv); // Transform the luma and chroma planes ret = deshake->transform(link->dst, link->w, link->h, CHROMA_WIDTH(link), CHROMA_HEIGHT(link), matrix_y, matrix_uv, INTERPOLATE_BILINEAR, deshake->edge, in, out); // Cleanup the old reference frame av_frame_free(&deshake->ref); if (ret < 0) return ret; // Store the current frame as the reference frame for calculating the // motion of the next frame deshake->ref = in; return ff_filter_frame(outlink, out); }
int av_frame_ref(AVFrame *dst, const AVFrame *src) { int i, ret = 0; dst->format = src->format; dst->width = src->width; dst->height = src->height; dst->channels = src->channels; dst->channel_layout = src->channel_layout; dst->nb_samples = src->nb_samples; ret = av_frame_copy_props(dst, src); if (ret < 0) return ret; /* duplicate the frame data if it's not refcounted */ if (!src->buf[0]) { ret = av_frame_get_buffer(dst, 32); if (ret < 0) return ret; ret = av_frame_copy(dst, src); if (ret < 0) av_frame_unref(dst); return ret; } /* ref the buffers */ for (i = 0; i < FF_ARRAY_ELEMS(src->buf); i++) { if (!src->buf[i]) continue; dst->buf[i] = av_buffer_ref(src->buf[i]); if (!dst->buf[i]) { ret = AVERROR(ENOMEM); goto fail; } } if (src->extended_buf) { dst->extended_buf = av_mallocz_array(sizeof(*dst->extended_buf), src->nb_extended_buf); if (!dst->extended_buf) { ret = AVERROR(ENOMEM); goto fail; } dst->nb_extended_buf = src->nb_extended_buf; for (i = 0; i < src->nb_extended_buf; i++) { dst->extended_buf[i] = av_buffer_ref(src->extended_buf[i]); if (!dst->extended_buf[i]) { ret = AVERROR(ENOMEM); goto fail; } } } /* duplicate extended data */ if (src->extended_data != src->data) { int ch = src->channels; if (!ch) { ret = AVERROR(EINVAL); goto fail; } CHECK_CHANNELS_CONSISTENCY(src); dst->extended_data = av_malloc_array(sizeof(*dst->extended_data), ch); if (!dst->extended_data) { ret = AVERROR(ENOMEM); goto fail; } memcpy(dst->extended_data, src->extended_data, sizeof(*src->extended_data) * ch); } else dst->extended_data = dst->data; memcpy(dst->data, src->data, sizeof(src->data)); memcpy(dst->linesize, src->linesize, sizeof(src->linesize)); return 0; fail: av_frame_unref(dst); return ret; }
static int filter_frame(AVFilterLink *inlink, AVFrame *in) { AVFilterContext *ctx = inlink->dst; FlipContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; AVFrame *out; uint8_t *inrow, *outrow; int i, j, plane, step; out = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!out) { av_frame_free(&in); return AVERROR(ENOMEM); } av_frame_copy_props(out, in); /* copy palette if required */ if (av_pix_fmt_desc_get(inlink->format)->flags & AV_PIX_FMT_FLAG_PAL) memcpy(out->data[1], in->data[1], AVPALETTE_SIZE); for (plane = 0; plane < 4 && in->data[plane] && in->linesize[plane]; plane++) { const int width = (plane == 1 || plane == 2) ? FF_CEIL_RSHIFT(inlink->w, s->hsub) : inlink->w; const int height = (plane == 1 || plane == 2) ? FF_CEIL_RSHIFT(inlink->h, s->vsub) : inlink->h; step = s->max_step[plane]; outrow = out->data[plane]; inrow = in ->data[plane] + (width - 1) * step; for (i = 0; i < height; i++) { switch (step) { case 1: for (j = 0; j < width; j++) outrow[j] = inrow[-j]; break; case 2: { uint16_t *outrow16 = (uint16_t *)outrow; uint16_t * inrow16 = (uint16_t *) inrow; for (j = 0; j < width; j++) outrow16[j] = inrow16[-j]; } break; case 3: { uint8_t *in = inrow; uint8_t *out = outrow; for (j = 0; j < width; j++, out += 3, in -= 3) { int32_t v = AV_RB24(in); AV_WB24(out, v); } } break; case 4: { uint32_t *outrow32 = (uint32_t *)outrow; uint32_t * inrow32 = (uint32_t *) inrow; for (j = 0; j < width; j++) outrow32[j] = inrow32[-j]; } break; default: for (j = 0; j < width; j++) memcpy(outrow + j*step, inrow - j*step, step); } inrow += in ->linesize[plane]; outrow += out->linesize[plane]; } } av_frame_free(&in); return ff_filter_frame(outlink, out); }
static int filter_frame(AVFilterLink *inlink, AVFrame *picref) { AVFilterContext *ctx = inlink->dst; AVFilterLink *outlink = ctx->outputs[0]; TInterlaceContext *tinterlace = ctx->priv; AVFrame *cur, *next, *out; int field, tff, ret; av_frame_free(&tinterlace->cur); tinterlace->cur = tinterlace->next; tinterlace->next = picref; cur = tinterlace->cur; next = tinterlace->next; /* we need at least two frames */ if (!tinterlace->cur) return 0; switch (tinterlace->mode) { case MODE_MERGE: /* move the odd frame into the upper field of the new image, even into * the lower field, generating a double-height video at half framerate */ out = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!out) return AVERROR(ENOMEM); av_frame_copy_props(out, cur); out->height = outlink->h; out->interlaced_frame = 1; out->top_field_first = 1; out->sample_aspect_ratio = av_mul_q(cur->sample_aspect_ratio, av_make_q(2, 1)); /* write odd frame lines into the upper field of the new frame */ copy_picture_field(tinterlace, out->data, out->linesize, (const uint8_t **)cur->data, cur->linesize, inlink->format, inlink->w, inlink->h, FIELD_UPPER_AND_LOWER, 1, FIELD_UPPER, tinterlace->flags); /* write even frame lines into the lower field of the new frame */ copy_picture_field(tinterlace, out->data, out->linesize, (const uint8_t **)next->data, next->linesize, inlink->format, inlink->w, inlink->h, FIELD_UPPER_AND_LOWER, 1, FIELD_LOWER, tinterlace->flags); av_frame_free(&tinterlace->next); break; case MODE_DROP_ODD: /* only output even frames, odd frames are dropped; height unchanged, half framerate */ case MODE_DROP_EVEN: /* only output odd frames, even frames are dropped; height unchanged, half framerate */ out = av_frame_clone(tinterlace->mode == MODE_DROP_EVEN ? cur : next); if (!out) return AVERROR(ENOMEM); av_frame_free(&tinterlace->next); break; case MODE_PAD: /* expand each frame to double height, but pad alternate * lines with black; framerate unchanged */ out = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!out) return AVERROR(ENOMEM); av_frame_copy_props(out, cur); out->height = outlink->h; out->sample_aspect_ratio = av_mul_q(cur->sample_aspect_ratio, av_make_q(2, 1)); field = (1 + tinterlace->frame) & 1 ? FIELD_UPPER : FIELD_LOWER; /* copy upper and lower fields */ copy_picture_field(tinterlace, out->data, out->linesize, (const uint8_t **)cur->data, cur->linesize, inlink->format, inlink->w, inlink->h, FIELD_UPPER_AND_LOWER, 1, field, tinterlace->flags); /* pad with black the other field */ copy_picture_field(tinterlace, out->data, out->linesize, (const uint8_t **)tinterlace->black_data, tinterlace->black_linesize, inlink->format, inlink->w, inlink->h, FIELD_UPPER_AND_LOWER, 1, !field, tinterlace->flags); break; /* interleave upper/lower lines from odd frames with lower/upper lines from even frames, * halving the frame rate and preserving image height */ case MODE_INTERLEAVE_TOP: /* top field first */ case MODE_INTERLEAVE_BOTTOM: /* bottom field first */ tff = tinterlace->mode == MODE_INTERLEAVE_TOP; out = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!out) return AVERROR(ENOMEM); av_frame_copy_props(out, cur); out->interlaced_frame = 1; out->top_field_first = tff; /* copy upper/lower field from cur */ copy_picture_field(tinterlace, out->data, out->linesize, (const uint8_t **)cur->data, cur->linesize, inlink->format, inlink->w, inlink->h, tff ? FIELD_UPPER : FIELD_LOWER, 1, tff ? FIELD_UPPER : FIELD_LOWER, tinterlace->flags); /* copy lower/upper field from next */ copy_picture_field(tinterlace, out->data, out->linesize, (const uint8_t **)next->data, next->linesize, inlink->format, inlink->w, inlink->h, tff ? FIELD_LOWER : FIELD_UPPER, 1, tff ? FIELD_LOWER : FIELD_UPPER, tinterlace->flags); av_frame_free(&tinterlace->next); break; case MODE_INTERLACEX2: /* re-interlace preserving image height, double frame rate */ /* output current frame first */ out = av_frame_clone(cur); if (!out) return AVERROR(ENOMEM); out->interlaced_frame = 1; if (cur->pts != AV_NOPTS_VALUE) out->pts = cur->pts*2; out->pts = av_rescale_q(out->pts, tinterlace->preout_time_base, outlink->time_base); if ((ret = ff_filter_frame(outlink, out)) < 0) return ret; /* output mix of current and next frame */ tff = next->top_field_first; out = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!out) return AVERROR(ENOMEM); av_frame_copy_props(out, next); out->interlaced_frame = 1; out->top_field_first = !tff; if (next->pts != AV_NOPTS_VALUE && cur->pts != AV_NOPTS_VALUE) out->pts = cur->pts + next->pts; else out->pts = AV_NOPTS_VALUE; /* write current frame second field lines into the second field of the new frame */ copy_picture_field(tinterlace, out->data, out->linesize, (const uint8_t **)cur->data, cur->linesize, inlink->format, inlink->w, inlink->h, tff ? FIELD_LOWER : FIELD_UPPER, 1, tff ? FIELD_LOWER : FIELD_UPPER, tinterlace->flags); /* write next frame first field lines into the first field of the new frame */ copy_picture_field(tinterlace, out->data, out->linesize, (const uint8_t **)next->data, next->linesize, inlink->format, inlink->w, inlink->h, tff ? FIELD_UPPER : FIELD_LOWER, 1, tff ? FIELD_UPPER : FIELD_LOWER, tinterlace->flags); break; default: av_assert0(0); } out->pts = av_rescale_q(out->pts, tinterlace->preout_time_base, outlink->time_base); ret = ff_filter_frame(outlink, out); tinterlace->frame++; return ret; }
static int filter_frame(AVFilterLink *inlink, AVFrame *in) { unsigned x, y, direct = 0; AVFilterContext *ctx = inlink->dst; VignetteContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; AVFrame *out; if (av_frame_is_writable(in)) { direct = 1; out = in; } else { out = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!out) { av_frame_free(&in); return AVERROR(ENOMEM); } av_frame_copy_props(out, in); } if (s->eval_mode == EVAL_MODE_FRAME) update_context(s, inlink, in); if (s->desc->flags & AV_PIX_FMT_FLAG_RGB) { uint8_t *dst = out->data[0]; const uint8_t *src = in ->data[0]; const float *fmap = s->fmap; const int dst_linesize = out->linesize[0]; const int src_linesize = in ->linesize[0]; const int fmap_linesize = s->fmap_linesize; for (y = 0; y < inlink->h; y++) { uint8_t *dstp = dst; const uint8_t *srcp = src; for (x = 0; x < inlink->w; x++, dstp += 3, srcp += 3) { const float f = fmap[x]; dstp[0] = av_clip_uint8(srcp[0] * f + get_dither_value(s)); dstp[1] = av_clip_uint8(srcp[1] * f + get_dither_value(s)); dstp[2] = av_clip_uint8(srcp[2] * f + get_dither_value(s)); } dst += dst_linesize; src += src_linesize; fmap += fmap_linesize; } } else { int plane; for (plane = 0; plane < 4 && in->data[plane] && in->linesize[plane]; plane++) { uint8_t *dst = out->data[plane]; const uint8_t *src = in ->data[plane]; const float *fmap = s->fmap; const int dst_linesize = out->linesize[plane]; const int src_linesize = in ->linesize[plane]; const int fmap_linesize = s->fmap_linesize; const int chroma = plane == 1 || plane == 2; const int hsub = chroma ? s->desc->log2_chroma_w : 0; const int vsub = chroma ? s->desc->log2_chroma_h : 0; const int w = AV_CEIL_RSHIFT(inlink->w, hsub); const int h = AV_CEIL_RSHIFT(inlink->h, vsub); for (y = 0; y < h; y++) { uint8_t *dstp = dst; const uint8_t *srcp = src; for (x = 0; x < w; x++) { const double dv = get_dither_value(s); if (chroma) *dstp++ = av_clip_uint8(fmap[x << hsub] * (*srcp++ - 127) + 127 + dv); else *dstp++ = av_clip_uint8(fmap[x ] * *srcp++ + dv); } dst += dst_linesize; src += src_linesize; fmap += fmap_linesize << vsub; } } } if (!direct) av_frame_free(&in); return ff_filter_frame(outlink, out); }
static int filter_frame(AVFilterLink *inlink, AVFrame *in) { AVFilterContext *ctx = inlink->dst; ResampleContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; int ret; if (s->avr) { AVFrame *out; int delay, nb_samples; /* maximum possible samples lavr can output */ delay = avresample_get_delay(s->avr); nb_samples = avresample_get_out_samples(s->avr, in->nb_samples); out = ff_get_audio_buffer(outlink, nb_samples); if (!out) { ret = AVERROR(ENOMEM); goto fail; } ret = avresample_convert(s->avr, out->extended_data, out->linesize[0], nb_samples, in->extended_data, in->linesize[0], in->nb_samples); if (ret <= 0) { av_frame_free(&out); if (ret < 0) goto fail; } av_assert0(!avresample_available(s->avr)); if (s->next_pts == AV_NOPTS_VALUE) { if (in->pts == AV_NOPTS_VALUE) { av_log(ctx, AV_LOG_WARNING, "First timestamp is missing, " "assuming 0.\n"); s->next_pts = 0; } else s->next_pts = av_rescale_q(in->pts, inlink->time_base, outlink->time_base); } if (ret > 0) { out->nb_samples = ret; ret = av_frame_copy_props(out, in); if (ret < 0) { av_frame_free(&out); goto fail; } out->sample_rate = outlink->sample_rate; /* Only convert in->pts if there is a discontinuous jump. This ensures that out->pts tracks the number of samples actually output by the resampler in the absence of such a jump. Otherwise, the rounding in av_rescale_q() and av_rescale() causes off-by-1 errors. */ if (in->pts != AV_NOPTS_VALUE && in->pts != s->next_in_pts) { out->pts = av_rescale_q(in->pts, inlink->time_base, outlink->time_base) - av_rescale(delay, outlink->sample_rate, inlink->sample_rate); } else out->pts = s->next_pts; s->next_pts = out->pts + out->nb_samples; s->next_in_pts = in->pts + in->nb_samples; ret = ff_filter_frame(outlink, out); s->got_output = 1; } fail: av_frame_free(&in); } else { in->format = outlink->format; ret = ff_filter_frame(outlink, in); s->got_output = 1; } return ret; }
static int filter_frame(AVFilterLink *inlink, AVFrame *in) { AVFilterContext *ctx = inlink->dst; DCTdnoizContext *s = ctx->priv; AVFilterLink *outlink = inlink->dst->outputs[0]; int direct, plane; AVFrame *out; if (av_frame_is_writable(in)) { direct = 1; out = in; } else { direct = 0; out = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!out) { av_frame_free(&in); return AVERROR(ENOMEM); } av_frame_copy_props(out, in); } s->color_decorrelation(s->cbuf[0], s->p_linesize, in->data[0], in->linesize[0], s->pr_width, s->pr_height); for (plane = 0; plane < 3; plane++) { #ifdef IDE_COMPILE ThreadData td = { s->cbuf[0][plane], s->cbuf[1][plane], }; #else ThreadData td = { .src = s->cbuf[0][plane], .dst = s->cbuf[1][plane], }; #endif ctx->internal->execute(ctx, filter_slice, &td, NULL, s->nb_threads); } s->color_correlation(out->data[0], out->linesize[0], s->cbuf[1], s->p_linesize, s->pr_width, s->pr_height); if (!direct) { int y; uint8_t *dst = out->data[0]; const uint8_t *src = in->data[0]; const int dst_linesize = out->linesize[0]; const int src_linesize = in->linesize[0]; const int hpad = (inlink->w - s->pr_width) * 3; const int vpad = (inlink->h - s->pr_height); if (hpad) { uint8_t *dstp = dst + s->pr_width * 3; const uint8_t *srcp = src + s->pr_width * 3; for (y = 0; y < s->pr_height; y++) { memcpy(dstp, srcp, hpad); dstp += dst_linesize; srcp += src_linesize; } } if (vpad) { uint8_t *dstp = dst + s->pr_height * dst_linesize; const uint8_t *srcp = src + s->pr_height * src_linesize; for (y = 0; y < vpad; y++) { memcpy(dstp, srcp, inlink->w * 3); dstp += dst_linesize; srcp += src_linesize; } } av_frame_free(&in); } return ff_filter_frame(outlink, out); } static av_cold void uninit(AVFilterContext *ctx) { int i; DCTdnoizContext *s = ctx->priv; av_free(s->weights); for (i = 0; i < 2; i++) { av_free(s->cbuf[i][0]); av_free(s->cbuf[i][1]); av_free(s->cbuf[i][2]); } for (i = 0; i < s->nb_threads; i++) { av_free(s->slices[i]); av_expr_free(s->expr[i]); } }
static int atrim_filter_frame(AVFilterLink *inlink, AVFrame *frame) { AVFilterContext *ctx = inlink->dst; TrimContext *s = ctx->priv; int64_t start_sample, end_sample = frame->nb_samples; int64_t pts; int drop; /* drop everything if EOF has already been returned */ if (s->eof) { av_frame_free(&frame); return 0; } if (frame->pts != AV_NOPTS_VALUE) pts = av_rescale_q(frame->pts, inlink->time_base, (AVRational){ 1, inlink->sample_rate }); else pts = s->next_pts; s->next_pts = pts + frame->nb_samples; /* check if at least a part of the frame is after the start time */ if (s->start_sample < 0 && s->start_pts == AV_NOPTS_VALUE) { start_sample = 0; } else { drop = 1; start_sample = frame->nb_samples; if (s->start_sample >= 0 && s->nb_samples + frame->nb_samples > s->start_sample) { drop = 0; start_sample = FFMIN(start_sample, s->start_sample - s->nb_samples); } if (s->start_pts != AV_NOPTS_VALUE && pts != AV_NOPTS_VALUE && pts + frame->nb_samples > s->start_pts) { drop = 0; start_sample = FFMIN(start_sample, s->start_pts - pts); } if (drop) goto drop; } if (s->first_pts == AV_NOPTS_VALUE) s->first_pts = pts + start_sample; /* check if at least a part of the frame is before the end time */ if (s->end_sample == INT64_MAX && s->end_pts == AV_NOPTS_VALUE && !s->duration_tb) { end_sample = frame->nb_samples; } else { drop = 1; end_sample = 0; if (s->end_sample != INT64_MAX && s->nb_samples < s->end_sample) { drop = 0; end_sample = FFMAX(end_sample, s->end_sample - s->nb_samples); } if (s->end_pts != AV_NOPTS_VALUE && pts != AV_NOPTS_VALUE && pts < s->end_pts) { drop = 0; end_sample = FFMAX(end_sample, s->end_pts - pts); } if (s->duration_tb && pts - s->first_pts < s->duration_tb) { drop = 0; end_sample = FFMAX(end_sample, s->first_pts + s->duration_tb - pts); } if (drop) { s->eof = 1; goto drop; } } s->nb_samples += frame->nb_samples; start_sample = FFMAX(0, start_sample); end_sample = FFMIN(frame->nb_samples, end_sample); av_assert0(start_sample < end_sample); if (start_sample) { AVFrame *out = ff_get_audio_buffer(ctx->outputs[0], end_sample - start_sample); if (!out) { av_frame_free(&frame); return AVERROR(ENOMEM); } av_frame_copy_props(out, frame); av_samples_copy(out->extended_data, frame->extended_data, 0, start_sample, out->nb_samples, av_get_channel_layout_nb_channels(frame->channel_layout), frame->format); if (out->pts != AV_NOPTS_VALUE) out->pts += av_rescale_q(start_sample, (AVRational){ 1, out->sample_rate }, inlink->time_base); av_frame_free(&frame); frame = out; } else frame->nb_samples = end_sample; s->got_output = 1; return ff_filter_frame(ctx->outputs[0], frame); drop: s->nb_samples += frame->nb_samples; av_frame_free(&frame); return 0; }
static int ff_filter_frame_framed(AVFilterLink *link, AVFrame *frame) { int (*filter_frame)(AVFilterLink *, AVFrame *); AVFilterContext *dstctx = link->dst; AVFilterPad *dst = link->dstpad; AVFrame *out = NULL; int ret; AVFilterCommand *cmd= link->dst->command_queue; int64_t pts; if (link->closed) { av_frame_free(&frame); return AVERROR_EOF; } if (!(filter_frame = dst->filter_frame)) filter_frame = default_filter_frame; /* copy the frame if needed */ if (dst->needs_writable && !av_frame_is_writable(frame)) { av_log(link->dst, AV_LOG_DEBUG, "Copying data in avfilter.\n"); switch (link->type) { case AVMEDIA_TYPE_VIDEO: out = ff_get_video_buffer(link, link->w, link->h); break; case AVMEDIA_TYPE_AUDIO: out = ff_get_audio_buffer(link, frame->nb_samples); break; default: ret = AVERROR(EINVAL); goto fail; } if (!out) { ret = AVERROR(ENOMEM); goto fail; } ret = av_frame_copy_props(out, frame); if (ret < 0) goto fail; switch (link->type) { case AVMEDIA_TYPE_VIDEO: av_image_copy(out->data, out->linesize, (const uint8_t **)frame->data, frame->linesize, frame->format, frame->width, frame->height); break; case AVMEDIA_TYPE_AUDIO: av_samples_copy(out->extended_data, frame->extended_data, 0, 0, frame->nb_samples, av_get_channel_layout_nb_channels(frame->channel_layout), frame->format); break; default: ret = AVERROR(EINVAL); goto fail; } av_frame_free(&frame); } else out = frame; while(cmd && cmd->time <= out->pts * av_q2d(link->time_base)){ av_log(link->dst, AV_LOG_DEBUG, "Processing command time:%f command:%s arg:%s\n", cmd->time, cmd->command, cmd->arg); avfilter_process_command(link->dst, cmd->command, cmd->arg, 0, 0, cmd->flags); ff_command_queue_pop(link->dst); cmd= link->dst->command_queue; } pts = out->pts; if (dstctx->enable_str) { int64_t pos = av_frame_get_pkt_pos(out); dstctx->var_values[VAR_N] = link->frame_count; dstctx->var_values[VAR_T] = pts == AV_NOPTS_VALUE ? NAN : pts * av_q2d(link->time_base); dstctx->var_values[VAR_W] = link->w; dstctx->var_values[VAR_H] = link->h; dstctx->var_values[VAR_POS] = pos == -1 ? NAN : pos; dstctx->is_disabled = fabs(av_expr_eval(dstctx->enable, dstctx->var_values, NULL)) < 0.5; if (dstctx->is_disabled && (dstctx->filter->flags & AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC)) filter_frame = default_filter_frame; } ret = filter_frame(link, out); link->frame_count++; link->frame_requested = 0; ff_update_link_current_pts(link, pts); return ret; fail: av_frame_free(&out); av_frame_free(&frame); return ret; }
static int vda_retrieve_data(AVCodecContext *s, AVFrame *frame) { InputStream *ist = s->opaque; VDAContext *vda = ist->hwaccel_ctx; CVPixelBufferRef pixbuf = (CVPixelBufferRef)frame->data[3]; OSType pixel_format = CVPixelBufferGetPixelFormatType(pixbuf); CVReturn err; uint8_t *data[4] = { 0 }; int linesize[4] = { 0 }; int planes, ret, i; av_frame_unref(vda->tmp_frame); switch (pixel_format) { case kCVPixelFormatType_420YpCbCr8Planar: vda->tmp_frame->format = AV_PIX_FMT_YUV420P; break; case kCVPixelFormatType_422YpCbCr8: vda->tmp_frame->format = AV_PIX_FMT_UYVY422; break; default: av_log(NULL, AV_LOG_ERROR, "Unsupported pixel format: %u\n", pixel_format); return AVERROR(ENOSYS); } vda->tmp_frame->width = frame->width; vda->tmp_frame->height = frame->height; ret = av_frame_get_buffer(vda->tmp_frame, 32); if (ret < 0) return ret; err = CVPixelBufferLockBaseAddress(pixbuf, kCVPixelBufferLock_ReadOnly); if (err != kCVReturnSuccess) { av_log(NULL, AV_LOG_ERROR, "Error locking the pixel buffer.\n"); return AVERROR_UNKNOWN; } if (CVPixelBufferIsPlanar(pixbuf)) { planes = CVPixelBufferGetPlaneCount(pixbuf); for (i = 0; i < planes; i++) { data[i] = CVPixelBufferGetBaseAddressOfPlane(pixbuf, i); linesize[i] = CVPixelBufferGetBytesPerRowOfPlane(pixbuf, i); } } else { data[0] = CVPixelBufferGetBaseAddress(pixbuf); linesize[0] = CVPixelBufferGetBytesPerRow(pixbuf); } av_image_copy(vda->tmp_frame->data, vda->tmp_frame->linesize, data, linesize, vda->tmp_frame->format, frame->width, frame->height); ret = av_frame_copy_props(vda->tmp_frame, frame); CVPixelBufferUnlockBaseAddress(pixbuf, kCVPixelBufferLock_ReadOnly); if (ret < 0) return ret; av_frame_unref(frame); av_frame_move_ref(frame, vda->tmp_frame); return 0; }