audio: deal with AVFrame-style buffer assignments

In the AVFrame-style system (which we inreasingly map our internal data
stuctures on), buffers and plane pointers don't necessarily have a 1:1
correspondence. For example, a single buffer could cover 2 or more
planes, all while other planes are covered by a second buffer, and so
on. They don't need to be ordered in the same way.

Change mp_audio_get_allocated_size() to retrieve the maximum size all
planes provide. This also considers the case of planes not pointing to
buffer start.

Change mp_audio_realloc() to reset all planes, even if corresponding
buffers are not reallocated. (The caller has to be careful anyway if it
wants to be sure the contents are preserved on realloc calls.)
This commit is contained in:
wm4 2015-06-12 17:44:40 +02:00
parent 0d2456ae5f
commit 627b87b0d8
2 changed files with 17 additions and 4 deletions

View File

@ -160,8 +160,8 @@ void mp_audio_realloc(struct mp_audio *mpa, int samples)
if (!mpa->allocated[n] || size != mpa->allocated[n]->size) {
if (av_buffer_realloc(&mpa->allocated[n], size) < 0)
abort(); // OOM
mpa->planes[n] = mpa->allocated[n]->data;
}
mpa->planes[n] = mpa->allocated[n]->data;
}
for (int n = mpa->num_planes; n < MP_NUM_CHANNELS; n++) {
av_buffer_unref(&mpa->allocated[n]);
@ -192,8 +192,18 @@ int mp_audio_get_allocated_size(struct mp_audio *mpa)
{
int size = 0;
for (int n = 0; n < mpa->num_planes; n++) {
int s = mpa->allocated[n] ? mpa->allocated[n]->size / mpa->sstride : 0;
size = n == 0 ? s : MPMIN(size, s);
for (int i = 0; i < MP_NUM_CHANNELS && mpa->allocated[i]; i++) {
uint8_t *start = mpa->allocated[i]->data;
uint8_t *end = start + mpa->allocated[i]->size;
uint8_t *plane = mpa->planes[n];
if (plane >= start && plane < end) {
int s = MPMIN((end - plane) / mpa->sstride, INT_MAX);
size = n == 0 ? s : MPMIN(size, s);
goto next;
}
}
return 0; // plane is not covered by any buffer
next: ;
}
return size;
}

View File

@ -37,8 +37,11 @@ struct mp_audio {
int num_planes; // number of planes
int bps; // size of sub-samples (af_fmt2bps(format))
// private
// --- private
bool readonly;
// These do not necessarily map directly to planes[]. They can have
// different order or count. There shouldn't be more buffers than planes.
// If allocated[n] is NULL, allocated[n+1] must also be NULL.
struct AVBufferRef *allocated[MP_NUM_CHANNELS];
};