Signed-off-by: Paul B Mahol <onemda@gmail.com>
Paul B Mahol authored on 2013/09/06 23:34:28... | ... |
@@ -80,21 +80,35 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) |
80 | 80 |
AVFilterContext *ctx = inlink->dst; |
81 | 81 |
FieldOrderContext *s = ctx->priv; |
82 | 82 |
AVFilterLink *outlink = ctx->outputs[0]; |
83 |
- int h, plane, line_step, line_size, line; |
|
84 |
- uint8_t *data; |
|
83 |
+ int h, plane, src_line_step, dst_line_step, line_size, line; |
|
84 |
+ uint8_t *dst, *src; |
|
85 |
+ AVFrame *out; |
|
85 | 86 |
|
86 | 87 |
if (!frame->interlaced_frame || |
87 | 88 |
frame->top_field_first == s->dst_tff) |
88 | 89 |
return ff_filter_frame(outlink, frame); |
89 | 90 |
|
91 |
+ if (av_frame_is_writable(frame)) { |
|
92 |
+ out = frame; |
|
93 |
+ } else { |
|
94 |
+ out = ff_get_video_buffer(outlink, outlink->w, outlink->h); |
|
95 |
+ if (!out) { |
|
96 |
+ av_frame_free(&frame); |
|
97 |
+ return AVERROR(ENOMEM); |
|
98 |
+ } |
|
99 |
+ av_frame_copy_props(out, frame); |
|
100 |
+ } |
|
101 |
+ |
|
90 | 102 |
av_dlog(ctx, |
91 | 103 |
"picture will move %s one line\n", |
92 | 104 |
s->dst_tff ? "up" : "down"); |
93 | 105 |
h = frame->height; |
94 | 106 |
for (plane = 0; plane < 4 && frame->data[plane] && frame->linesize[plane]; plane++) { |
95 |
- line_step = frame->linesize[plane]; |
|
107 |
+ dst_line_step = out->linesize[plane]; |
|
108 |
+ src_line_step = frame->linesize[plane]; |
|
96 | 109 |
line_size = s->line_size[plane]; |
97 |
- data = frame->data[plane]; |
|
110 |
+ dst = out->data[plane]; |
|
111 |
+ src = frame->data[plane]; |
|
98 | 112 |
if (s->dst_tff) { |
99 | 113 |
/** Move every line up one line, working from |
100 | 114 |
* the top to the bottom of the frame. |
... | ... |
@@ -103,11 +117,12 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) |
103 | 103 |
* penultimate line from that field. */ |
104 | 104 |
for (line = 0; line < h; line++) { |
105 | 105 |
if (1 + line < frame->height) { |
106 |
- memcpy(data, data + line_step, line_size); |
|
106 |
+ memcpy(dst, src + src_line_step, line_size); |
|
107 | 107 |
} else { |
108 |
- memcpy(data, data - line_step - line_step, line_size); |
|
108 |
+ memcpy(dst, src - 2 * src_line_step, line_size); |
|
109 | 109 |
} |
110 |
- data += line_step; |
|
110 |
+ dst += dst_line_step; |
|
111 |
+ src += src_line_step; |
|
111 | 112 |
} |
112 | 113 |
} else { |
113 | 114 |
/** Move every line down one line, working from |
... | ... |
@@ -115,20 +130,24 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) |
115 | 115 |
* The original bottom line is lost. |
116 | 116 |
* The new first line is created as a copy of the |
117 | 117 |
* second line from that field. */ |
118 |
- data += (h - 1) * line_step; |
|
118 |
+ dst += (h - 1) * dst_line_step; |
|
119 |
+ src += (h - 1) * src_line_step; |
|
119 | 120 |
for (line = h - 1; line >= 0 ; line--) { |
120 | 121 |
if (line > 0) { |
121 |
- memcpy(data, data - line_step, line_size); |
|
122 |
+ memcpy(dst, src - src_line_step, line_size); |
|
122 | 123 |
} else { |
123 |
- memcpy(data, data + line_step + line_step, line_size); |
|
124 |
+ memcpy(dst, src + 2 * src_line_step, line_size); |
|
124 | 125 |
} |
125 |
- data -= line_step; |
|
126 |
+ dst -= dst_line_step; |
|
127 |
+ src -= src_line_step; |
|
126 | 128 |
} |
127 | 129 |
} |
128 | 130 |
} |
129 |
- frame->top_field_first = s->dst_tff; |
|
131 |
+ out->top_field_first = s->dst_tff; |
|
130 | 132 |
|
131 |
- return ff_filter_frame(outlink, frame); |
|
133 |
+ if (frame != out) |
|
134 |
+ av_frame_free(&frame); |
|
135 |
+ return ff_filter_frame(outlink, out); |
|
132 | 136 |
} |
133 | 137 |
|
134 | 138 |
#define OFFSET(x) offsetof(FieldOrderContext, x) |
... | ... |
@@ -149,7 +168,6 @@ static const AVFilterPad avfilter_vf_fieldorder_inputs[] = { |
149 | 149 |
.type = AVMEDIA_TYPE_VIDEO, |
150 | 150 |
.config_props = config_input, |
151 | 151 |
.filter_frame = filter_frame, |
152 |
- .needs_writable = 1, |
|
153 | 152 |
}, |
154 | 153 |
{ NULL } |
155 | 154 |
}; |