int PressSensor::setEnable(int32_t handle, int en)
{
	int err = 0;
	int what = press;
    switch(handle){
		case ID_P : what = press; break;
		case ID_T : what = temperature; break;
    }

    if(en)
		mEnabled[what]++;
	else
		mEnabled[what]--;
	if(mEnabled[what] < 0)
		mEnabled[what] = 0;
	if(mEnabled[press] > 0 || mEnabled[temperature] > 0)
		err = enable_sensor();
	else
		err = disable_sensor();
	if (!err) {
            update_delay(what);
    }
	ALOGD("PressSensor mEnabled %d, Temperature mEnabled %d\n",mEnabled[press],mEnabled[temperature]);
    return err;
}
Example #2
0
int KionixSensor::setDelay(int32_t handle, int64_t ns)
{
    if (ns < 0)
        return -EINVAL;

    mDelays = ns;
    return update_delay();
}
int MPLSensor::enable(int32_t handle, int en)
{
    FUNC_LOG;
    //ALOGV("handle : %d en: %d", handle, en);

    int what = -1;

    switch (handle) {
    case ID_A:
        what = Accelerometer;
        break;
    case ID_M:
        what = MagneticField;
        break;
    case ID_O:
        what = Orientation;
        break;
    case ID_GY:
        what = Gyro;
        break;
    case ID_GR:
        what = Gravity;
        break;
    case ID_RV:
        what = RotationVector;
        break;
    case ID_LA:
        what = LinearAccel;
        break;
    default: //this takes care of all the gestures
        what = handle;
        break;
    }

    if (uint32_t(what) >= numSensors)
        return -EINVAL;

    int newState = en ? 1 : 0;
    int err = 0;
    //ALOGV_IF((uint32_t(newState) << what) != (mEnabled & (1 << what)),
    //        "sensor state change what=%d", what);

    pthread_mutex_lock(&mMplMutex);
    if ((uint32_t(newState) << what) != (mEnabled & (1 << what))) {
        uint32_t sensor_type;
        short flags = newState;
        mEnabled &= ~(1 << what);
        mEnabled |= (uint32_t(flags) << what);
        ALOGV_IF(EXTRA_VERBOSE, "mEnabled = %x", mEnabled);
        setPowerStates(mEnabled);
        pthread_mutex_unlock(&mMplMutex);
        if (!newState)
            update_delay();
        return err;
    }
    pthread_mutex_unlock(&mMplMutex);
    return err;
}
int AccelSensor::setDelay(int32_t handle, int64_t ns) {
        if (ns < 0)
                return -EINVAL;
                
#ifdef DEBUG_SENSOR                
        ALOGD("%s: ns = %lld", __func__, ns);
#endif
        mDelay = ns;
        
        return update_delay();
}
int Mma7660fc::enable(int32_t handle, int en)
{
    int what = -1;
    switch (handle) {
    case ID_A:
        what = Accelerometer;
        break;
        //case ID_O: what = Orientation;   break;
    }

    if (uint32_t(what) >= numSensors)
        return -EINVAL;

    int newState = en ? 1 : 0;
    int err = 0;

    ALOGD("Mma7660fc: enable()  newState : %d | mEnabled : %d ", newState, mEnabled);

    if ((uint32_t(newState) << what) != (mEnabled & (1 << what)))
    {
        if (!mEnabled) {
            open_device();
        }

        short flags = newState;

        if ( newState == 1 ) {

            err = ioctl(dev_fd, ECS_IOCTL_START); // , &flags
            err = err < 0 ? -errno : 0;

            ALOGE_IF(err, "Mma7660fc: ECS_IOCTL_START failed (%s) ", strerror(-err));

        } else {

            err = ioctl(dev_fd, ECS_IOCTL_CLOSE); // , &flags
            err = err < 0 ? -errno : 0;

            ALOGE_IF(err, "Mma7660fc: ECS_IOCTL_CLOSE failed (%s) ", strerror(-err));
        }

        if (!err) {
            mEnabled &= ~(1<<what);
            mEnabled |= (uint32_t(flags)<<what);
            update_delay();
        }
        if (!mEnabled) {
            close_device();
        }
    }

    return err;
}
Example #6
0
static int filter_frame(struct af_instance *af, struct mp_audio *audio)
{
    af_ac3enc_t *s = af->priv;

    // filter_output must have been called until no output was produced.
    if (s->pending && s->pending->samples)
        MP_ERR(af, "broken data flow\n");

    talloc_free(s->pending);
    s->pending = audio;
    update_delay(af);
    return 0;
}
int PressSensor::setDelay(int32_t handle, int64_t ns)
{
    if (ns < 0)
        return -EINVAL;
	int what = press;
    switch(handle){
		case ID_P : what = press; break;
		case ID_T : what = temperature; break;
    }

    mDelay[what] = ns;
    return update_delay(what);
}
Example #8
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;
}
Example #9
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;
}
int MPLSensor::setDelay(int32_t handle, int64_t ns)
{
    FUNC_LOG;
    ALOGV_IF(EXTRA_VERBOSE,
            " setDelay handle: %d rate %d", handle, (int) (ns / 1000000LL));
    int what = -1;
    switch (handle) {
    case ID_A:
        what = Accelerometer;
        break;
    case ID_M:
        what = MagneticField;
        break;
    case ID_O:
        what = Orientation;
        break;
    case ID_GY:
        what = Gyro;
        break;
    case ID_GR:
        what = Gravity;
        break;
    case ID_RV:
        what = RotationVector;
        break;
    case ID_LA:
        what = LinearAccel;
        break;
    default:
        what = handle;
        break;
    }

    if (uint32_t(what) >= numSensors)
        return -EINVAL;

    if (ns < 0)
        return -EINVAL;

    pthread_mutex_lock(&mMplMutex);
    mDelays[what] = ns;
    pthread_mutex_unlock(&mMplMutex);
    return update_delay();
}
int Mma7660fc::setDelay(int32_t handle, int64_t ns)
{
    int what = -1;
    switch (handle) {
    case ID_A:
        what = Accelerometer;
        break;
        //case ID_O: what = Orientation;   break;
    }

    if (uint32_t(what) >= numSensors)
        return -EINVAL;

    if (ns < 0)
        return -EINVAL;

    mDelays[what] = ns;
    return update_delay();

}
int AkmSensor::setDelay(int32_t handle, int64_t ns)
{
    int what = -1;
    uint32_t sensor_type = 0;

    if (ns < 0)
        return -EINVAL;

    switch (handle) {
        case ID_A: sensor_type = SENSOR_TYPE_ACCELEROMETER; break;
        case ID_M: sensor_type = SENSOR_TYPE_MAGNETIC_FIELD; break;
        case ID_O: sensor_type = SENSOR_TYPE_ORIENTATION; break;
    }

    if (sensor_type == 0)
        return -EINVAL;

    mDelays[what] = ns;
    return update_delay();
}
Example #13
0
int GS_STSensor::setDelay(int32_t handle, int64_t ns)
{
#ifdef ECS_IOCTL_APP_SET_DELAY
    int what = -1;
    switch (handle) {
        case ID_A: what = Accelerometer; break;
    }

    if (uint32_t(what) >= numSensors)
        return -EINVAL;

    if (ns < 0)
        return -EINVAL;

    mDelays[what] = ns;
    return update_delay();
#else
    return -1;
#endif
}
int AkmSensor::setDelay(int32_t handle, int64_t ns)
{
#ifdef ECS_IOCTL_APP_SET_DELAY
    int what = -1;
    switch (handle) {
        case ID_M: what = MagneticField; break;
        case ID_O: what = Orientation;   break;
    }

    if (uint32_t(what) >= numSensors)
        return -EINVAL;

    if (ns < 0)
        return -EINVAL;

    mDelays[what] = ns;
    return update_delay();
#else
    return -1;
#endif
}
int AkmSensor::enable(int32_t handle, int en)
{
    int what = -1;
    switch (handle) {
        case ID_A: what = Accelerometer; break;
        case ID_M: what = MagneticField; break;
        case ID_O: what = Orientation;   break;
    }

    if (uint32_t(what) >= numSensors)
        return -EINVAL;

    int newState  = en ? 1 : 0;
    int err = 0;

    if ((uint32_t(newState)<<what) != (mEnabled & (1<<what))) {
        if (!mEnabled) {
            open_device();
        }
        int cmd;
        switch (what) {
            case Accelerometer: cmd = ECS_IOCTL_APP_SET_AFLAG;  break;
            case MagneticField: cmd = ECS_IOCTL_APP_SET_MVFLAG; break;
            case Orientation:   cmd = ECS_IOCTL_APP_SET_MFLAG;  break;
        }
        short flags = newState;
        err = ioctl(dev_fd, cmd, &flags);
        err = err<0 ? -errno : 0;
        LOGE_IF(err, "ECS_IOCTL_APP_SET_XXX failed (%s)", strerror(-err));
        if (!err) {
            mEnabled &= ~(1<<what);
            mEnabled |= (uint32_t(flags)<<what);
            update_delay();
        }
        if (!mEnabled) {
            close_device();
        }
    }
    return err;
}
int Hwmsen::setDelay(int32_t handle, int64_t ns)
{
    int what = -1;
	ALOGD("setDelay: (handle=%d, ns=%d)",
                    handle, ns);

	if( handle != ID_ACCELEROMETER && handle != ID_MAGNETIC &&
		handle != ID_ORIENTATION && handle != ID_GYROSCOPE && 
		handle != ID_LIGHT)
	{
	    ALOGD("setDelay: (handle=%d, ns=%d) is not hwmsen driver command", handle, ns);
		return 0;
	}
	
    what = handle;
    if (uint32_t(what) >= numSensors)
        return -EINVAL;

    if (ns < 0)
        return -EINVAL;
    mDelays[what] = ns;
    return update_delay(what);

}
int AccelSensor::setEnable(int32_t handle, int en) {
	int err = 0;
        
	if(handle != ID_A && handle != ID_O && handle != ID_M)
		return -1;
		
	if(en)
		mUser++;
	else{
		mUser--;
		if(mUser < 0)
			mUser = 0;
	}

	if(mUser > 0)
		err = enable_sensor();
	else
		err = disable_sensor();
		
	if(handle == ID_A ) {
		if(en)
         	        mEnabled++;
		else
			mEnabled--;
		if(mEnabled < 0)
			mEnabled = 0;
        }
        
	update_delay();
#ifdef DEBUG_SENSOR
	ALOGD("AccelSensor enable %d ,usercount %d, handle %d ,mEnabled %d, err %d", 
	        en, mUser, handle, mEnabled, err);
#endif

        return 0;
}
Example #18
0
/*
 * FIXME: use linux/kthread.h
 */
static int dvb_frontend_thread(void *data)
{
	struct dvb_frontend *fe = data;
	struct dvb_frontend_private *fepriv = fe->frontend_priv;
	unsigned long timeout;
	char name [15];
	int quality = 0, delay = 3*HZ;
	fe_status_t s;
	int check_wrapped = 0;

	dprintk("%s\n", __FUNCTION__);

	snprintf (name, sizeof(name), "kdvb-fe-%i", fe->dvb->num);

        lock_kernel();
        daemonize(name);
        sigfillset(&current->blocked);
        unlock_kernel();

	fepriv->status = 0;
	dvb_frontend_init(fe);
	fepriv->wakeup = 0;

	while (1) {
		up(&fepriv->sem);	    /* is locked when we enter the thread... */

		timeout = wait_event_interruptible_timeout(fepriv->wait_queue,
							   dvb_frontend_should_wakeup(fe),
							   delay);
		if (0 != dvb_frontend_is_exiting(fe)) {
			/* got signal or quitting */
			break;
		}

		if (current->flags & PF_FREEZE)
			refrigerator(PF_FREEZE);

		if (down_interruptible(&fepriv->sem))
			break;

		/* if we've got no parameters, just keep idling */
		if (fepriv->state & FESTATE_IDLE) {
			delay = 3*HZ;
			quality = 0;
			continue;
		}

		/* get the frontend status */
		if (fepriv->state & FESTATE_RETUNE) {
			s = 0;
		} else {
			if (fe->ops->read_status)
				fe->ops->read_status(fe, &s);
			if (s != fepriv->status) {
				dvb_frontend_add_event(fe, s);
				fepriv->status = s;
			}
		}
		/* if we're not tuned, and we have a lock, move to the TUNED state */
		if ((fepriv->state & FESTATE_WAITFORLOCK) && (s & FE_HAS_LOCK)) {
			update_delay(&quality, &delay, fepriv->min_delay, s & FE_HAS_LOCK);
			fepriv->state = FESTATE_TUNED;

			/* if we're tuned, then we have determined the correct inversion */
			if ((!(fe->ops->info.caps & FE_CAN_INVERSION_AUTO)) &&
			    (fepriv->parameters.inversion == INVERSION_AUTO)) {
				fepriv->parameters.inversion = fepriv->inversion;
			}
			continue;
		}

		/* if we are tuned already, check we're still locked */
		if (fepriv->state & FESTATE_TUNED) {
			update_delay(&quality, &delay, fepriv->min_delay, s & FE_HAS_LOCK);

			/* we're tuned, and the lock is still good... */
			if (s & FE_HAS_LOCK){
				delay = HZ >> 1;    /* kevin_add for speed up update speed */
				continue;
			}
			else {
Example #19
0
/*
 * FIXME: use linux/kthread.h
 */
static int dvb_frontend_thread (void *data)
{
	struct dvb_frontend *fe = (struct dvb_frontend *) data;
	unsigned long timeout;
	char name [15];
	int quality = 0, delay = 3*HZ;
	fe_status_t s;
	int check_wrapped = 0;

	dprintk ("%s\n", __FUNCTION__);

	snprintf (name, sizeof(name), "kdvb-fe-%i", fe->dvb->num);

        lock_kernel ();
        daemonize (name);
        sigfillset (&current->blocked);
        unlock_kernel ();

	fe->status = 0;
	dvb_frontend_init (fe);
	fe->wakeup = 0;

	while (1) {
		up (&fe->sem);      /* is locked when we enter the thread... */

		timeout = wait_event_interruptible_timeout(fe->wait_queue,
							   dvb_frontend_should_wakeup(fe),
							   delay);
		if (0 != dvb_frontend_is_exiting (fe)) {
			/* got signal or quitting */
			break;
		}

		if (current->flags & PF_FREEZE)
			refrigerator(PF_FREEZE);

		if (down_interruptible (&fe->sem))
			break;

		/* if we've got no parameters, just keep idling */
		if (fe->state & FESTATE_IDLE) {
			delay = 3*HZ;
			quality = 0;
			continue;
		}

retune:
		/* get the frontend status */
		if (fe->state & FESTATE_RETUNE) {
			s = 0;
		} else {
			if (fe->ops->read_status)
				fe->ops->read_status(fe, &s);
			if (s != fe->status) {
			dvb_frontend_add_event (fe, s);
				fe->status = s;
			}
		}
		/* if we're not tuned, and we have a lock, move to the TUNED state */
		if ((fe->state & FESTATE_WAITFORLOCK) && (s & FE_HAS_LOCK)) {
			update_delay(&quality, &delay, fe->min_delay, s & FE_HAS_LOCK);
			fe->state = FESTATE_TUNED;

			/* if we're tuned, then we have determined the correct inversion */
			if ((!(fe->ops->info.caps & FE_CAN_INVERSION_AUTO)) &&
			    (fe->parameters.inversion == INVERSION_AUTO)) {
				fe->parameters.inversion = fe->inversion;
			}
			continue;
		}

		/* if we are tuned already, check we're still locked */
		if (fe->state & FESTATE_TUNED) {
			update_delay(&quality, &delay, fe->min_delay, s & FE_HAS_LOCK);

			/* we're tuned, and the lock is still good... */
			if (s & FE_HAS_LOCK)
				continue;
			else {
				/* if we _WERE_ tuned, but now don't have a lock,
				 * need to zigzag */
				fe->state = FESTATE_ZIGZAG_FAST;
				fe->started_auto_step = fe->auto_step;
				check_wrapped = 0;
			}
		}

		/* don't actually do anything if we're in the LOSTLOCK state,
		 * the frontend is set to FE_CAN_RECOVER, and the max_drift is 0 */
		if ((fe->state & FESTATE_LOSTLOCK) && 
		    (fe->ops->info.caps & FE_CAN_RECOVER) && (fe->max_drift == 0)) {
			update_delay(&quality, &delay, fe->min_delay, s & FE_HAS_LOCK);
						continue;
				}
	    
		/* don't do anything if we're in the DISEQC state, since this
		 * might be someone with a motorized dish controlled by DISEQC.
		 * If its actually a re-tune, there will be a SET_FRONTEND soon enough.	*/
		if (fe->state & FESTATE_DISEQC) {
			update_delay(&quality, &delay, fe->min_delay, s & FE_HAS_LOCK);
			continue;
				}

		/* if we're in the RETUNE state, set everything up for a brand
		 * new scan, keeping the current inversion setting, as the next
		 * tune is _very_ likely to require the same */
		if (fe->state & FESTATE_RETUNE) {
			fe->lnb_drift = 0;
			fe->auto_step = 0;
			fe->auto_sub_step = 0;
			fe->started_auto_step = 0;
			check_wrapped = 0;
		}

		/* fast zigzag. */
		if ((fe->state & FESTATE_SEARCHING_FAST) || (fe->state & FESTATE_RETUNE)) {
			delay = fe->min_delay;

			/* peform a tune */
			if (dvb_frontend_autotune(fe, check_wrapped)) {
				/* OK, if we've run out of trials at the fast speed.
				 * Drop back to slow for the _next_ attempt */
				fe->state = FESTATE_SEARCHING_SLOW;
				fe->started_auto_step = fe->auto_step;
				continue;
			}
			check_wrapped = 1;

			/* if we've just retuned, enter the ZIGZAG_FAST state.
			 * This ensures we cannot return from an
			 * FE_SET_FRONTEND ioctl before the first frontend tune
			 * occurs */
			if (fe->state & FESTATE_RETUNE) {
				fe->state = FESTATE_TUNING_FAST;
				goto retune;
			}
		}

		/* slow zigzag */
		if (fe->state & FESTATE_SEARCHING_SLOW) {
			update_delay(&quality, &delay, fe->min_delay, s & FE_HAS_LOCK);
		    
			/* Note: don't bother checking for wrapping; we stay in this
			 * state until we get a lock */
			dvb_frontend_autotune(fe, 0);
		}
	}

	if (dvb_shutdown_timeout) {
		if (dvb_powerdown_on_sleep)
			if (fe->ops->set_voltage)
				fe->ops->set_voltage(fe, SEC_VOLTAGE_OFF);
		if (fe->ops->sleep)
			fe->ops->sleep(fe);
	}

	fe->thread_pid = 0;
	mb();

	dvb_frontend_wakeup(fe);
	return 0;
}
Example #20
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);

#if HAVE_AVCODEC_NEW_CODEC_API
    // 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;
    }
#else
    err = read_input_frame(af, frame);
    if (err < 0)
        goto done;
    if (err == 0)
        goto done;
    err = -1;
    int ok;
    int lavc_ret = avcodec_encode_audio2(s->lavc_actx, &pkt, frame, &ok);
    s->input->samples = 0;
    if (lavc_ret < 0 || !ok) {
        MP_FATAL(af, "Encode failed.\n");
        goto done;
    }
#endif

    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;
}
Example #21
0
static int filter_out(struct af_instance *af)
{
    af_ac3enc_t *s = af->priv;
    if (!fill_buffer(af))
        return 0; // need more input

    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(s->input->num_planes <= AV_NUM_DATA_POINTERS);
    frame->extended_data = frame->data;
    for (int n = 0; n < s->input->num_planes; n++)
        frame->data[n] = s->input->planes[n];
    frame->linesize[0] = s->input->samples * s->input->sstride;

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

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

    struct mp_audio *out =
        mp_audio_pool_get(af->out_pool, af->data, s->out_samples);
    if (!out)
        return -1;
    mp_audio_copy_attributes(out, 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_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, s->pkt.data, s->pkt.size);
    memset(buf + header_len + s->pkt.size, 0,
            frame_size - (header_len + s->pkt.size));
    swap_16((uint16_t *)(buf + header_len), s->pkt.size / 2);
    out->samples = frame_size / out->sstride;
    af_add_output_frame(af, out);
    update_delay(af);
    return 0;
}