/* * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
if (!frame->linesize[0]) { for (int i = 1; i <= align; i += i) {
ret = av_image_fill_linesizes(frame->linesize, frame->format,
FFALIGN(frame->width, i)); if (ret < 0) return ret; if (!(frame->linesize[0] & (align-1))) break;
}
for (int i = 0; i < 4 && frame->linesize[i]; i++)
frame->linesize[i] = FFALIGN(frame->linesize[i], align);
}
for (int i = 0; i < 4; i++)
linesizes[i] = frame->linesize[i];
for (int i = 1; i < 4; i++) { if (frame->data[i])
frame->data[i] += i * plane_padding;
frame->data[i] = (uint8_t *)FFALIGN((uintptr_t)frame->data[i], align);
}
staticint get_audio_buffer(AVFrame *frame, int align)
{ int planar = av_sample_fmt_is_planar(frame->format); int channels, planes;
size_t size; int ret;
channels = frame->ch_layout.nb_channels;
planes = planar ? channels : 1; if (!frame->linesize[0]) {
ret = av_samples_get_buffer_size(&frame->linesize[0], channels,
frame->nb_samples, frame->format,
align); if (ret < 0) return ret;
}
ret = frame_copy_props(dst, src, 0); if (ret < 0) goto fail;
ret = av_channel_layout_copy(&dst->ch_layout, &src->ch_layout); if (ret < 0) goto fail;
/* duplicate the frame data if it's not refcounted */ if (!src->buf[0]) {
ret = av_frame_get_buffer(dst, 0); if (ret < 0) goto fail;
ret = av_frame_copy(dst, src); if (ret < 0) goto fail;
return 0;
}
/* ref the buffers */ for (int 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_calloc(src->nb_extended_buf, sizeof(*dst->extended_buf)); if (!dst->extended_buf) {
ret = AVERROR(ENOMEM); goto fail;
}
dst->nb_extended_buf = src->nb_extended_buf;
for (int 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;
}
}
}
if (src->hw_frames_ctx) {
dst->hw_frames_ctx = av_buffer_ref(src->hw_frames_ctx); if (!dst->hw_frames_ctx) {
ret = AVERROR(ENOMEM); goto fail;
}
}
/* duplicate extended data */ if (src->extended_data != src->data) { int ch = dst->ch_layout.nb_channels;
int av_frame_replace(AVFrame *dst, const AVFrame *src)
{ int ret = 0;
if (dst == src) return AVERROR(EINVAL);
if (!src->buf[0]) {
av_frame_unref(dst);
/* duplicate the frame data if it's not refcounted */ if ( src->data[0] || src->data[1]
|| src->data[2] || src->data[3]) return av_frame_ref(dst, src);
ret = frame_copy_props(dst, src, 0); if (ret < 0) goto fail;
}
ret = av_channel_layout_copy(&dst->ch_layout, &src->ch_layout); if (ret < 0) goto fail;
frame_side_data_wipe(dst);
av_dict_free(&dst->metadata);
ret = frame_copy_props(dst, src, 0); if (ret < 0) goto fail;
/* replace the buffers */ for (int i = 0; i < FF_ARRAY_ELEMS(src->buf); i++) {
ret = av_buffer_replace(&dst->buf[i], src->buf[i]); if (ret < 0) goto fail;
}
if (src->extended_buf) { if (dst->nb_extended_buf != src->nb_extended_buf) { int nb_extended_buf = FFMIN(dst->nb_extended_buf, src->nb_extended_buf); void *tmp;
for (int i = nb_extended_buf; i < dst->nb_extended_buf; i++)
av_buffer_unref(&dst->extended_buf[i]);
tmp = av_realloc_array(dst->extended_buf, sizeof(*dst->extended_buf),
src->nb_extended_buf); if (!tmp) {
ret = AVERROR(ENOMEM); goto fail;
}
dst->extended_buf = tmp;
dst->nb_extended_buf = src->nb_extended_buf;
for (int i = 0; i < src->nb_extended_buf; i++) {
ret = av_buffer_replace(&dst->extended_buf[i], src->extended_buf[i]); if (ret < 0) goto fail;
}
} elseif (dst->extended_buf) { for (int i = 0; i < dst->nb_extended_buf; i++)
av_buffer_unref(&dst->extended_buf[i]);
av_freep(&dst->extended_buf);
}
ret = av_buffer_replace(&dst->hw_frames_ctx, src->hw_frames_ctx); if (ret < 0) goto fail;
if (dst->extended_data != dst->data)
av_freep(&dst->extended_data);
if (src->extended_data != src->data) { int ch = dst->ch_layout.nb_channels;
if (!ch) {
ret = AVERROR(EINVAL); goto fail;
}
if (ch > SIZE_MAX / sizeof(*dst->extended_data)) goto fail;
dst->extended_data = av_memdup(src->extended_data, sizeof(*dst->extended_data) * ch); if (!dst->extended_data) {
ret = AVERROR(ENOMEM); goto fail;
}
} else
dst->extended_data = dst->data;
if (av_frame_ref(ret, src) < 0)
av_frame_free(&ret);
return ret;
}
void av_frame_unref(AVFrame *frame)
{ if (!frame) return;
frame_side_data_wipe(frame);
for (int i = 0; i < FF_ARRAY_ELEMS(frame->buf); i++)
av_buffer_unref(&frame->buf[i]); for (int i = 0; i < frame->nb_extended_buf; i++)
av_buffer_unref(&frame->extended_buf[i]);
av_freep(&frame->extended_buf);
av_dict_free(&frame->metadata);
int av_frame_is_writable(AVFrame *frame)
{ int ret = 1;
/* assume non-refcounted frames are not writable */ if (!frame->buf[0]) return 0;
for (int i = 0; i < FF_ARRAY_ELEMS(frame->buf); i++) if (frame->buf[i])
ret &= !!av_buffer_is_writable(frame->buf[i]); for (int i = 0; i < frame->nb_extended_buf; i++)
ret &= !!av_buffer_is_writable(frame->extended_buf[i]);
return ret;
}
int av_frame_make_writable(AVFrame *frame)
{
AVFrame tmp; int ret;
if (frame->hw_frames_ctx)
ret = av_hwframe_get_buffer(frame->hw_frames_ctx, &tmp, 0); else
ret = av_frame_get_buffer(&tmp, 0); 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;
desc = av_pix_fmt_desc_get(frame->format); if (!desc) return AVERROR_BUG;
/* Apply just the right/bottom cropping for hwaccel formats. Bitstream * formats cannot be easily handled here either (and corresponding decoders * should not export any cropping anyway), so do the same for those as well.
* */ if (desc->flags & (AV_PIX_FMT_FLAG_BITSTREAM | AV_PIX_FMT_FLAG_HWACCEL)) {
frame->width -= frame->crop_right;
frame->height -= frame->crop_bottom;
frame->crop_right = 0;
frame->crop_bottom = 0; return 0;
}
/* calculate the offsets for each plane */
calc_cropping_offsets(offsets, frame, desc);
/* adjust the offsets to avoid breaking alignment */ if (!(flags & AV_FRAME_CROP_UNALIGNED)) { int log2_crop_align = frame->crop_left ? ff_ctz(frame->crop_left) : INT_MAX; int min_log2_align = INT_MAX;
for (int i = 0; frame->data[i]; i++) { int log2_align = offsets[i] ? ff_ctz(offsets[i]) : INT_MAX;
min_log2_align = FFMIN(log2_align, min_log2_align);
}
/* we assume, and it should always be true, that the data alignment is
* related to the cropping alignment by a constant power-of-2 factor */ if (log2_crop_align < min_log2_align) return AVERROR_BUG;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.