1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com> 3cabdff1aSopenharmony_ci * 4cabdff1aSopenharmony_ci * This file is part of FFmpeg. 5cabdff1aSopenharmony_ci * 6cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 7cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 8cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 9cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 10cabdff1aSopenharmony_ci * 11cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 12cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 13cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14cabdff1aSopenharmony_ci * Lesser General Public License for more details. 15cabdff1aSopenharmony_ci * 16cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 17cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 18cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19cabdff1aSopenharmony_ci */ 20cabdff1aSopenharmony_ci 21cabdff1aSopenharmony_ci#include <stdint.h> 22cabdff1aSopenharmony_ci#include <string.h> 23cabdff1aSopenharmony_ci 24cabdff1aSopenharmony_ci#include "libavutil/mem.h" 25cabdff1aSopenharmony_ci#include "audio_data.h" 26cabdff1aSopenharmony_ci 27cabdff1aSopenharmony_cistatic const AVClass audio_data_class = { 28cabdff1aSopenharmony_ci .class_name = "AudioData", 29cabdff1aSopenharmony_ci .item_name = av_default_item_name, 30cabdff1aSopenharmony_ci .version = LIBAVUTIL_VERSION_INT, 31cabdff1aSopenharmony_ci}; 32cabdff1aSopenharmony_ci 33cabdff1aSopenharmony_ci/* 34cabdff1aSopenharmony_ci * Calculate alignment for data pointers. 35cabdff1aSopenharmony_ci */ 36cabdff1aSopenharmony_cistatic void calc_ptr_alignment(AudioData *a) 37cabdff1aSopenharmony_ci{ 38cabdff1aSopenharmony_ci int p; 39cabdff1aSopenharmony_ci int min_align = 128; 40cabdff1aSopenharmony_ci 41cabdff1aSopenharmony_ci for (p = 0; p < a->planes; p++) { 42cabdff1aSopenharmony_ci int cur_align = 128; 43cabdff1aSopenharmony_ci while ((intptr_t)a->data[p] % cur_align) 44cabdff1aSopenharmony_ci cur_align >>= 1; 45cabdff1aSopenharmony_ci if (cur_align < min_align) 46cabdff1aSopenharmony_ci min_align = cur_align; 47cabdff1aSopenharmony_ci } 48cabdff1aSopenharmony_ci a->ptr_align = min_align; 49cabdff1aSopenharmony_ci} 50cabdff1aSopenharmony_ci 51cabdff1aSopenharmony_ciint ff_sample_fmt_is_planar(enum AVSampleFormat sample_fmt, int channels) 52cabdff1aSopenharmony_ci{ 53cabdff1aSopenharmony_ci if (channels == 1) 54cabdff1aSopenharmony_ci return 1; 55cabdff1aSopenharmony_ci else 56cabdff1aSopenharmony_ci return av_sample_fmt_is_planar(sample_fmt); 57cabdff1aSopenharmony_ci} 58cabdff1aSopenharmony_ci 59cabdff1aSopenharmony_ciint ff_audio_data_set_channels(AudioData *a, int channels) 60cabdff1aSopenharmony_ci{ 61cabdff1aSopenharmony_ci if (channels < 1 || channels > AVRESAMPLE_MAX_CHANNELS || 62cabdff1aSopenharmony_ci channels > a->allocated_channels) 63cabdff1aSopenharmony_ci return AVERROR(EINVAL); 64cabdff1aSopenharmony_ci 65cabdff1aSopenharmony_ci a->channels = channels; 66cabdff1aSopenharmony_ci a->planes = a->is_planar ? channels : 1; 67cabdff1aSopenharmony_ci 68cabdff1aSopenharmony_ci calc_ptr_alignment(a); 69cabdff1aSopenharmony_ci 70cabdff1aSopenharmony_ci return 0; 71cabdff1aSopenharmony_ci} 72cabdff1aSopenharmony_ci 73cabdff1aSopenharmony_ciint ff_audio_data_init(AudioData *a, uint8_t * const *src, int plane_size, 74cabdff1aSopenharmony_ci int channels, int nb_samples, 75cabdff1aSopenharmony_ci enum AVSampleFormat sample_fmt, int read_only, 76cabdff1aSopenharmony_ci const char *name) 77cabdff1aSopenharmony_ci{ 78cabdff1aSopenharmony_ci int p; 79cabdff1aSopenharmony_ci 80cabdff1aSopenharmony_ci memset(a, 0, sizeof(*a)); 81cabdff1aSopenharmony_ci a->class = &audio_data_class; 82cabdff1aSopenharmony_ci 83cabdff1aSopenharmony_ci if (channels < 1 || channels > AVRESAMPLE_MAX_CHANNELS) { 84cabdff1aSopenharmony_ci av_log(a, AV_LOG_ERROR, "invalid channel count: %d\n", channels); 85cabdff1aSopenharmony_ci return AVERROR(EINVAL); 86cabdff1aSopenharmony_ci } 87cabdff1aSopenharmony_ci 88cabdff1aSopenharmony_ci a->sample_size = av_get_bytes_per_sample(sample_fmt); 89cabdff1aSopenharmony_ci if (!a->sample_size) { 90cabdff1aSopenharmony_ci av_log(a, AV_LOG_ERROR, "invalid sample format\n"); 91cabdff1aSopenharmony_ci return AVERROR(EINVAL); 92cabdff1aSopenharmony_ci } 93cabdff1aSopenharmony_ci a->is_planar = ff_sample_fmt_is_planar(sample_fmt, channels); 94cabdff1aSopenharmony_ci a->planes = a->is_planar ? channels : 1; 95cabdff1aSopenharmony_ci a->stride = a->sample_size * (a->is_planar ? 1 : channels); 96cabdff1aSopenharmony_ci 97cabdff1aSopenharmony_ci for (p = 0; p < (a->is_planar ? channels : 1); p++) { 98cabdff1aSopenharmony_ci if (!src[p]) { 99cabdff1aSopenharmony_ci av_log(a, AV_LOG_ERROR, "invalid NULL pointer for src[%d]\n", p); 100cabdff1aSopenharmony_ci return AVERROR(EINVAL); 101cabdff1aSopenharmony_ci } 102cabdff1aSopenharmony_ci a->data[p] = src[p]; 103cabdff1aSopenharmony_ci } 104cabdff1aSopenharmony_ci a->allocated_samples = nb_samples * !read_only; 105cabdff1aSopenharmony_ci a->nb_samples = nb_samples; 106cabdff1aSopenharmony_ci a->sample_fmt = sample_fmt; 107cabdff1aSopenharmony_ci a->channels = channels; 108cabdff1aSopenharmony_ci a->allocated_channels = channels; 109cabdff1aSopenharmony_ci a->read_only = read_only; 110cabdff1aSopenharmony_ci a->allow_realloc = 0; 111cabdff1aSopenharmony_ci a->name = name ? name : "{no name}"; 112cabdff1aSopenharmony_ci 113cabdff1aSopenharmony_ci calc_ptr_alignment(a); 114cabdff1aSopenharmony_ci a->samples_align = plane_size / a->stride; 115cabdff1aSopenharmony_ci 116cabdff1aSopenharmony_ci return 0; 117cabdff1aSopenharmony_ci} 118cabdff1aSopenharmony_ci 119cabdff1aSopenharmony_ciAudioData *ff_audio_data_alloc(int channels, int nb_samples, 120cabdff1aSopenharmony_ci enum AVSampleFormat sample_fmt, const char *name) 121cabdff1aSopenharmony_ci{ 122cabdff1aSopenharmony_ci AudioData *a; 123cabdff1aSopenharmony_ci int ret; 124cabdff1aSopenharmony_ci 125cabdff1aSopenharmony_ci if (channels < 1 || channels > AVRESAMPLE_MAX_CHANNELS) 126cabdff1aSopenharmony_ci return NULL; 127cabdff1aSopenharmony_ci 128cabdff1aSopenharmony_ci a = av_mallocz(sizeof(*a)); 129cabdff1aSopenharmony_ci if (!a) 130cabdff1aSopenharmony_ci return NULL; 131cabdff1aSopenharmony_ci 132cabdff1aSopenharmony_ci a->sample_size = av_get_bytes_per_sample(sample_fmt); 133cabdff1aSopenharmony_ci if (!a->sample_size) { 134cabdff1aSopenharmony_ci av_free(a); 135cabdff1aSopenharmony_ci return NULL; 136cabdff1aSopenharmony_ci } 137cabdff1aSopenharmony_ci a->is_planar = ff_sample_fmt_is_planar(sample_fmt, channels); 138cabdff1aSopenharmony_ci a->planes = a->is_planar ? channels : 1; 139cabdff1aSopenharmony_ci a->stride = a->sample_size * (a->is_planar ? 1 : channels); 140cabdff1aSopenharmony_ci 141cabdff1aSopenharmony_ci a->class = &audio_data_class; 142cabdff1aSopenharmony_ci a->sample_fmt = sample_fmt; 143cabdff1aSopenharmony_ci a->channels = channels; 144cabdff1aSopenharmony_ci a->allocated_channels = channels; 145cabdff1aSopenharmony_ci a->read_only = 0; 146cabdff1aSopenharmony_ci a->allow_realloc = 1; 147cabdff1aSopenharmony_ci a->name = name ? name : "{no name}"; 148cabdff1aSopenharmony_ci 149cabdff1aSopenharmony_ci if (nb_samples > 0) { 150cabdff1aSopenharmony_ci ret = ff_audio_data_realloc(a, nb_samples); 151cabdff1aSopenharmony_ci if (ret < 0) { 152cabdff1aSopenharmony_ci av_free(a); 153cabdff1aSopenharmony_ci return NULL; 154cabdff1aSopenharmony_ci } 155cabdff1aSopenharmony_ci return a; 156cabdff1aSopenharmony_ci } else { 157cabdff1aSopenharmony_ci calc_ptr_alignment(a); 158cabdff1aSopenharmony_ci return a; 159cabdff1aSopenharmony_ci } 160cabdff1aSopenharmony_ci} 161cabdff1aSopenharmony_ci 162cabdff1aSopenharmony_ciint ff_audio_data_realloc(AudioData *a, int nb_samples) 163cabdff1aSopenharmony_ci{ 164cabdff1aSopenharmony_ci int ret, new_buf_size, plane_size, p; 165cabdff1aSopenharmony_ci 166cabdff1aSopenharmony_ci /* check if buffer is already large enough */ 167cabdff1aSopenharmony_ci if (a->allocated_samples >= nb_samples) 168cabdff1aSopenharmony_ci return 0; 169cabdff1aSopenharmony_ci 170cabdff1aSopenharmony_ci /* validate that the output is not read-only and realloc is allowed */ 171cabdff1aSopenharmony_ci if (a->read_only || !a->allow_realloc) 172cabdff1aSopenharmony_ci return AVERROR(EINVAL); 173cabdff1aSopenharmony_ci 174cabdff1aSopenharmony_ci new_buf_size = av_samples_get_buffer_size(&plane_size, 175cabdff1aSopenharmony_ci a->allocated_channels, nb_samples, 176cabdff1aSopenharmony_ci a->sample_fmt, 0); 177cabdff1aSopenharmony_ci if (new_buf_size < 0) 178cabdff1aSopenharmony_ci return new_buf_size; 179cabdff1aSopenharmony_ci 180cabdff1aSopenharmony_ci /* if there is already data in the buffer and the sample format is planar, 181cabdff1aSopenharmony_ci allocate a new buffer and copy the data, otherwise just realloc the 182cabdff1aSopenharmony_ci internal buffer and set new data pointers */ 183cabdff1aSopenharmony_ci if (a->nb_samples > 0 && a->is_planar) { 184cabdff1aSopenharmony_ci uint8_t *new_data[AVRESAMPLE_MAX_CHANNELS] = { NULL }; 185cabdff1aSopenharmony_ci 186cabdff1aSopenharmony_ci ret = av_samples_alloc(new_data, &plane_size, a->allocated_channels, 187cabdff1aSopenharmony_ci nb_samples, a->sample_fmt, 0); 188cabdff1aSopenharmony_ci if (ret < 0) 189cabdff1aSopenharmony_ci return ret; 190cabdff1aSopenharmony_ci 191cabdff1aSopenharmony_ci for (p = 0; p < a->planes; p++) 192cabdff1aSopenharmony_ci memcpy(new_data[p], a->data[p], a->nb_samples * a->stride); 193cabdff1aSopenharmony_ci 194cabdff1aSopenharmony_ci av_freep(&a->buffer); 195cabdff1aSopenharmony_ci memcpy(a->data, new_data, sizeof(new_data)); 196cabdff1aSopenharmony_ci a->buffer = a->data[0]; 197cabdff1aSopenharmony_ci } else { 198cabdff1aSopenharmony_ci av_freep(&a->buffer); 199cabdff1aSopenharmony_ci a->buffer = av_malloc(new_buf_size); 200cabdff1aSopenharmony_ci if (!a->buffer) 201cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 202cabdff1aSopenharmony_ci ret = av_samples_fill_arrays(a->data, &plane_size, a->buffer, 203cabdff1aSopenharmony_ci a->allocated_channels, nb_samples, 204cabdff1aSopenharmony_ci a->sample_fmt, 0); 205cabdff1aSopenharmony_ci if (ret < 0) 206cabdff1aSopenharmony_ci return ret; 207cabdff1aSopenharmony_ci } 208cabdff1aSopenharmony_ci a->buffer_size = new_buf_size; 209cabdff1aSopenharmony_ci a->allocated_samples = nb_samples; 210cabdff1aSopenharmony_ci 211cabdff1aSopenharmony_ci calc_ptr_alignment(a); 212cabdff1aSopenharmony_ci a->samples_align = plane_size / a->stride; 213cabdff1aSopenharmony_ci 214cabdff1aSopenharmony_ci return 0; 215cabdff1aSopenharmony_ci} 216cabdff1aSopenharmony_ci 217cabdff1aSopenharmony_civoid ff_audio_data_free(AudioData **a) 218cabdff1aSopenharmony_ci{ 219cabdff1aSopenharmony_ci if (!*a) 220cabdff1aSopenharmony_ci return; 221cabdff1aSopenharmony_ci av_free((*a)->buffer); 222cabdff1aSopenharmony_ci av_freep(a); 223cabdff1aSopenharmony_ci} 224cabdff1aSopenharmony_ci 225cabdff1aSopenharmony_ciint ff_audio_data_copy(AudioData *dst, AudioData *src, ChannelMapInfo *map) 226cabdff1aSopenharmony_ci{ 227cabdff1aSopenharmony_ci int ret, p; 228cabdff1aSopenharmony_ci 229cabdff1aSopenharmony_ci /* validate input/output compatibility */ 230cabdff1aSopenharmony_ci if (dst->sample_fmt != src->sample_fmt || dst->channels < src->channels) 231cabdff1aSopenharmony_ci return AVERROR(EINVAL); 232cabdff1aSopenharmony_ci 233cabdff1aSopenharmony_ci if (map && !src->is_planar) { 234cabdff1aSopenharmony_ci av_log(src, AV_LOG_ERROR, "cannot remap packed format during copy\n"); 235cabdff1aSopenharmony_ci return AVERROR(EINVAL); 236cabdff1aSopenharmony_ci } 237cabdff1aSopenharmony_ci 238cabdff1aSopenharmony_ci /* if the input is empty, just empty the output */ 239cabdff1aSopenharmony_ci if (!src->nb_samples) { 240cabdff1aSopenharmony_ci dst->nb_samples = 0; 241cabdff1aSopenharmony_ci return 0; 242cabdff1aSopenharmony_ci } 243cabdff1aSopenharmony_ci 244cabdff1aSopenharmony_ci /* reallocate output if necessary */ 245cabdff1aSopenharmony_ci ret = ff_audio_data_realloc(dst, src->nb_samples); 246cabdff1aSopenharmony_ci if (ret < 0) 247cabdff1aSopenharmony_ci return ret; 248cabdff1aSopenharmony_ci 249cabdff1aSopenharmony_ci /* copy data */ 250cabdff1aSopenharmony_ci if (map) { 251cabdff1aSopenharmony_ci if (map->do_remap) { 252cabdff1aSopenharmony_ci for (p = 0; p < src->planes; p++) { 253cabdff1aSopenharmony_ci if (map->channel_map[p] >= 0) 254cabdff1aSopenharmony_ci memcpy(dst->data[p], src->data[map->channel_map[p]], 255cabdff1aSopenharmony_ci src->nb_samples * src->stride); 256cabdff1aSopenharmony_ci } 257cabdff1aSopenharmony_ci } 258cabdff1aSopenharmony_ci if (map->do_copy || map->do_zero) { 259cabdff1aSopenharmony_ci for (p = 0; p < src->planes; p++) { 260cabdff1aSopenharmony_ci if (map->channel_copy[p]) 261cabdff1aSopenharmony_ci memcpy(dst->data[p], dst->data[map->channel_copy[p]], 262cabdff1aSopenharmony_ci src->nb_samples * src->stride); 263cabdff1aSopenharmony_ci else if (map->channel_zero[p]) 264cabdff1aSopenharmony_ci av_samples_set_silence(&dst->data[p], 0, src->nb_samples, 265cabdff1aSopenharmony_ci 1, dst->sample_fmt); 266cabdff1aSopenharmony_ci } 267cabdff1aSopenharmony_ci } 268cabdff1aSopenharmony_ci } else { 269cabdff1aSopenharmony_ci for (p = 0; p < src->planes; p++) 270cabdff1aSopenharmony_ci memcpy(dst->data[p], src->data[p], src->nb_samples * src->stride); 271cabdff1aSopenharmony_ci } 272cabdff1aSopenharmony_ci 273cabdff1aSopenharmony_ci dst->nb_samples = src->nb_samples; 274cabdff1aSopenharmony_ci 275cabdff1aSopenharmony_ci return 0; 276cabdff1aSopenharmony_ci} 277cabdff1aSopenharmony_ci 278cabdff1aSopenharmony_ciint ff_audio_data_combine(AudioData *dst, int dst_offset, AudioData *src, 279cabdff1aSopenharmony_ci int src_offset, int nb_samples) 280cabdff1aSopenharmony_ci{ 281cabdff1aSopenharmony_ci int ret, p, dst_offset2, dst_move_size; 282cabdff1aSopenharmony_ci 283cabdff1aSopenharmony_ci /* validate input/output compatibility */ 284cabdff1aSopenharmony_ci if (dst->sample_fmt != src->sample_fmt || dst->channels != src->channels) { 285cabdff1aSopenharmony_ci av_log(src, AV_LOG_ERROR, "sample format mismatch\n"); 286cabdff1aSopenharmony_ci return AVERROR(EINVAL); 287cabdff1aSopenharmony_ci } 288cabdff1aSopenharmony_ci 289cabdff1aSopenharmony_ci /* validate offsets are within the buffer bounds */ 290cabdff1aSopenharmony_ci if (dst_offset < 0 || dst_offset > dst->nb_samples || 291cabdff1aSopenharmony_ci src_offset < 0 || src_offset > src->nb_samples) { 292cabdff1aSopenharmony_ci av_log(src, AV_LOG_ERROR, "offset out-of-bounds: src=%d dst=%d\n", 293cabdff1aSopenharmony_ci src_offset, dst_offset); 294cabdff1aSopenharmony_ci return AVERROR(EINVAL); 295cabdff1aSopenharmony_ci } 296cabdff1aSopenharmony_ci 297cabdff1aSopenharmony_ci /* check offsets and sizes to see if we can just do nothing and return */ 298cabdff1aSopenharmony_ci if (nb_samples > src->nb_samples - src_offset) 299cabdff1aSopenharmony_ci nb_samples = src->nb_samples - src_offset; 300cabdff1aSopenharmony_ci if (nb_samples <= 0) 301cabdff1aSopenharmony_ci return 0; 302cabdff1aSopenharmony_ci 303cabdff1aSopenharmony_ci /* validate that the output is not read-only */ 304cabdff1aSopenharmony_ci if (dst->read_only) { 305cabdff1aSopenharmony_ci av_log(dst, AV_LOG_ERROR, "dst is read-only\n"); 306cabdff1aSopenharmony_ci return AVERROR(EINVAL); 307cabdff1aSopenharmony_ci } 308cabdff1aSopenharmony_ci 309cabdff1aSopenharmony_ci /* reallocate output if necessary */ 310cabdff1aSopenharmony_ci ret = ff_audio_data_realloc(dst, dst->nb_samples + nb_samples); 311cabdff1aSopenharmony_ci if (ret < 0) { 312cabdff1aSopenharmony_ci av_log(dst, AV_LOG_ERROR, "error reallocating dst\n"); 313cabdff1aSopenharmony_ci return ret; 314cabdff1aSopenharmony_ci } 315cabdff1aSopenharmony_ci 316cabdff1aSopenharmony_ci dst_offset2 = dst_offset + nb_samples; 317cabdff1aSopenharmony_ci dst_move_size = dst->nb_samples - dst_offset; 318cabdff1aSopenharmony_ci 319cabdff1aSopenharmony_ci for (p = 0; p < src->planes; p++) { 320cabdff1aSopenharmony_ci if (dst_move_size > 0) { 321cabdff1aSopenharmony_ci memmove(dst->data[p] + dst_offset2 * dst->stride, 322cabdff1aSopenharmony_ci dst->data[p] + dst_offset * dst->stride, 323cabdff1aSopenharmony_ci dst_move_size * dst->stride); 324cabdff1aSopenharmony_ci } 325cabdff1aSopenharmony_ci memcpy(dst->data[p] + dst_offset * dst->stride, 326cabdff1aSopenharmony_ci src->data[p] + src_offset * src->stride, 327cabdff1aSopenharmony_ci nb_samples * src->stride); 328cabdff1aSopenharmony_ci } 329cabdff1aSopenharmony_ci dst->nb_samples += nb_samples; 330cabdff1aSopenharmony_ci 331cabdff1aSopenharmony_ci return 0; 332cabdff1aSopenharmony_ci} 333cabdff1aSopenharmony_ci 334cabdff1aSopenharmony_civoid ff_audio_data_drain(AudioData *a, int nb_samples) 335cabdff1aSopenharmony_ci{ 336cabdff1aSopenharmony_ci if (a->nb_samples <= nb_samples) { 337cabdff1aSopenharmony_ci /* drain the whole buffer */ 338cabdff1aSopenharmony_ci a->nb_samples = 0; 339cabdff1aSopenharmony_ci } else { 340cabdff1aSopenharmony_ci int p; 341cabdff1aSopenharmony_ci int move_offset = a->stride * nb_samples; 342cabdff1aSopenharmony_ci int move_size = a->stride * (a->nb_samples - nb_samples); 343cabdff1aSopenharmony_ci 344cabdff1aSopenharmony_ci for (p = 0; p < a->planes; p++) 345cabdff1aSopenharmony_ci memmove(a->data[p], a->data[p] + move_offset, move_size); 346cabdff1aSopenharmony_ci 347cabdff1aSopenharmony_ci a->nb_samples -= nb_samples; 348cabdff1aSopenharmony_ci } 349cabdff1aSopenharmony_ci} 350cabdff1aSopenharmony_ci 351cabdff1aSopenharmony_ciint ff_audio_data_add_to_fifo(AVAudioFifo *af, AudioData *a, int offset, 352cabdff1aSopenharmony_ci int nb_samples) 353cabdff1aSopenharmony_ci{ 354cabdff1aSopenharmony_ci uint8_t *offset_data[AVRESAMPLE_MAX_CHANNELS]; 355cabdff1aSopenharmony_ci int offset_size, p; 356cabdff1aSopenharmony_ci 357cabdff1aSopenharmony_ci if (offset >= a->nb_samples) 358cabdff1aSopenharmony_ci return 0; 359cabdff1aSopenharmony_ci offset_size = offset * a->stride; 360cabdff1aSopenharmony_ci for (p = 0; p < a->planes; p++) 361cabdff1aSopenharmony_ci offset_data[p] = a->data[p] + offset_size; 362cabdff1aSopenharmony_ci 363cabdff1aSopenharmony_ci return av_audio_fifo_write(af, (void **)offset_data, nb_samples); 364cabdff1aSopenharmony_ci} 365cabdff1aSopenharmony_ci 366cabdff1aSopenharmony_ciint ff_audio_data_read_from_fifo(AVAudioFifo *af, AudioData *a, int nb_samples) 367cabdff1aSopenharmony_ci{ 368cabdff1aSopenharmony_ci int ret; 369cabdff1aSopenharmony_ci 370cabdff1aSopenharmony_ci if (a->read_only) 371cabdff1aSopenharmony_ci return AVERROR(EINVAL); 372cabdff1aSopenharmony_ci 373cabdff1aSopenharmony_ci ret = ff_audio_data_realloc(a, nb_samples); 374cabdff1aSopenharmony_ci if (ret < 0) 375cabdff1aSopenharmony_ci return ret; 376cabdff1aSopenharmony_ci 377cabdff1aSopenharmony_ci ret = av_audio_fifo_read(af, (void **)a->data, nb_samples); 378cabdff1aSopenharmony_ci if (ret >= 0) 379cabdff1aSopenharmony_ci a->nb_samples = ret; 380cabdff1aSopenharmony_ci return ret; 381cabdff1aSopenharmony_ci} 382