00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 #include <stdint.h>
00022 #include <string.h>
00023 
00024 #include "libavutil/mem.h"
00025 #include "audio_data.h"
00026 
00027 static const AVClass audio_data_class = {
00028     .class_name = "AudioData",
00029     .item_name  = av_default_item_name,
00030     .version    = LIBAVUTIL_VERSION_INT,
00031 };
00032 
00033 
00034 
00035 
00036 static void calc_ptr_alignment(AudioData *a)
00037 {
00038     int p;
00039     int min_align = 128;
00040 
00041     for (p = 0; p < a->planes; p++) {
00042         int cur_align = 128;
00043         while ((intptr_t)a->data[p] % cur_align)
00044             cur_align >>= 1;
00045         if (cur_align < min_align)
00046             min_align = cur_align;
00047     }
00048     a->ptr_align = min_align;
00049 }
00050 
00051 int ff_audio_data_set_channels(AudioData *a, int channels)
00052 {
00053     if (channels < 1 || channels > AVRESAMPLE_MAX_CHANNELS ||
00054         channels > a->allocated_channels)
00055         return AVERROR(EINVAL);
00056 
00057     a->channels  = channels;
00058     a->planes    = a->is_planar ? channels : 1;
00059 
00060     calc_ptr_alignment(a);
00061 
00062     return 0;
00063 }
00064 
00065 int ff_audio_data_init(AudioData *a, void **src, int plane_size, int channels,
00066                        int nb_samples, enum AVSampleFormat sample_fmt,
00067                        int read_only, const char *name)
00068 {
00069     int p;
00070 
00071     memset(a, 0, sizeof(*a));
00072     a->class = &audio_data_class;
00073 
00074     if (channels < 1 || channels > AVRESAMPLE_MAX_CHANNELS) {
00075         av_log(a, AV_LOG_ERROR, "invalid channel count: %d\n", channels);
00076         return AVERROR(EINVAL);
00077     }
00078 
00079     a->sample_size = av_get_bytes_per_sample(sample_fmt);
00080     if (!a->sample_size) {
00081         av_log(a, AV_LOG_ERROR, "invalid sample format\n");
00082         return AVERROR(EINVAL);
00083     }
00084     a->is_planar = av_sample_fmt_is_planar(sample_fmt);
00085     a->planes    = a->is_planar ? channels : 1;
00086     a->stride    = a->sample_size * (a->is_planar ? 1 : channels);
00087 
00088     for (p = 0; p < (a->is_planar ? channels : 1); p++) {
00089         if (!src[p]) {
00090             av_log(a, AV_LOG_ERROR, "invalid NULL pointer for src[%d]\n", p);
00091             return AVERROR(EINVAL);
00092         }
00093         a->data[p] = src[p];
00094     }
00095     a->allocated_samples  = nb_samples * !read_only;
00096     a->nb_samples         = nb_samples;
00097     a->sample_fmt         = sample_fmt;
00098     a->channels           = channels;
00099     a->allocated_channels = channels;
00100     a->read_only          = read_only;
00101     a->allow_realloc      = 0;
00102     a->name               = name ? name : "{no name}";
00103 
00104     calc_ptr_alignment(a);
00105     a->samples_align = plane_size / a->stride;
00106 
00107     return 0;
00108 }
00109 
00110 AudioData *ff_audio_data_alloc(int channels, int nb_samples,
00111                                enum AVSampleFormat sample_fmt, const char *name)
00112 {
00113     AudioData *a;
00114     int ret;
00115 
00116     if (channels < 1 || channels > AVRESAMPLE_MAX_CHANNELS)
00117         return NULL;
00118 
00119     a = av_mallocz(sizeof(*a));
00120     if (!a)
00121         return NULL;
00122 
00123     a->sample_size = av_get_bytes_per_sample(sample_fmt);
00124     if (!a->sample_size) {
00125         av_free(a);
00126         return NULL;
00127     }
00128     a->is_planar = av_sample_fmt_is_planar(sample_fmt);
00129     a->planes    = a->is_planar ? channels : 1;
00130     a->stride    = a->sample_size * (a->is_planar ? 1 : channels);
00131 
00132     a->class              = &audio_data_class;
00133     a->sample_fmt         = sample_fmt;
00134     a->channels           = channels;
00135     a->allocated_channels = channels;
00136     a->read_only          = 0;
00137     a->allow_realloc      = 1;
00138     a->name               = name ? name : "{no name}";
00139 
00140     if (nb_samples > 0) {
00141         ret = ff_audio_data_realloc(a, nb_samples);
00142         if (ret < 0) {
00143             av_free(a);
00144             return NULL;
00145         }
00146         return a;
00147     } else {
00148         calc_ptr_alignment(a);
00149         return a;
00150     }
00151 }
00152 
00153 int ff_audio_data_realloc(AudioData *a, int nb_samples)
00154 {
00155     int ret, new_buf_size, plane_size, p;
00156 
00157     
00158     if (a->allocated_samples >= nb_samples)
00159         return 0;
00160 
00161     
00162     if (a->read_only || !a->allow_realloc)
00163         return AVERROR(EINVAL);
00164 
00165     new_buf_size = av_samples_get_buffer_size(&plane_size,
00166                                               a->allocated_channels, nb_samples,
00167                                               a->sample_fmt, 0);
00168     if (new_buf_size < 0)
00169         return new_buf_size;
00170 
00171     
00172 
00173 
00174     if (a->nb_samples > 0 && a->is_planar) {
00175         uint8_t *new_data[AVRESAMPLE_MAX_CHANNELS] = { NULL };
00176 
00177         ret = av_samples_alloc(new_data, &plane_size, a->allocated_channels,
00178                                nb_samples, a->sample_fmt, 0);
00179         if (ret < 0)
00180             return ret;
00181 
00182         for (p = 0; p < a->planes; p++)
00183             memcpy(new_data[p], a->data[p], a->nb_samples * a->stride);
00184 
00185         av_freep(&a->buffer);
00186         memcpy(a->data, new_data, sizeof(new_data));
00187         a->buffer = a->data[0];
00188     } else {
00189         av_freep(&a->buffer);
00190         a->buffer = av_malloc(new_buf_size);
00191         if (!a->buffer)
00192             return AVERROR(ENOMEM);
00193         ret = av_samples_fill_arrays(a->data, &plane_size, a->buffer,
00194                                      a->allocated_channels, nb_samples,
00195                                      a->sample_fmt, 0);
00196         if (ret < 0)
00197             return ret;
00198     }
00199     a->buffer_size       = new_buf_size;
00200     a->allocated_samples = nb_samples;
00201 
00202     calc_ptr_alignment(a);
00203     a->samples_align = plane_size / a->stride;
00204 
00205     return 0;
00206 }
00207 
00208 void ff_audio_data_free(AudioData **a)
00209 {
00210     if (!*a)
00211         return;
00212     av_free((*a)->buffer);
00213     av_freep(a);
00214 }
00215 
00216 int ff_audio_data_copy(AudioData *dst, AudioData *src)
00217 {
00218     int ret, p;
00219 
00220     
00221     if (dst->sample_fmt != src->sample_fmt || dst->channels < src->channels)
00222         return AVERROR(EINVAL);
00223 
00224     
00225     if (!src->nb_samples) {
00226         dst->nb_samples = 0;
00227         return 0;
00228     }
00229 
00230     
00231     ret = ff_audio_data_realloc(dst, src->nb_samples);
00232     if (ret < 0)
00233         return ret;
00234 
00235     
00236     for (p = 0; p < src->planes; p++)
00237         memcpy(dst->data[p], src->data[p], src->nb_samples * src->stride);
00238     dst->nb_samples = src->nb_samples;
00239 
00240     return 0;
00241 }
00242 
00243 int ff_audio_data_combine(AudioData *dst, int dst_offset, AudioData *src,
00244                           int src_offset, int nb_samples)
00245 {
00246     int ret, p, dst_offset2, dst_move_size;
00247 
00248     
00249     if (dst->sample_fmt != src->sample_fmt || dst->channels != src->channels) {
00250         av_log(src, AV_LOG_ERROR, "sample format mismatch\n");
00251         return AVERROR(EINVAL);
00252     }
00253 
00254     
00255     if (dst_offset < 0 || dst_offset > dst->nb_samples ||
00256         src_offset < 0 || src_offset > src->nb_samples) {
00257         av_log(src, AV_LOG_ERROR, "offset out-of-bounds: src=%d dst=%d\n",
00258                src_offset, dst_offset);
00259         return AVERROR(EINVAL);
00260     }
00261 
00262     
00263     if (nb_samples > src->nb_samples - src_offset)
00264         nb_samples = src->nb_samples - src_offset;
00265     if (nb_samples <= 0)
00266         return 0;
00267 
00268     
00269     if (dst->read_only) {
00270         av_log(dst, AV_LOG_ERROR, "dst is read-only\n");
00271         return AVERROR(EINVAL);
00272     }
00273 
00274     
00275     ret = ff_audio_data_realloc(dst, dst->nb_samples + nb_samples);
00276     if (ret < 0) {
00277         av_log(dst, AV_LOG_ERROR, "error reallocating dst\n");
00278         return ret;
00279     }
00280 
00281     dst_offset2   = dst_offset + nb_samples;
00282     dst_move_size = dst->nb_samples - dst_offset;
00283 
00284     for (p = 0; p < src->planes; p++) {
00285         if (dst_move_size > 0) {
00286             memmove(dst->data[p] + dst_offset2 * dst->stride,
00287                     dst->data[p] + dst_offset  * dst->stride,
00288                     dst_move_size * dst->stride);
00289         }
00290         memcpy(dst->data[p] + dst_offset * dst->stride,
00291                src->data[p] + src_offset * src->stride,
00292                nb_samples * src->stride);
00293     }
00294     dst->nb_samples += nb_samples;
00295 
00296     return 0;
00297 }
00298 
00299 void ff_audio_data_drain(AudioData *a, int nb_samples)
00300 {
00301     if (a->nb_samples <= nb_samples) {
00302         
00303         a->nb_samples = 0;
00304     } else {
00305         int p;
00306         int move_offset = a->stride * nb_samples;
00307         int move_size   = a->stride * (a->nb_samples - nb_samples);
00308 
00309         for (p = 0; p < a->planes; p++)
00310             memmove(a->data[p], a->data[p] + move_offset, move_size);
00311 
00312         a->nb_samples -= nb_samples;
00313     }
00314 }
00315 
00316 int ff_audio_data_add_to_fifo(AVAudioFifo *af, AudioData *a, int offset,
00317                               int nb_samples)
00318 {
00319     uint8_t *offset_data[AVRESAMPLE_MAX_CHANNELS];
00320     int offset_size, p;
00321 
00322     if (offset >= a->nb_samples)
00323         return 0;
00324     offset_size = offset * a->stride;
00325     for (p = 0; p < a->planes; p++)
00326         offset_data[p] = a->data[p] + offset_size;
00327 
00328     return av_audio_fifo_write(af, (void **)offset_data, nb_samples);
00329 }
00330 
00331 int ff_audio_data_read_from_fifo(AVAudioFifo *af, AudioData *a, int nb_samples)
00332 {
00333     int ret;
00334 
00335     if (a->read_only)
00336         return AVERROR(EINVAL);
00337 
00338     ret = ff_audio_data_realloc(a, nb_samples);
00339     if (ret < 0)
00340         return ret;
00341 
00342     ret = av_audio_fifo_read(af, (void **)a->data, nb_samples);
00343     if (ret >= 0)
00344         a->nb_samples = ret;
00345     return ret;
00346 }