Esempio n. 1
0
static int reinit_vs(struct vf_instance *vf)
{
    struct vf_priv_s *p = vf->priv;
    VSMap *vars = NULL, *in = NULL, *out = NULL;
    int res = -1;

    destroy_vs(vf);

    MP_DBG(vf, "initializing...\n");
    p->initializing = true;

    if (p->drv->load_core(vf) < 0 || !p->vsapi || !p->vscore) {
        MP_FATAL(vf, "Could not get vapoursynth API handle.\n");
        goto error;
    }

    in = p->vsapi->createMap();
    out = p->vsapi->createMap();
    vars = p->vsapi->createMap();
    if (!in || !out || !vars)
        goto error;

    p->vsapi->createFilter(in, out, "Input", infiltInit, infiltGetFrame,
                           infiltFree, fmSerial, 0, vf, p->vscore);
    int vserr;
    p->in_node = p->vsapi->propGetNode(out, "clip", 0, &vserr);
    if (!p->in_node) {
        MP_FATAL(vf, "Could not get our own input node.\n");
        goto error;
    }

    if (p->vsapi->propSetNode(vars, "video_in", p->in_node, 0))
        goto error;

    int d_w, d_h;
    mp_image_params_get_dsize(&p->fmt_in, &d_w, &d_h);

    p->vsapi->propSetInt(vars, "video_in_dw", d_w, 0);
    p->vsapi->propSetInt(vars, "video_in_dh", d_h, 0);
    p->vsapi->propSetFloat(vars, "container_fps", vf->chain->container_fps, 0);
    p->vsapi->propSetFloat(vars, "display_fps", vf->chain->display_fps, 0);

    if (p->drv->load(vf, vars) < 0)
        goto error;
    if (!p->out_node) {
        MP_FATAL(vf, "Could not get script output node.\n");
        goto error;
    }

    const VSVideoInfo *vi = p->vsapi->getVideoInfo(p->out_node);
    if (!isConstantFormat(vi)) {
        MP_FATAL(vf, "Video format is required to be constant.\n");
        goto error;
    }

    pthread_mutex_lock(&p->lock);
    p->initializing = false;
    pthread_mutex_unlock(&p->lock);
    MP_DBG(vf, "initialized.\n");
    res = 0;
error:
    if (p->vsapi) {
        p->vsapi->freeMap(in);
        p->vsapi->freeMap(out);
        p->vsapi->freeMap(vars);
    }
    if (res < 0)
        destroy_vs(vf);
    return res;
}
Esempio n. 2
0
static void hotplug_uninit(struct ao *ao)
{
    MP_DBG(ao, "Hotplug uninit\n");
    wasapi_change_uninit(ao);
    CoUninitialize();
}
Esempio n. 3
0
static int dvd_read_sector(stream_t *stream, dvd_priv_t *d, unsigned char *data)
{
  int len;

  if(d->packs_left==0) {
    /**
     * If we're not at the end of this cell, we can determine the next
     * VOBU to display using the VOBU_SRI information section of the
     * DSI.  Using this value correctly follows the current angle,
     * avoiding the doubled scenes in The Matrix, and makes our life
     * really happy.
     *
     * Otherwise, we set our next address past the end of this cell to
     * force the code above to go to the next cell in the program.
     */
    if(d->dsi_pack.vobu_sri.next_vobu != SRI_END_OF_CELL) {
       d->cur_pack= d->dsi_pack.dsi_gi.nv_pck_lbn + ( d->dsi_pack.vobu_sri.next_vobu & 0x7fffffff );
       MP_DBG(stream, "Navi  new pos=0x%X  \n",d->cur_pack);
    } else {
      // end of cell! find next cell!
      MP_VERBOSE(stream, "--- END OF CELL !!! ---\n");
      d->cur_pack=d->cell_last_pack+1;
    }
  }

read_next:
  if(d->cur_pack>d->cell_last_pack) {
    // end of cell!
    int next=dvd_next_cell(stream, d);
    if(next>=0) {
      d->cur_cell=next;
      // if( d->cur_pgc->cell_playback[d->cur_cell].block_type
      // == BLOCK_TYPE_ANGLE_BLOCK ) d->cur_cell+=dvd_angle-1;
      d->cur_pack = d->cur_pgc->cell_playback[ d->cur_cell ].first_sector;
      d->cell_last_pack=d->cur_pgc->cell_playback[ d->cur_cell ].last_sector;
      MP_VERBOSE(stream, "DVD next cell: %d  pack: 0x%X-0x%X  \n",d->cur_cell,d->cur_pack,d->cell_last_pack);
    } else
        return -1; // EOF
  }

  len = DVDReadBlocks(d->title, d->cur_pack, 1, data);
  // only == 0 should indicate an error, but some dvdread version are buggy when used with dvdcss
  if(len <= 0) return -1; //error

  if(data[38]==0 && data[39]==0 && data[40]==1 && data[41]==0xBF &&
    data[1024]==0 && data[1025]==0 && data[1026]==1 && data[1027]==0xBF) {
       // found a Navi packet!!!
#if DVDREAD_VERSION >= LIBDVDREAD_VERSION(0,9,0)
    navRead_DSI(&d->dsi_pack, &(data[ DSI_START_BYTE ]));
#else
    navRead_DSI(&d->dsi_pack, &(data[ DSI_START_BYTE ]), sizeof(dsi_t));
#endif
    if(d->cur_pack != d->dsi_pack.dsi_gi.nv_pck_lbn ) {
      MP_VERBOSE(stream, "Invalid NAVI packet! lba=0x%X  navi=0x%X  \n",
        d->cur_pack,d->dsi_pack.dsi_gi.nv_pck_lbn);
    } else {
      // process!
      d->packs_left = d->dsi_pack.dsi_gi.vobu_ea;
      MP_DBG(stream, "Found NAVI packet! lba=0x%X  len=%d  \n",d->cur_pack,d->packs_left);
      //navPrint_DSI(&d->dsi_pack);
      MP_TRACE(stream, "\r### CELL %d: Navi: %d/%d  IFO: %d/%d   \n",d->cur_cell,
        d->dsi_pack.dsi_gi.vobu_c_idn,d->dsi_pack.dsi_gi.vobu_vob_idn,
        d->cur_pgc->cell_position[d->cur_cell].cell_nr,
        d->cur_pgc->cell_position[d->cur_cell].vob_id_nr);

      if(d->angle_seek) {
        int i,skip=0;
        for(i=0;i<9;i++)        // check if all values zero:
          if((skip=d->dsi_pack.sml_agli.data[i].address)!=0) break;
        if(skip && skip!=0x7fffffff) {
          // sml_agli table has valid data (at least one non-zero):
         d->cur_pack=d->dsi_pack.dsi_gi.nv_pck_lbn+
         d->dsi_pack.sml_agli.data[d->dvd_angle-1].address;
         d->angle_seek=0;
         d->cur_pack--;
         MP_VERBOSE(stream, "Angle-seek synced using sml_agli map!  new_lba=0x%X  \n",d->cur_pack);
        } else {
          // check if we're in the right cell, jump otherwise:
          if( (d->dsi_pack.dsi_gi.vobu_c_idn==d->cur_pgc->cell_position[d->cur_cell].cell_nr) &&
            (d->dsi_pack.dsi_gi.vobu_vob_idn==d->cur_pgc->cell_position[d->cur_cell].vob_id_nr) ){
            d->angle_seek=0;
            MP_VERBOSE(stream, "Angle-seek synced by cell/vob IDN search!  \n");
          } else {
            // wrong angle, skip this vobu:
            d->cur_pack=d->dsi_pack.dsi_gi.nv_pck_lbn+
            d->dsi_pack.dsi_gi.vobu_ea;
            d->angle_seek=2; // DEBUG
          }
        }
      }
    }
    ++d->cur_pack;
    goto read_next;
  }

  ++d->cur_pack;
  if(d->packs_left>=0) --d->packs_left;

  if(d->angle_seek) {
    if(d->angle_seek==2) MP_VERBOSE(stream, "!!! warning! reading packet while angle_seek !!!\n");
    goto read_next; // searching for Navi packet
  }

  return d->cur_pack-1;
}
Esempio n. 4
0
static void VS_CC infiltInit(VSMap *in, VSMap *out, void **instanceData,
                             VSNode *node, VSCore *core, const VSAPI *vsapi)
{
    struct vf_instance *vf = *instanceData;
    struct vf_priv_s *p = vf->priv;
    // The number of frames of our input node is obviously unknown. The user
    // could for example seek any time, randomly "ending" the clip.
    // This specific value was suggested by the VapourSynth developer.
    int enough_for_everyone = INT_MAX / 16;

    // Note: this is called from createFilter, so no need for locking.

    VSVideoInfo fmt = {
        .format = p->vsapi->getFormatPreset(mp_to_vs(p->fmt_in.imgfmt), p->vscore),
        .width = p->fmt_in.w,
        .height = p->fmt_in.h,
        .numFrames = enough_for_everyone,
    };
    if (!fmt.format) {
        p->vsapi->setError(out, "Unsupported input format.\n");
        return;
    }

    p->vsapi->setVideoInfo(&fmt, 1, node);
    p->in_node_active = true;
}

static const VSFrameRef *VS_CC infiltGetFrame(int frameno, int activationReason,
    void **instanceData, void **frameData,
    VSFrameContext *frameCtx, VSCore *core,
    const VSAPI *vsapi)
{
    struct vf_instance *vf = *instanceData;
    struct vf_priv_s *p = vf->priv;
    VSFrameRef *ret = NULL;

    pthread_mutex_lock(&p->lock);
    MP_DBG(vf, "VS asking for frame %d (at %d)\n", frameno, p->in_frameno);
    while (1) {
        if (p->shutdown) {
            p->vsapi->setFilterError("EOF or filter reinit/uninit", frameCtx);
            MP_DBG(vf, "returning error on EOF/reset\n");
            break;
        }
        if (p->initializing) {
            MP_WARN(vf, "Frame requested during init! This is unsupported.\n"
                        "Returning black dummy frame with 0 duration.\n");
            ret = alloc_vs_frame(p, &vf->fmt_in);
            if (!ret) {
                p->vsapi->setFilterError("Could not allocate VS frame", frameCtx);
                break;
            }
            struct mp_image vsframe = map_vs_frame(p, ret, true);
            mp_image_clear(&vsframe, 0, 0, vf->fmt_in.w, vf->fmt_in.h);
            struct mp_image dummy = {0};
            mp_image_set_params(&dummy, &vf->fmt_in);
            set_vs_frame_props(p, ret, &dummy, 0, 1);
            break;
        }
        if (frameno < p->in_frameno) {
            char msg[180];
            snprintf(msg, sizeof(msg),
                "Frame %d requested, but only have frames starting from %d. "
                "Try increasing the buffered-frames suboption.",
                frameno, p->in_frameno);
            MP_FATAL(vf, "%s\n", msg);
            p->vsapi->setFilterError(msg, frameCtx);
            break;
        }
        if (frameno >= p->in_frameno + MP_TALLOC_AVAIL(p->buffered)) {
            // Too far in the future. Remove frames, so that the main thread can
            // queue new frames.
            if (p->num_buffered) {
                drain_oldest_buffered_frame(p);
                pthread_cond_broadcast(&p->wakeup);
                if (vf->chain->wakeup_callback)
                    vf->chain->wakeup_callback(vf->chain->wakeup_callback_ctx);
                continue;
            }
        }
        if (frameno >= p->in_frameno + p->num_buffered) {
            // If we think EOF was reached, don't wait for new input, and assume
            // the VS filter has reached EOF.
            if (p->eof) {
                p->shutdown = true;
                continue;
            }
        }
        if (frameno < p->in_frameno + p->num_buffered) {
            struct mp_image *img = p->buffered[frameno - p->in_frameno];
            ret = alloc_vs_frame(p, &img->params);
            if (!ret) {
                p->vsapi->setFilterError("Could not allocate VS frame", frameCtx);
                break;
            }
            struct mp_image vsframe = map_vs_frame(p, ret, true);
            mp_image_copy(&vsframe, img);
            int res = 1e6;
            int dur = img->pts * res + 0.5;
            set_vs_frame_props(p, ret, img, dur, res);
            break;
        }
        pthread_cond_wait(&p->wakeup, &p->lock);
    }
    pthread_cond_broadcast(&p->wakeup);
    pthread_mutex_unlock(&p->lock);
    return ret;
}

static void VS_CC infiltFree(void *instanceData, VSCore *core, const VSAPI *vsapi)
{
    struct vf_instance *vf = instanceData;
    struct vf_priv_s *p = vf->priv;

    pthread_mutex_lock(&p->lock);
    p->in_node_active = false;
    pthread_cond_broadcast(&p->wakeup);
    pthread_mutex_unlock(&p->lock);
}

// number of getAsyncFrame calls in progress
// must be called with p->lock held
static int num_requested(struct vf_priv_s *p)
{
    int r = 0;
    for (int n = 0; n < p->max_requests; n++)
        r += p->requested[n] == &dummy_img;
    return r;
}
Esempio n. 5
0
// Initialization and runtime control
static int control(struct af_instance *af, int cmd, void *arg)
{
    af_scaletempo_t *s = af->priv;
    switch (cmd) {
    case AF_CONTROL_REINIT: {
        struct mp_audio *data = (struct mp_audio *)arg;
        float srate = data->rate / 1000;
        int nch = data->nch;
        int use_int = 0;

        MP_VERBOSE(af, "[scaletempo] %.3f speed * %.3f scale_nominal = %.3f\n",
               s->speed, s->scale_nominal, s->scale);

        mp_audio_force_interleaved_format(data);
        mp_audio_copy_config(af->data, data);

        if (s->scale == 1.0) {
            if (s->speed_tempo && s->speed_pitch)
                return AF_DETACH;
            af->delay = 0;
            af->mul = 1;
            return af_test_output(af, data);
        }

        if (data->format == AF_FORMAT_S16) {
            use_int = 1;
        } else {
            mp_audio_set_format(af->data, AF_FORMAT_FLOAT);
        }
        int bps = af->data->bps;

        s->frames_stride        = srate * s->ms_stride;
        s->bytes_stride         = s->frames_stride * bps * nch;
        s->frames_stride_scaled = s->scale * s->frames_stride;
        s->frames_stride_error  = 0;
        af->mul = 1.0 / s->scale;
        af->delay = 0;

        int frames_overlap = s->frames_stride * s->percent_overlap;
        if (frames_overlap <= 0) {
            s->bytes_standing   = s->bytes_stride;
            s->samples_standing = s->bytes_standing / bps;
            s->output_overlap   = NULL;
            s->bytes_overlap    = 0;
        } else {
            s->samples_overlap  = frames_overlap * nch;
            s->bytes_overlap    = frames_overlap * nch * bps;
            s->bytes_standing   = s->bytes_stride - s->bytes_overlap;
            s->samples_standing = s->bytes_standing / bps;
            s->buf_overlap      = realloc(s->buf_overlap, s->bytes_overlap);
            s->table_blend      = realloc(s->table_blend, s->bytes_overlap * 4);
            if (!s->buf_overlap || !s->table_blend) {
                MP_FATAL(af, "[scaletempo] Out of memory\n");
                return AF_ERROR;
            }
            memset(s->buf_overlap, 0, s->bytes_overlap);
            if (use_int) {
                int32_t *pb = s->table_blend;
                int64_t blend = 0;
                for (int i = 0; i < frames_overlap; i++) {
                    int32_t v = blend / frames_overlap;
                    for (int j = 0; j < nch; j++)
                        *pb++ = v;
                    blend += 65536; // 2^16
                }
                s->output_overlap = output_overlap_s16;
            } else {
                float *pb = s->table_blend;
                for (int i = 0; i < frames_overlap; i++) {
                    float v = i / (float)frames_overlap;
                    for (int j = 0; j < nch; j++)
                        *pb++ = v;
                }
                s->output_overlap = output_overlap_float;
            }
        }

        s->frames_search = (frames_overlap > 1) ? srate * s->ms_search : 0;
        if (s->frames_search <= 0)
            s->best_overlap_offset = NULL;
        else {
            if (use_int) {
                int64_t t = frames_overlap;
                int32_t n = 8589934588LL / (t * t); // 4 * (2^31 - 1) / t^2
                s->buf_pre_corr = realloc(s->buf_pre_corr,
                                          s->bytes_overlap * 2 + UNROLL_PADDING);
                s->table_window = realloc(s->table_window,
                                          s->bytes_overlap * 2 - nch * bps * 2);
                if (!s->buf_pre_corr || !s->table_window) {
                    MP_FATAL(af, "[scaletempo] Out of memory\n");
                    return AF_ERROR;
                }
                memset((char *)s->buf_pre_corr + s->bytes_overlap * 2, 0,
                       UNROLL_PADDING);
                int32_t *pw = s->table_window;
                for (int i = 1; i < frames_overlap; i++) {
                    int32_t v = (i * (t - i) * n) >> 15;
                    for (int j = 0; j < nch; j++)
                        *pw++ = v;
                }
                s->best_overlap_offset = best_overlap_offset_s16;
            } else {
                s->buf_pre_corr = realloc(s->buf_pre_corr, s->bytes_overlap);
                s->table_window = realloc(s->table_window,
                                          s->bytes_overlap - nch * bps);
                if (!s->buf_pre_corr || !s->table_window) {
                    MP_FATAL(af, "[scaletempo] Out of memory\n");
                    return AF_ERROR;
                }
                float *pw = s->table_window;
                for (int i = 1; i < frames_overlap; i++) {
                    float v = i * (frames_overlap - i);
                    for (int j = 0; j < nch; j++)
                        *pw++ = v;
                }
                s->best_overlap_offset = best_overlap_offset_float;
            }
        }

        s->bytes_per_frame = bps * nch;
        s->num_channels    = nch;

        s->bytes_queue = (s->frames_search + s->frames_stride + frames_overlap)
                         * bps * nch;
        s->buf_queue = realloc(s->buf_queue, s->bytes_queue + UNROLL_PADDING);
        if (!s->buf_queue) {
            MP_FATAL(af, "[scaletempo] Out of memory\n");
            return AF_ERROR;
        }

        s->bytes_queued = 0;
        s->bytes_to_slide = 0;

        MP_DBG(af, "[scaletempo] "
               "%.2f stride_in, %i stride_out, %i standing, "
               "%i overlap, %i search, %i queue, %s mode\n",
               s->frames_stride_scaled,
               (int)(s->bytes_stride / nch / bps),
               (int)(s->bytes_standing / nch / bps),
               (int)(s->bytes_overlap / nch / bps),
               s->frames_search,
               (int)(s->bytes_queue / nch / bps),
               (use_int ? "s16" : "float"));

        return af_test_output(af, (struct mp_audio *)arg);
    }
    case AF_CONTROL_SET_PLAYBACK_SPEED: {
        if (s->speed_tempo) {
            if (s->speed_pitch)
                break;
            s->speed = *(double *)arg;
            s->scale = s->speed * s->scale_nominal;
        } else {
            if (s->speed_pitch) {
                s->speed = 1 / *(double *)arg;
                s->scale = s->speed * s->scale_nominal;
                break;
            }
        }
        return AF_OK;
    }
    case AF_CONTROL_RESET:
        s->bytes_queued = 0;
        s->bytes_to_slide = 0;
        s->frames_stride_error = 0;
        memset(s->buf_overlap, 0, s->bytes_overlap);
    }
Esempio n. 6
0
static int filter_out(struct af_instance *af)
{
    af_ac3enc_t *s = af->priv;

    if (!s->pending)
        return 0;

    AVFrame *frame = av_frame_alloc();
    if (!frame) {
        MP_FATAL(af, "Could not allocate memory \n");
        return -1;
    }
    int err = -1;

    AVPacket pkt = {0};
    av_init_packet(&pkt);

    // Send input as long as it wants.
    while (1) {
        err = read_input_frame(af, frame);
        if (err < 0)
            goto done;
        if (err == 0)
            break;
        err = -1;
        int lavc_ret = avcodec_send_frame(s->lavc_actx, frame);
        // On EAGAIN, we're supposed to read remaining output.
        if (lavc_ret == AVERROR(EAGAIN))
            break;
        if (lavc_ret < 0) {
            MP_FATAL(af, "Encode failed.\n");
            goto done;
        }
        s->encoder_buffered += s->input->samples;
        s->input->samples = 0;
    }
    int lavc_ret = avcodec_receive_packet(s->lavc_actx, &pkt);
    if (lavc_ret == AVERROR(EAGAIN)) {
        // Need to buffer more input.
        err = 0;
        goto done;
    }
    if (lavc_ret < 0) {
        MP_FATAL(af, "Encode failed.\n");
        goto done;
    }

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

    s->encoder_buffered -= AC3_FRAME_SIZE;

    struct mp_audio *out =
        mp_audio_pool_get(af->out_pool, af->data, s->out_samples);
    if (!out)
        goto done;
    mp_audio_copy_attributes(out, s->pending);

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

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

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

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

    if (frame_size > out->samples * out->sstride)
        abort();

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

    err = 0;
done:
    av_packet_unref(&pkt);
    av_frame_free(&frame);
    update_delay(af);
    return err;
}
Esempio n. 7
0
// Initialization and runtime control
static int control(struct af_instance *af, int cmd, void *arg)
{
    af_ac3enc_t *s  = af->priv;
    static const int default_bit_rate[AC3_MAX_CHANNELS+1] = \
        {0, 96000, 192000, 256000, 384000, 448000, 448000};

    switch (cmd){
    case AF_CONTROL_REINIT: {
        struct mp_audio *in = arg;
        struct mp_audio orig_in = *in;

        if (!af_fmt_is_pcm(in->format) || in->nch < s->cfg_min_channel_num)
            return AF_DETACH;

        // At least currently, the AC3 encoder doesn't export sample rates.
        in->rate = 48000;
        select_encode_format(s->lavc_actx, in);

        af->data->rate = in->rate;
        mp_audio_set_format(af->data, AF_FORMAT_S_AC3);
        mp_audio_set_num_channels(af->data, 2);

        if (!mp_audio_config_equals(in, &orig_in))
            return AF_FALSE;

        if (s->cfg_add_iec61937_header) {
            s->out_samples = AC3_FRAME_SIZE;
        } else {
            s->out_samples = AC3_MAX_CODED_FRAME_SIZE / af->data->sstride;
        }

        mp_audio_copy_config(s->input, in);

        talloc_free(s->pending);
        s->pending = NULL;

        MP_DBG(af, "reinit: %d, %d, %d.\n", in->nch, in->rate, s->in_samples);

        int bit_rate = s->bit_rate ? s->bit_rate : default_bit_rate[in->nch];

        if (s->lavc_actx->channels != in->nch ||
            s->lavc_actx->sample_rate != in->rate ||
            s->lavc_actx->bit_rate != bit_rate)
        {
            avcodec_close(s->lavc_actx);

            // Put sample parameters
            s->lavc_actx->sample_fmt = af_to_avformat(in->format);
            s->lavc_actx->channels = in->nch;
            s->lavc_actx->channel_layout = mp_chmap_to_lavc(&in->channels);
            s->lavc_actx->sample_rate = in->rate;
            s->lavc_actx->bit_rate = bit_rate;

            if (avcodec_open2(s->lavc_actx, s->lavc_acodec, NULL) < 0) {
                MP_ERR(af, "Couldn't open codec %s, br=%d.\n", "ac3", bit_rate);
                return AF_ERROR;
            }

            if (s->lavc_actx->frame_size < 1) {
                MP_ERR(af, "encoder didn't specify input frame size\n");
                return AF_ERROR;
            }
        }
        s->in_samples = s->lavc_actx->frame_size;
        mp_audio_realloc(s->input, s->in_samples);
        s->input->samples = 0;
        s->encoder_buffered = 0;
        return AF_OK;
    }
    case AF_CONTROL_RESET:
        if (avcodec_is_open(s->lavc_actx))
            avcodec_flush_buffers(s->lavc_actx);
        talloc_free(s->pending);
        s->pending = NULL;
        s->input->samples = 0;
        s->encoder_buffered = 0;
        return AF_OK;
    }
    return AF_UNKNOWN;
}
Esempio n. 8
0
File: ao_alsa.c Progetto: DZW314/mpv
static int control(struct ao *ao, enum aocontrol cmd, void *arg)
{
    struct priv *p = ao->priv;
    snd_mixer_t *handle = NULL;
    switch (cmd) {
    case AOCONTROL_GET_MUTE:
    case AOCONTROL_SET_MUTE:
    case AOCONTROL_GET_VOLUME:
    case AOCONTROL_SET_VOLUME:
    {
        int err;
        snd_mixer_elem_t *elem;
        snd_mixer_selem_id_t *sid;

        long pmin, pmax;
        long get_vol, set_vol;
        float f_multi;

        if (!af_fmt_is_pcm(ao->format))
            return CONTROL_FALSE;

        snd_mixer_selem_id_alloca(&sid);

        snd_mixer_selem_id_set_index(sid, p->cfg_mixer_index);
        snd_mixer_selem_id_set_name(sid, p->cfg_mixer_name);

        err = snd_mixer_open(&handle, 0);
        CHECK_ALSA_ERROR("Mixer open error");

        err = snd_mixer_attach(handle, p->cfg_mixer_device);
        CHECK_ALSA_ERROR("Mixer attach error");

        err = snd_mixer_selem_register(handle, NULL, NULL);
        CHECK_ALSA_ERROR("Mixer register error");

        err = snd_mixer_load(handle);
        CHECK_ALSA_ERROR("Mixer load error");

        elem = snd_mixer_find_selem(handle, sid);
        if (!elem) {
            MP_VERBOSE(ao, "Unable to find simple control '%s',%i.\n",
                       snd_mixer_selem_id_get_name(sid),
                       snd_mixer_selem_id_get_index(sid));
            goto alsa_error;
        }

        snd_mixer_selem_get_playback_volume_range(elem, &pmin, &pmax);
        f_multi = (100 / (float)(pmax - pmin));

        switch (cmd) {
        case AOCONTROL_SET_VOLUME: {
            ao_control_vol_t *vol = arg;
            set_vol = vol->left / f_multi + pmin + 0.5;

            err = snd_mixer_selem_set_playback_volume
                    (elem, SND_MIXER_SCHN_FRONT_LEFT, set_vol);
            CHECK_ALSA_ERROR("Error setting left channel");
            MP_DBG(ao, "left=%li, ", set_vol);

            set_vol = vol->right / f_multi + pmin + 0.5;

            err = snd_mixer_selem_set_playback_volume
                    (elem, SND_MIXER_SCHN_FRONT_RIGHT, set_vol);
            CHECK_ALSA_ERROR("Error setting right channel");
            MP_DBG(ao, "right=%li, pmin=%li, pmax=%li, mult=%f\n",
                   set_vol, pmin, pmax, f_multi);
            break;
        }
        case AOCONTROL_GET_VOLUME: {
            ao_control_vol_t *vol = arg;
            snd_mixer_selem_get_playback_volume
                (elem, SND_MIXER_SCHN_FRONT_LEFT, &get_vol);
            vol->left = (get_vol - pmin) * f_multi;
            snd_mixer_selem_get_playback_volume
                (elem, SND_MIXER_SCHN_FRONT_RIGHT, &get_vol);
            vol->right = (get_vol - pmin) * f_multi;
            MP_DBG(ao, "left=%f, right=%f\n", vol->left, vol->right);
            break;
        }
        case AOCONTROL_SET_MUTE: {
            bool *mute = arg;
            if (!snd_mixer_selem_has_playback_switch(elem))
                goto alsa_error;
            if (!snd_mixer_selem_has_playback_switch_joined(elem)) {
                snd_mixer_selem_set_playback_switch
                    (elem, SND_MIXER_SCHN_FRONT_RIGHT, !*mute);
            }
            snd_mixer_selem_set_playback_switch
                (elem, SND_MIXER_SCHN_FRONT_LEFT, !*mute);
            break;
        }
        case AOCONTROL_GET_MUTE: {
            bool *mute = arg;
            if (!snd_mixer_selem_has_playback_switch(elem))
                goto alsa_error;
            int tmp = 1;
            snd_mixer_selem_get_playback_switch
                (elem, SND_MIXER_SCHN_FRONT_LEFT, &tmp);
            *mute = !tmp;
            if (!snd_mixer_selem_has_playback_switch_joined(elem)) {
                snd_mixer_selem_get_playback_switch
                    (elem, SND_MIXER_SCHN_FRONT_RIGHT, &tmp);
                *mute &= !tmp;
            }
            break;
        }
        }
        snd_mixer_close(handle);
        return CONTROL_OK;
    }

    } //end switch
    return CONTROL_UNKNOWN;

alsa_error:
    if (handle)
        snd_mixer_close(handle);
    return CONTROL_ERROR;
}
Esempio n. 9
0
static int reconfig(struct vf_instance *vf, struct mp_image_params *in,
                    struct mp_image_params *out)
{
    int width = in->w, height = in->h, d_width = in->d_w, d_height = in->d_h;
    unsigned int outfmt = in->imgfmt;
    unsigned int best = find_best_out(vf, outfmt);
    int round_w = 0, round_h = 0;

    if (!best) {
        MP_WARN(vf, "SwScale: no supported outfmt found :(\n");
        return -1;
    }

    vf->next->query_format(vf->next, best);

    vf->priv->w = vf->priv->cfg_w;
    vf->priv->h = vf->priv->cfg_h;

    if (vf->priv->w <= -8) {
        vf->priv->w += 8;
        round_w = 1;
    }
    if (vf->priv->h <= -8) {
        vf->priv->h += 8;
        round_h = 1;
    }

    if (vf->priv->w < -3 || vf->priv->h < -3 ||
        (vf->priv->w < -1 && vf->priv->h < -1))
    {
        // TODO: establish a direct connection to the user's brain
        // and find out what the heck he thinks MPlayer should do
        // with this nonsense.
        MP_ERR(vf, "SwScale: EUSERBROKEN Check your parameters, they make no sense!\n");
        return -1;
    }

    if (vf->priv->w == -1)
        vf->priv->w = width;
    if (vf->priv->w == 0)
        vf->priv->w = d_width;

    if (vf->priv->h == -1)
        vf->priv->h = height;
    if (vf->priv->h == 0)
        vf->priv->h = d_height;

    if (vf->priv->w == -3)
        vf->priv->w = vf->priv->h * width / height;
    if (vf->priv->w == -2)
        vf->priv->w = vf->priv->h * d_width / d_height;

    if (vf->priv->h == -3)
        vf->priv->h = vf->priv->w * height / width;
    if (vf->priv->h == -2)
        vf->priv->h = vf->priv->w * d_height / d_width;

    if (round_w)
        vf->priv->w = ((vf->priv->w + 8) / 16) * 16;
    if (round_h)
        vf->priv->h = ((vf->priv->h + 8) / 16) * 16;

    // check for upscaling, now that all parameters had been applied
    if (vf->priv->noup) {
        if ((vf->priv->w > width) + (vf->priv->h > height) >= vf->priv->noup) {
            vf->priv->w = width;
            vf->priv->h = height;
        }
    }

    MP_DBG(vf, "SwScale: scaling %dx%d %s to %dx%d %s  \n",
           width, height, vo_format_name(outfmt), vf->priv->w, vf->priv->h,
           vo_format_name(best));

    // Compute new d_width and d_height, preserving aspect
    // while ensuring that both are >= output size in pixels.
    if (vf->priv->h * d_width > vf->priv->w * d_height) {
        d_width = vf->priv->h * d_width / d_height;
        d_height = vf->priv->h;
    } else {
        d_height = vf->priv->w * d_height / d_width;
        d_width = vf->priv->w;
    }

    *out = *in;
    out->w = vf->priv->w;
    out->h = vf->priv->h;
    out->d_w = d_width;
    out->d_h = d_height;
    out->imgfmt = best;

    // Second-guess what libswscale is going to output and what not.
    // It depends what libswscale supports for in/output, and what makes sense.
    struct mp_imgfmt_desc s_fmt = mp_imgfmt_get_desc(in->imgfmt);
    struct mp_imgfmt_desc d_fmt = mp_imgfmt_get_desc(out->imgfmt);
    // keep colorspace settings if the data stays in yuv
    if (!(s_fmt.flags & MP_IMGFLAG_YUV) || !(d_fmt.flags & MP_IMGFLAG_YUV)) {
        out->colorspace = MP_CSP_AUTO;
        out->colorlevels = MP_CSP_LEVELS_AUTO;
    }
    mp_image_params_guess_csp(out);

    mp_sws_set_from_cmdline(vf->priv->sws, vf->chain->opts->vo.sws_opts);
    vf->priv->sws->flags |= vf->priv->v_chr_drop << SWS_SRC_V_CHR_DROP_SHIFT;
    vf->priv->sws->flags |= vf->priv->accurate_rnd * SWS_ACCURATE_RND;
    vf->priv->sws->src = *in;
    vf->priv->sws->dst = *out;

    if (mp_sws_reinit(vf->priv->sws) < 0) {
        // error...
        MP_WARN(vf, "Couldn't init libswscale for this setup\n");
        return -1;
    }
    return 0;
}