Beispiel #1
0
static int fill_queue(struct af_instance *af, struct mp_audio *data, int offset)
{
    af_scaletempo_t *s = af->priv;
    int bytes_in = mp_audio_psize(data) - offset;
    int offset_unchanged = offset;

    if (s->bytes_to_slide > 0) {
        if (s->bytes_to_slide < s->bytes_queued) {
            int bytes_move = s->bytes_queued - s->bytes_to_slide;
            memmove(s->buf_queue, s->buf_queue + s->bytes_to_slide, bytes_move);
            s->bytes_to_slide = 0;
            s->bytes_queued = bytes_move;
        } else {
            int bytes_skip;
            s->bytes_to_slide -= s->bytes_queued;
            bytes_skip = MPMIN(s->bytes_to_slide, bytes_in);
            s->bytes_queued = 0;
            s->bytes_to_slide -= bytes_skip;
            offset += bytes_skip;
            bytes_in -= bytes_skip;
        }
    }

    if (bytes_in > 0) {
        int bytes_copy = MPMIN(s->bytes_queue - s->bytes_queued, bytes_in);
        assert(bytes_copy >= 0);
        memcpy(s->buf_queue + s->bytes_queued,
               (int8_t *)data->planes[0] + offset, bytes_copy);
        s->bytes_queued += bytes_copy;
        offset += bytes_copy;
    }

    return offset - offset_unchanged;
}
Beispiel #2
0
// Initialization and runtime control
static int control(struct af_instance* af, int cmd, void* arg)
{
    af_pan_t* s = af->priv;

    switch(cmd) {
    case AF_CONTROL_REINIT:
        // Sanity check
        if(!arg) return AF_ERROR;

        af->data->rate   = ((struct mp_audio*)arg)->rate;
        mp_audio_set_format(af->data, AF_FORMAT_FLOAT);
        set_channels(af->data, s->nch ? s->nch: ((struct mp_audio*)arg)->nch);

        if((af->data->format != ((struct mp_audio*)arg)->format) ||
                (af->data->bps != ((struct mp_audio*)arg)->bps)) {
            mp_audio_set_format((struct mp_audio*)arg, af->data->format);
            return AF_FALSE;
        }
        return AF_OK;
    case AF_CONTROL_SET_PAN_LEVEL: {
        int    i;
        int    ch = ((af_control_ext_t*)arg)->ch;
        float* level = ((af_control_ext_t*)arg)->arg;
        if (ch >= AF_NCH)
            return AF_FALSE;
        for(i=0; i<AF_NCH; i++)
            s->level[ch][i] = level[i];
        return AF_OK;
    }
    case AF_CONTROL_SET_PAN_NOUT:
        // Reinit must be called after this function has been called

        // Sanity check
        if(((int*)arg)[0] <= 0 || ((int*)arg)[0] > AF_NCH) {
            MP_ERR(af, "The number of output channels must be"
                   " between 1 and %i. Current value is %i\n",AF_NCH,((int*)arg)[0]);
            return AF_ERROR;
        }
        s->nch=((int*)arg)[0];
        return AF_OK;
    case AF_CONTROL_SET_PAN_BALANCE: {
        float val = *(float*)arg;
        if (s->nch)
            return AF_ERROR;
        if (af->data->nch >= 2) {
            s->level[0][0] = MPMIN(1.f, 1.f - val);
            s->level[0][1] = MPMAX(0.f, val);
            s->level[1][0] = MPMAX(0.f, -val);
            s->level[1][1] = MPMIN(1.f, 1.f + val);
        }
        return AF_OK;
    }
    case AF_CONTROL_GET_PAN_BALANCE:
        if (s->nch)
            return AF_ERROR;
        *(float*)arg = s->level[0][1] - s->level[1][0];
        return AF_OK;
    }
    return AF_UNKNOWN;
}
Beispiel #3
0
// This is called both during init and at runtime.
static int resize_cache(struct priv *s, int64_t size)
{
    int64_t min_size = FILL_LIMIT * 4;
    int64_t max_size = ((size_t)-1) / 4;
    int64_t buffer_size = MPMIN(MPMAX(size, min_size), max_size);

    unsigned char *buffer = malloc(buffer_size);
    struct byte_meta *bm = calloc(buffer_size / BYTE_META_CHUNK_SIZE + 2,
                                  sizeof(struct byte_meta));
    if (!buffer || !bm) {
        free(buffer);
        free(bm);
        return STREAM_ERROR;
    }

    if (s->buffer) {
        // Copy & free the old ringbuffer data.
        // If the buffer is too small, prefer to copy these regions:
        // 1. Data starting from read_filepos, until cache end
        size_t read_1 = read_buffer(s, buffer, buffer_size, s->read_filepos);
        // 2. then data from before read_filepos until cache start
        //    (this one needs to be copied to the end of the ringbuffer)
        size_t read_2 = 0;
        if (s->min_filepos < s->read_filepos) {
            size_t copy_len = buffer_size - read_1;
            copy_len = MPMIN(copy_len, s->read_filepos - s->min_filepos);
            assert(copy_len + read_1 <= buffer_size);
            read_2 = read_buffer(s, buffer + buffer_size - copy_len, copy_len,
                                 s->read_filepos - copy_len);
            // This shouldn't happen, unless copy_len was computed incorrectly.
            assert(read_2 == copy_len);
        }
        // Set it up such that read_1 is at buffer pos 0, and read_2 wraps
        // around below it, so that it is located at the end of the buffer.
        s->min_filepos = s->read_filepos - read_2;
        s->max_filepos = s->read_filepos + read_1;
        s->offset = s->max_filepos - read_1;
    } else {
        cache_drop_contents(s);
    }

    free(s->buffer);
    free(s->bm);

    s->buffer_size = buffer_size;
    s->back_size = buffer_size / 2;
    s->buffer = buffer;
    s->bm = bm;
    s->idle = false;
    s->eof = false;

    //make sure that we won't wait from cache_fill
    //more data than it is allowed to fill
    if (s->seek_limit > s->buffer_size - FILL_LIMIT)
        s->seek_limit = s->buffer_size - FILL_LIMIT;

    return STREAM_OK;
}
Beispiel #4
0
static void fill_rect(struct vo *vo, GC gc, int x0, int y0, int x1, int y1)
{
    struct vo_x11_state *x11 = vo->x11;

    x0 = MPMAX(x0, 0);
    y0 = MPMAX(y0, 0);
    x1 = MPMIN(x1, vo->dwidth);
    y1 = MPMIN(y1, vo->dheight);

    if (x11->window && gc && x1 > x0 && y1 > y0)
        XFillRectangle(x11->display, x11->window, gc, x0, y0, x1 - x0, y1 - y0);
}
Beispiel #5
0
// Copy at most dst_size from the cache at the given absolute file position pos.
// Return number of bytes that could actually be read.
// Does not advance the file position, or change anything else.
// Can be called from anywhere, as long as the mutex is held.
static size_t read_buffer(struct priv *s, unsigned char *dst,
                          size_t dst_size, int64_t pos)
{
    size_t read = 0;
    while (read < dst_size) {
        if (pos >= s->max_filepos || pos < s->min_filepos)
            break;
        int64_t newb = s->max_filepos - pos; // new bytes in the buffer

        int64_t bpos = pos - s->offset; // file pos to buffer memory pos
        if (bpos < 0) {
            bpos += s->buffer_size;
        } else if (bpos >= s->buffer_size) {
            bpos -= s->buffer_size;
        }

        if (newb > s->buffer_size - bpos)
            newb = s->buffer_size - bpos; // handle wrap...

        newb = MPMIN(newb, dst_size - read);

        assert(newb >= 0 && read + newb <= dst_size);
        assert(bpos >= 0 && bpos + newb <= s->buffer_size);
        memcpy(&dst[read], &s->buffer[bpos], newb);
        read += newb;
        pos += newb;
    }
    return read;
}
Beispiel #6
0
void ca_get_active_chmap(struct ao *ao, AudioDeviceID device, int channel_count,
                         struct mp_chmap *out_map)
{
    // Apparently, we have to guess by looking back at the supported layouts,
    // and I haven't found a property that retrieves the actual currently
    // active channel layout.

    struct mp_chmap_sel chmap_sel = {0};
    ca_retrieve_layouts(ao, &chmap_sel, device);

    // Use any exact match.
    for (int n = 0; n < chmap_sel.num_chmaps; n++) {
        if (chmap_sel.chmaps[n].num == channel_count) {
            MP_VERBOSE(ao, "mismatching channels - fallback #%d\n", n);
            *out_map = chmap_sel.chmaps[n];
            return;
        }
    }

    // Fall back to stereo or mono, and fill the rest with silence. (We don't
    // know what the device expects. We could use a larger default layout here,
    // but let's not.)
    mp_chmap_from_channels(out_map, MPMIN(2, channel_count));
    out_map->num = channel_count;
    for (int n = 2; n < out_map->num; n++)
        out_map->speaker[n] = MP_SPEAKER_ID_NA;
    MP_WARN(ao, "mismatching channels - falling back to %s\n",
            mp_chmap_to_str(out_map));
}
Beispiel #7
0
static int archive_entry_seek(stream_t *s, int64_t newpos)
{
    struct priv *p = s->priv;
    if (!p->mpa)
        return -1;
    if (archive_seek_data(p->mpa->arch, newpos, SEEK_SET) >= 0)
        return 1;
    // libarchive can't seek in most formats.
    if (newpos < s->pos) {
        // Hack seeking backwards into working by reopening the archive and
        // starting over.
        MP_VERBOSE(s, "trying to reopen archive for performing seek\n");
        if (reopen_archive(s) < STREAM_OK)
            return -1;
        s->pos = 0;
    }
    if (newpos > s->pos) {
        // For seeking forwards, just keep reading data (there's no libarchive
        // skip function either).
        char buffer[4096];
        while (newpos > s->pos) {
            if (mp_cancel_test(s->cancel))
                return -1;

            int size = MPMIN(newpos - s->pos, sizeof(buffer));
            int r = archive_read_data(p->mpa->arch, buffer, size);
            if (r < 0) {
                MP_ERR(s, "%s\n", archive_error_string(p->mpa->arch));
                return -1;
            }
            s->pos += r;
        }
    }
    return 1;
}
Beispiel #8
0
static void mp_msg_av_log_callback(void *ptr, int level, const char *fmt,
                                   va_list vl)
{
    AVClass *avc = ptr ? *(AVClass **)ptr : NULL;
    int mp_level = av_log_level_to_mp_level(level);

    // Note: mp_log is thread-safe, but destruction of the log instances is not.
    pthread_mutex_lock(&log_lock);

    if (!log_mpv_instance) {
        pthread_mutex_unlock(&log_lock);
        // Fallback to stderr
        vfprintf(stderr, fmt, vl);
        return;
    }

    struct mp_log *log = get_av_log(ptr);

    if (mp_msg_test(log, mp_level)) {
        char buffer[4096] = "";
        int pos = 0;
        const char *prefix = avc ? avc->item_name(ptr) : NULL;
        if (log_print_prefix && prefix)
            pos = snprintf(buffer, sizeof(buffer), "%s: ", prefix);
        log_print_prefix = fmt[strlen(fmt) - 1] == '\n';

        pos = MPMIN(MPMAX(pos, 0), sizeof(buffer));
        vsnprintf(buffer + pos, sizeof(buffer) - pos, fmt, vl);

        mp_msg(log, mp_level, "%s", buffer);
    }

    pthread_mutex_unlock(&log_lock);
}
Beispiel #9
0
static int filter_out(struct af_instance *af)
{
    struct priv *p = af->priv;

    while (rubberband_available(p->rubber) <= 0) {
        const float *dummy[MP_NUM_CHANNELS] = {0};
        const float **in_data = dummy;
        size_t in_samples = 0;
        if (p->pending) {
            if (!p->pending->samples)
                break;

            // recover from previous EOF
            if (p->needs_reset) {
                rubberband_reset(p->rubber);
                p->rubber_delay = 0;
            }
            p->needs_reset = false;

            size_t needs = rubberband_get_samples_required(p->rubber);
            in_data = (void *)&p->pending->planes;
            in_samples = MPMIN(p->pending->samples, needs);
        }

        if (p->needs_reset)
            break; // previous EOF
        p->needs_reset = !p->pending; // EOF

        rubberband_process(p->rubber, in_data, in_samples, p->needs_reset);
        p->rubber_delay += in_samples;

        if (!p->pending)
            break;
        mp_audio_skip_samples(p->pending, in_samples);
    }

    int out_samples = rubberband_available(p->rubber);
    if (out_samples > 0) {
        struct mp_audio *out =
            mp_audio_pool_get(af->out_pool, af->data, out_samples);
        if (!out)
            return -1;
        if (p->pending)
            mp_audio_copy_config(out, p->pending);

        float **out_data = (void *)&out->planes;
        out->samples = rubberband_retrieve(p->rubber, out_data, out->samples);
        p->rubber_delay -= out->samples * p->speed;

        af_add_output_frame(af, out);
    }

    int delay_samples = p->rubber_delay;
    if (p->pending)
        delay_samples += p->pending->samples;
    af->delay = delay_samples / (af->data->rate * p->speed);

    return 0;
}
Beispiel #10
0
// Filter len bytes of input, put result into outbuf.
static int filter_n_bytes(struct dec_audio *da, struct mp_audio_buffer *outbuf,
                          int len)
{
    int error = 0;

    struct mp_audio config;
    mp_audio_buffer_get_format(da->decode_buffer, &config);

    while (mp_audio_buffer_samples(da->decode_buffer) < len) {
        int maxlen = mp_audio_buffer_get_write_available(da->decode_buffer);
        if (maxlen < DECODE_MAX_UNIT)
            break;
        struct mp_audio buffer;
        mp_audio_buffer_get_write_buffer(da->decode_buffer, maxlen, &buffer);
        buffer.samples = 0;
        error = da->ad_driver->decode_audio(da, &buffer, maxlen);
        if (error < 0)
            break;
        // Commit the data just read as valid data
        mp_audio_buffer_finish_write(da->decode_buffer, buffer.samples);
        // Format change
        if (!mp_audio_config_equals(&da->decoded, &config)) {
            // If there are still samples left in the buffer, let them drain
            // first, and don't signal a format change to the caller yet.
            if (mp_audio_buffer_samples(da->decode_buffer) > 0)
                break;
            error = -2;
            break;
        }
    }

    // Filter
    struct mp_audio filter_data;
    mp_audio_buffer_peek(da->decode_buffer, &filter_data);
    filter_data.rate = da->afilter->input.rate; // due to playback speed change
    len = MPMIN(filter_data.samples, len);
    filter_data.samples = len;
    bool eof = filter_data.samples == 0 && error < 0;

    if (af_filter(da->afilter, &filter_data, eof ? AF_FILTER_FLAG_EOF : 0) < 0)
        return -1;

    mp_audio_buffer_append(outbuf, &filter_data);
    if (eof && filter_data.samples > 0)
        error = 0; // don't end playback yet

    // remove processed data from decoder buffer:
    mp_audio_buffer_skip(da->decode_buffer, len);

    // Assume the filter chain is drained from old data at this point.
    // (If not, the remaining old data is discarded.)
    if (error == -2) {
        if (!reinit_audio_buffer(da))
            error = -1; // switch to invalid format
    }

    return error;
}
Beispiel #11
0
static int fill_buffer(stream_t *s, char *buffer, int max_len)
{
    struct priv *p = s->priv;
    if (s->pos < 0)
        return -1;
    if (s->pos >= p->max_size) {
        if (stream_seek(p->original, s->pos) < 1)
            return -1;
        return stream_read(p->original, buffer, max_len);
    }
    // Size of file changes -> invalidate last block
    if (s->pos >= p->size - BLOCK_SIZE) {
        int64_t new_size = -1;
        stream_control(s, STREAM_CTRL_GET_SIZE, &new_size);
        if (new_size != p->size)
            set_bit(p, BLOCK_ALIGN(p->size), 0);
        p->size = MPMIN(p->max_size, new_size);
    }
    int64_t aligned = BLOCK_ALIGN(s->pos);
    if (!test_bit(p, aligned)) {
        char tmp[BLOCK_SIZE];
        stream_seek(p->original, aligned);
        int r = stream_read(p->original, tmp, BLOCK_SIZE);
        if (r < BLOCK_SIZE) {
            if (p->size < 0) {
                MP_WARN(s, "suspected EOF\n");
            } else if (aligned + r < p->size) {
                MP_ERR(s, "unexpected EOF\n");
                return -1;
            }
        }
        if (fseeko(p->cache_file, aligned, SEEK_SET))
            return -1;
        if (fwrite(tmp, r, 1, p->cache_file) != 1)
            return -1;
        set_bit(p, aligned, 1);
    }
    if (fseeko(p->cache_file, s->pos, SEEK_SET))
        return -1;
    // align/limit to blocks
    max_len = MPMIN(max_len, BLOCK_SIZE - (s->pos % BLOCK_SIZE));
    // Limit to max. known file size
    max_len = MPMIN(max_len, p->size - s->pos);
    return fread(buffer, 1, max_len, p->cache_file);
}
Beispiel #12
0
// Clamp [start, end) to range [0, size) with various fallbacks.
static void clamp_size(int size, int *start, int *end)
{
    *start = MPMAX(0, *start);
    *end = MPMIN(size, *end);
    if (*start >= *end) {
        *start = 0;
        *end = 1;
    }
}
Beispiel #13
0
static int archive_entry_seek(stream_t *s, int64_t newpos)
{
    struct priv *p = s->priv;
    if (p->mpa && !p->broken_seek) {
        locale_t oldlocale = uselocale(p->mpa->locale);
        int r = archive_seek_data(p->mpa->arch, newpos, SEEK_SET);
        uselocale(oldlocale);
        if (r >= 0)
            return 1;
        MP_WARN(s, "possibly unsupported seeking - switching to reopening\n");
        p->broken_seek = true;
        if (reopen_archive(s) < STREAM_OK)
            return -1;
    }
    // libarchive can't seek in most formats.
    if (newpos < s->pos) {
        // Hack seeking backwards into working by reopening the archive and
        // starting over.
        MP_VERBOSE(s, "trying to reopen archive for performing seek\n");
        if (reopen_archive(s) < STREAM_OK)
            return -1;
        s->pos = 0;
    }
    if (newpos > s->pos) {
        // For seeking forwards, just keep reading data (there's no libarchive
        // skip function either).
        char buffer[4096];
        while (newpos > s->pos) {
            if (mp_cancel_test(s->cancel))
                return -1;

            int size = MPMIN(newpos - s->pos, sizeof(buffer));
            locale_t oldlocale = uselocale(p->mpa->locale);
            int r = archive_read_data(p->mpa->arch, buffer, size);
            if (r <= 0) {
                if (r == 0 && newpos > p->entry_size) {
                    MP_ERR(s, "demuxer trying to seek beyond end of archive "
                           "entry\n");
                } else if (r == 0) {
                    MP_ERR(s, "end of archive entry reached while seeking\n");
                } else {
                    MP_ERR(s, "%s\n", archive_error_string(p->mpa->arch));
                }
                uselocale(oldlocale);
                if (mp_archive_check_fatal(p->mpa, r)) {
                    mp_archive_free(p->mpa);
                    p->mpa = NULL;
                }
                return -1;
            }
            uselocale(oldlocale);
            s->pos += r;
        }
    }
    return 1;
}
Beispiel #14
0
static void reselect_streams(demuxer_t *demuxer)
{
    struct priv *p = demuxer->priv;
    for (int n = 0; n < MPMIN(p->slave->num_streams, p->num_streams); n++) {
        if (p->streams[n]) {
            demuxer_select_track(p->slave, p->slave->streams[n],
                demux_stream_is_selected(p->streams[n]));
        }
    }
}
Beispiel #15
0
// Initialization and runtime control
static int control(struct af_instance* af, int cmd, void* arg)
{
  af_channels_t* s = af->priv;
  switch(cmd){
  case AF_CONTROL_REINIT: ;

    struct mp_chmap chmap;
    mp_chmap_set_unknown(&chmap, s->nch);
    mp_audio_set_channels(af->data, &chmap);

    // Set default channel assignment
    if(!s->router){
      int i;
      // Make sure this filter isn't redundant
      if(af->data->nch == ((struct mp_audio*)arg)->nch)
	return AF_DETACH;

      // If mono: fake stereo
      if(((struct mp_audio*)arg)->nch == 1){
	s->nr = MPMIN(af->data->nch,2);
	for(i=0;i<s->nr;i++){
	  s->route[i][FR] = 0;
	  s->route[i][TO] = i;
	}
      }
      else{
	s->nr = MPMIN(af->data->nch, ((struct mp_audio*)arg)->nch);
	for(i=0;i<s->nr;i++){
	  s->route[i][FR] = i;
	  s->route[i][TO] = i;
	}
      }
    }

    af->data->rate   = ((struct mp_audio*)arg)->rate;
    mp_audio_force_interleaved_format((struct mp_audio*)arg);
    mp_audio_set_format(af->data, ((struct mp_audio*)arg)->format);
    return check_routes(af,((struct mp_audio*)arg)->nch,af->data->nch);
  }
  return AF_UNKNOWN;
}
Beispiel #16
0
static void update_speed(struct af_instance *af, float speed)
{
    af_scaletempo_t *s = af->priv;

    s->speed = speed;

    double factor = (s->speed_opt & SCALE_PITCH) ? 1.0 / s->speed : s->speed;
    s->scale = factor * s->scale_nominal;

    s->frames_stride_scaled = s->scale * s->frames_stride;
    s->frames_stride_error = MPMIN(s->frames_stride_error, s->frames_stride_scaled);
}
Beispiel #17
0
Datei: rar.c Projekt: 0x0all/mpv
static int SkipBlock(struct stream *s, const rar_block_t *hdr)
{
    uint64_t size = (uint64_t)hdr->size + hdr->add_size;

    while (size > 0) {
        int skip = MPMIN(size, INT_MAX);
        if (!stream_skip(s, skip))
            return -1;

        size -= skip;
    }
    return 0;
}
Beispiel #18
0
Datei: rar.c Projekt: 0x0all/mpv
ssize_t RarRead(rar_file_t *file, void *data, size_t size)
{
    size_t total = 0;
    while (total < size) {
        const uint64_t chunk_end = file->current_chunk->cummulated_size + file->current_chunk->size;
        int max = MPMIN(MPMIN((int64_t)(size - total), (int64_t)(chunk_end - file->i_pos)), INT_MAX);
        if (max <= 0)
            break;

        int r = stream_read(file->s, data, max);
        if (r <= 0)
            break;

        total += r;
        data = (char *)data + r;
        file->i_pos += r;
        if (file->i_pos >= chunk_end &&
            RarSeek(file, file->i_pos))
            break;
    }
    return total;

}
Beispiel #19
0
static int keys_count_matches(char *buf, int buflen) {
    int count = 0;
    if (buflen < 0)
        buflen = strlen(buf);

    for (int i = 0; i < getch2_keys.len; i++) {
        keycode_st *st = &getch2_keys.map[i];
        int len = MPMIN(buflen, st->len);

        if (memcmp(buf, st->chars, len) == 0)
            count++;
    }
    return count;
}
Beispiel #20
0
// Copy data from input frame to encode frame (because libavcodec wants a full
// AC3 frame for encoding, while filter input frames can be smaller or larger).
// Return true if the frame is complete.
static bool fill_buffer(struct af_instance *af)
{
    af_ac3enc_t *s = af->priv;

    af->delay = 0;

    if (s->pending) {
        int copy = MPMIN(s->in_samples - s->input->samples, s->pending->samples);
        s->input->samples += copy;
        mp_audio_copy(s->input, s->input->samples - copy, s->pending, 0, copy);
        mp_audio_skip_samples(s->pending, copy);
    }
    update_delay(af);
    return s->input->samples >= s->in_samples;
}
Beispiel #21
0
static bool is_compatible(int fmt1, int fmt2)
{
    struct mp_imgfmt_desc d1 = mp_imgfmt_get_desc(fmt1);
    struct mp_imgfmt_desc d2 = mp_imgfmt_get_desc(fmt2);
    if (d1.num_planes < d2.num_planes)
        return false;
    if (!(d1.flags & MP_IMGFLAG_BYTE_ALIGNED) ||
        !(d2.flags & MP_IMGFLAG_BYTE_ALIGNED))
        return false;
    for (int n = 0; n < MPMIN(d1.num_planes, d2.num_planes); n++) {
        if (d1.bytes[n] != d2.bytes[n])
            return false;
        if (d1.xs[n] != d2.xs[n] || d1.ys[n] != d2.ys[n])
            return false;
    }
    return true;
}
Beispiel #22
0
// Copy data from input frame to encode frame (because libavcodec wants a full
// AC3 frame for encoding, while filter input frames can be smaller or larger).
// Return true if the frame is complete.
static bool fill_buffer(struct af_instance *af)
{
    af_ac3enc_t *s = af->priv;

    af->delay = 0;

    if (s->pending) {
        if (!mp_audio_is_writeable(s->input))
            assert(s->input->samples == 0); // we can't have sent a partial frame
        mp_audio_realloc_min(s->input, s->in_samples);
        int copy = MPMIN(s->in_samples - s->input->samples, s->pending->samples);
        s->input->samples += copy;
        mp_audio_copy(s->input, s->input->samples - copy, s->pending, 0, copy);
        mp_audio_skip_samples(s->pending, copy);
    }
    update_delay(af);
    return s->input->samples >= s->in_samples;
}
Beispiel #23
0
void mp_set_avcodec_threads(struct mp_log *l, AVCodecContext *avctx, int threads)
{
    if (threads == 0) {
        threads = av_cpu_count();
        if (threads < 1) {
            mp_warn(l, "Could not determine thread count to use, defaulting to 1.\n");
            threads = 1;
        } else {
            mp_verbose(l, "Detected %d logical cores.\n", threads);
            if (threads > 1)
                threads += 1; // extra thread for better load balancing
        }
        // Apparently some libavcodec versions have or had trouble with more
        // than 16 threads, and/or print a warning when using > 16.
        threads = MPMIN(threads, 16);
    }
    mp_verbose(l, "Requesting %d threads for decoding.\n", threads);
    avctx->thread_count = threads;
}
Beispiel #24
0
static float compute_replaygain(struct MPContext *mpctx)
{
    struct MPOpts *opts = mpctx->opts;

    float rgain = 1.0;

    struct replaygain_data *rg = NULL;
    struct track *track = mpctx->current_track[0][STREAM_AUDIO];
    if (track)
        rg = track->stream->codec->replaygain_data;
    if (opts->rgain_mode && rg) {
        MP_VERBOSE(mpctx, "Replaygain: Track=%f/%f Album=%f/%f\n",
                   rg->track_gain, rg->track_peak,
                   rg->album_gain, rg->album_peak);

        float gain, peak;
        if (opts->rgain_mode == 1) {
            gain = rg->track_gain;
            peak = rg->track_peak;
        } else {
            gain = rg->album_gain;
            peak = rg->album_peak;
        }

        gain += opts->rgain_preamp;
        rgain = db_gain(gain);

        MP_VERBOSE(mpctx, "Applying replay-gain: %f\n", rgain);

        if (!opts->rgain_clip) { // clipping prevention
            rgain = MPMIN(rgain, 1.0 / peak);
            MP_VERBOSE(mpctx, "...with clipping prevention: %f\n", rgain);
        }
    } else if (opts->rgain_fallback) {
        rgain = db_gain(opts->rgain_fallback);
        MP_VERBOSE(mpctx, "Applying fallback gain: %f\n", rgain);
    }

    return rgain;
}
Beispiel #25
0
static int play(struct ao *ao, void **data, int samples, int flags)
{
    struct priv *priv = ao->priv;
    int accepted;

    resume(ao);

    if (priv->buffered <= 0)
        priv->buffered = priv->latency; // emulate fixed latency

    priv->playing_final = flags & AOPLAY_FINAL_CHUNK;
    if (priv->playing_final) {
        // Last audio chunk - don't round to outburst.
        accepted = MPMIN(priv->buffersize - priv->buffered, samples);
    } else {
        int maxbursts = (priv->buffersize - priv->buffered) / priv->outburst;
        int playbursts = samples / priv->outburst;
        int bursts = playbursts > maxbursts ? maxbursts : playbursts;
        accepted = bursts * priv->outburst;
    }
    priv->buffered += accepted;
    return accepted;
}
Beispiel #26
0
struct timespec mp_time_us_to_timespec(int64_t time_us)
{
    struct timespec ts;
    get_realtime(&ts);
    // We don't know what time source mp_time_us() uses, but usually it's not
    // CLOCK_REALTIME - so we have to remap the times.
    int64_t unow = mp_time_us();
    int64_t diff_us = time_us - unow;
    int64_t diff_secs = diff_us / (1000L * 1000L);
    long diff_nsecs = (diff_us - diff_secs * (1000L * 1000L)) * 1000L;
    if (diff_nsecs < 0) {
        diff_secs -= 1;
        diff_nsecs += 1000000000L;
    }
    if (diff_nsecs + ts.tv_nsec >= 1000000000UL) {
        diff_secs += 1;
        diff_nsecs -= 1000000000UL;
    }
    // OSX can't deal with large timeouts. Also handles tv_sec/time_t overflows.
    diff_secs = MPMIN(diff_secs, 10000000);
    ts.tv_sec += diff_secs;
    ts.tv_nsec += diff_nsecs;
    return ts;
}
Beispiel #27
0
// Filter data through filter
static int filter(struct af_instance* af, struct mp_audio* audio, int flags)
{
    struct mp_audio *out = af->data;
    af_ac3enc_t *s = af->priv;
    int num_frames = (audio->samples + mp_audio_buffer_samples(s->pending))
                     / s->in_samples;

    int max_out_samples = s->out_samples * num_frames;
    mp_audio_realloc_min(out, max_out_samples);
    out->samples = 0;

    while (audio->samples > 0) {
        int ret;

        int consumed_pending = 0;
        struct mp_audio in_frame;
        int pending = mp_audio_buffer_samples(s->pending);
        if (pending == 0 && audio->samples >= s->in_samples) {
            in_frame = *audio;
            mp_audio_skip_samples(audio, s->in_samples);
        } else {
            if (pending > 0 && pending < s->in_samples) {
                struct mp_audio tmp = *audio;
                tmp.samples = MPMIN(tmp.samples, s->in_samples);
                mp_audio_buffer_append(s->pending, &tmp);
                mp_audio_skip_samples(audio, tmp.samples);
            }
            mp_audio_buffer_peek(s->pending, &in_frame);
            if (in_frame.samples < s->in_samples)
                break;
            consumed_pending = s->in_samples;
        }
        in_frame.samples = s->in_samples;

        AVFrame *frame = av_frame_alloc();
        if (!frame) {
            MP_FATAL(af, "Could not allocate memory \n");
            return -1;
        }
        frame->nb_samples = s->in_samples;
        frame->format = s->lavc_actx->sample_fmt;
        frame->channel_layout = s->lavc_actx->channel_layout;
        assert(in_frame.num_planes <= AV_NUM_DATA_POINTERS);
        frame->extended_data = frame->data;
        for (int n = 0; n < in_frame.num_planes; n++)
            frame->data[n] = in_frame.planes[n];
        frame->linesize[0] = s->in_samples * audio->sstride;

        int ok;
        ret = avcodec_encode_audio2(s->lavc_actx, &s->pkt, frame, &ok);
        av_frame_free(&frame);
        if (ret < 0 || !ok) {
            MP_FATAL(af, "Encode failed.\n");
            return -1;
        }

        mp_audio_buffer_skip(s->pending, consumed_pending);

        MP_DBG(af, "avcodec_encode_audio got %d, pending %d.\n",
               s->pkt.size, mp_audio_buffer_samples(s->pending));

        int frame_size = s->pkt.size;
        int header_len = 0;
        char hdr[8];

        if (s->cfg_add_iec61937_header && s->pkt.size > 5) {
            int bsmod = s->pkt.data[5] & 0x7;
            int len = frame_size;

            frame_size = AC3_FRAME_SIZE * 2 * 2;
            header_len = 8;

            AV_WB16(hdr,     0xF872);   // iec 61937 syncword 1
            AV_WB16(hdr + 2, 0x4E1F);   // iec 61937 syncword 2
            hdr[4] = bsmod;             // bsmod
            hdr[5] = 0x01;              // data-type ac3
            AV_WB16(hdr + 6, len << 3); // number of bits in payload
        }

        size_t max_size = (max_out_samples - out->samples) * out->sstride;
        if (frame_size > max_size)
            abort();

        char *buf = (char *)out->planes[0] + out->samples * out->sstride;
        memcpy(buf, hdr, header_len);
        memcpy(buf + header_len, s->pkt.data, s->pkt.size);
        memset(buf + header_len + s->pkt.size, 0,
               frame_size - (header_len + s->pkt.size));
        out->samples += frame_size / out->sstride;
    }

    mp_audio_buffer_append(s->pending, audio);

    *audio = *out;
    return 0;
}
Beispiel #28
0
// Filter len bytes of input, put result into outbuf.
static int filter_n_bytes(struct dec_audio *da, struct mp_audio_buffer *outbuf,
                          int len)
{
    bool format_change = false;
    int error = 0;

    assert(len > 0); // would break EOF logic below

    while (mp_audio_buffer_samples(da->decode_buffer) < len) {
        // Check for a format change
        struct mp_audio config;
        mp_audio_buffer_get_format(da->decode_buffer, &config);
        format_change = !mp_audio_config_equals(&da->decoded, &config);
        if (format_change) {
            error = AD_EOF; // drain remaining data left in the current buffer
            break;
        }
        if (da->decoded.samples > 0) {
            int copy = MPMIN(da->decoded.samples, len);
            struct mp_audio append = da->decoded;
            append.samples = copy;
            mp_audio_buffer_append(da->decode_buffer, &append);
            mp_audio_skip_samples(&da->decoded, copy);
            da->pts_offset += copy;
            continue;
        }
        error = da->ad_driver->decode_packet(da);
        if (error < 0)
            break;
    }

    if (error == AD_WAIT)
        return error;

    // Filter
    struct mp_audio filter_data;
    mp_audio_buffer_peek(da->decode_buffer, &filter_data);
    filter_data.rate = da->afilter->input.rate; // due to playback speed change
    len = MPMIN(filter_data.samples, len);
    filter_data.samples = len;
    bool eof = error == AD_EOF && filter_data.samples == 0;

    if (af_filter(da->afilter, &filter_data, eof ? AF_FILTER_FLAG_EOF : 0) < 0)
        return AD_ERR;

    mp_audio_buffer_append(outbuf, &filter_data);
    if (error == AD_EOF && filter_data.samples > 0)
        error = 0; // don't end playback yet

    // remove processed data from decoder buffer:
    mp_audio_buffer_skip(da->decode_buffer, len);

    // if format was changed, and all data was drained, execute the format change
    if (format_change && eof) {
        error = AD_NEW_FMT;
        if (!reinit_audio_buffer(da))
            error = AD_ERR; // switch to invalid format
    }

    return error;
}
Beispiel #29
0
static int init(struct ao *ao)
{
    if (SDL_WasInit(SDL_INIT_AUDIO)) {
        MP_ERR(ao, "already initialized\n");
        return -1;
    }

    struct priv *priv = ao->priv;

    if (SDL_InitSubSystem(SDL_INIT_AUDIO)) {
        if (!ao->probing)
            MP_ERR(ao, "SDL_Init failed\n");
        uninit(ao);
        return -1;
    }

    struct mp_chmap_sel sel = {0};
    mp_chmap_sel_add_waveext_def(&sel);
    if (!ao_chmap_sel_adjust(ao, &sel, &ao->channels)) {
        uninit(ao);
        return -1;
    }

    ao->format = af_fmt_from_planar(ao->format);

    SDL_AudioSpec desired, obtained;

    desired.format = AUDIO_S16SYS;
    for (int n = 0; fmtmap[n][0]; n++) {
        if (ao->format == fmtmap[n][0]) {
            desired.format = fmtmap[n][1];
            break;
        }
    }
    desired.freq = ao->samplerate;
    desired.channels = ao->channels.num;
    desired.samples = MPMIN(32768, ceil_power_of_two(ao->samplerate *
                                                     priv->buflen));
    desired.callback = audio_callback;
    desired.userdata = ao;

    MP_VERBOSE(ao, "requested format: %d Hz, %d channels, %x, "
               "buffer size: %d samples\n",
               (int) desired.freq, (int) desired.channels,
               (int) desired.format, (int) desired.samples);

    obtained = desired;
    if (SDL_OpenAudio(&desired, &obtained)) {
        if (!ao->probing)
            MP_ERR(ao, "could not open audio: %s\n", SDL_GetError());
        uninit(ao);
        return -1;
    }

    MP_VERBOSE(ao, "obtained format: %d Hz, %d channels, %x, "
               "buffer size: %d samples\n",
               (int) obtained.freq, (int) obtained.channels,
               (int) obtained.format, (int) obtained.samples);

    // The sample count is usually the number of samples the callback requests,
    // which we assume is the period size. Normally, ao.c will allocate a large
    // enough buffer. But in case the period size should be pathologically
    // large, this will help.
    ao->device_buffer = 3 * obtained.samples;

    ao->format = 0;
    for (int n = 0; fmtmap[n][0]; n++) {
        if (obtained.format == fmtmap[n][1]) {
            ao->format = fmtmap[n][0];
            break;
        }
    }
    if (!ao->format) {
        if (!ao->probing)
            MP_ERR(ao, "could not find matching format\n");
        uninit(ao);
        return -1;
    }

    if (!ao_chmap_sel_get_def(ao, &sel, &ao->channels, obtained.channels)) {
        uninit(ao);
        return -1;
    }

    ao->samplerate = obtained.freq;

    priv->paused = 1;

    return 1;
}
Beispiel #30
0
Datei: audio.c Projekt: wrl/mpv
static int audio_start_sync(struct MPContext *mpctx, int playsize)
{
    struct ao *ao = mpctx->ao;
    struct MPOpts *opts = mpctx->opts;
    sh_audio_t * const sh_audio = mpctx->sh_audio;
    int res;

    // Timing info may not be set without
    res = decode_audio(sh_audio, &ao->buffer, 1);
    if (res < 0)
        return res;

    int bytes;
    bool did_retry = false;
    double written_pts;
    double bps = ao->bps / opts->playback_speed;
    bool hrseek = mpctx->hrseek_active;   // audio only hrseek
    mpctx->hrseek_active = false;
    while (1) {
        written_pts = written_audio_pts(mpctx);
        double ptsdiff;
        if (hrseek)
            ptsdiff = written_pts - mpctx->hrseek_pts;
        else
            ptsdiff = written_pts - mpctx->sh_video->pts - mpctx->delay
                      - mpctx->audio_delay;
        bytes = ptsdiff * bps;
        bytes -= bytes % (ao->channels.num * af_fmt2bits(ao->format) / 8);

        // ogg demuxers give packets without timing
        if (written_pts <= 1 && sh_audio->pts == MP_NOPTS_VALUE) {
            if (!did_retry) {
                // Try to read more data to see packets that have pts
                res = decode_audio(sh_audio, &ao->buffer, ao->bps);
                if (res < 0)
                    return res;
                did_retry = true;
                continue;
            }
            bytes = 0;
        }

        if (fabs(ptsdiff) > 300 || isnan(ptsdiff))   // pts reset or just broken?
            bytes = 0;

        if (bytes > 0)
            break;

        mpctx->syncing_audio = false;
        int a = MPMIN(-bytes, MPMAX(playsize, 20000));
        res = decode_audio(sh_audio, &ao->buffer, a);
        bytes += ao->buffer.len;
        if (bytes >= 0) {
            memmove(ao->buffer.start,
                    ao->buffer.start + ao->buffer.len - bytes, bytes);
            ao->buffer.len = bytes;
            if (res < 0)
                return res;
            return decode_audio(sh_audio, &ao->buffer, playsize);
        }
        ao->buffer.len = 0;
        if (res < 0)
            return res;
    }
    if (hrseek)
        // Don't add silence in audio-only case even if position is too late
        return 0;
    int fillbyte = 0;
    if ((ao->format & AF_FORMAT_SIGN_MASK) == AF_FORMAT_US)
        fillbyte = 0x80;
    if (bytes >= playsize) {
        /* This case could fall back to the one below with
         * bytes = playsize, but then silence would keep accumulating
         * in a_out_buffer if the AO accepts less data than it asks for
         * in playsize. */
        char *p = malloc(playsize);
        memset(p, fillbyte, playsize);
        write_to_ao(mpctx, p, playsize, 0, written_pts - bytes / bps);
        free(p);
        return ASYNC_PLAY_DONE;
    }
    mpctx->syncing_audio = false;
    decode_audio_prepend_bytes(&ao->buffer, bytes, fillbyte);
    return decode_audio(sh_audio, &ao->buffer, playsize);
}