bool
protocol_send(uint16_t address, uint16_t command, sent_cb_t* cb)
{
	// gpiote0 (toggles gpio)
	NRF_GPIOTE->POWER = GPIOTE_POWER_POWER_Enabled << GPIOTE_POWER_POWER_Pos;
	nrf_gpiote_task_config(0, context.led_pin, NRF_GPIOTE_POLARITY_TOGGLE, NRF_GPIOTE_INITIAL_VALUE_LOW);

	if (context.state != PROTOCOL_STATE_IDLE) {
		return false;
	}
	context.state = PROTOCOL_STATE_PREAMBLE_DONE;
	context.address = address;
	context.command = command;
	context.cb = cb;
	NRF_POWER->TASKS_CONSTLAT = 1; // PAN 11 "HFCLK: Base current with HFCLK running is too high"
	NRF_RTC1->TASKS_STOP = 1;
	NRF_RTC1->TASKS_CLEAR = 1;
	NRF_RTC1->PRESCALER = ROUNDED_DIV(LFCLK_FREQUENCY,
		ROUNDED_DIV(1000000,
			context.protocol->preamble.leader + context.protocol->preamble.pause - RTC_TASK_JITTER
			)) - 1;
	NRF_RTC1->CC[0] = 1;
	NRF_RTC1->TASKS_START = 1;
	pulse(ROUNDED_DIV(context.protocol->preamble.leader, context.protocol->pulse_width));
	return true;
}
Exemplo n.º 2
0
int16_t timer_start(int16_t id, uint32_t us)
{
	uint32_t ticks;

	if (id < 0)
		return -EINVAL;

	if (!timers[id].enabled)
		return -EINVAL;

	if (timers[id].active)
		return -EALREADY;

	ticks = ROUNDED_DIV((uint64_t)us * HFCLK, TIMER_SECONDS(1)
					* ROUNDED_DIV(2 << TIMER_PRESCALER, 2));

	timers[id].active = 1;
	timers[id].ticks = ticks;

	update_cc(id, (uint64_t) ticks);

	if (active == 0) {
		NRF_TIMER0->TASKS_START = 1UL;
	}

	active++;

	return 0;
}
Exemplo n.º 3
0
static void adx_encode(ADXContext *c, uint8_t *adx, const int16_t *wav,
                       ADXChannelState *prev, int channels)
{
    PutBitContext pb;
    int scale;
    int i, j;
    int s0, s1, s2, d;
    int max = 0;
    int min = 0;

    s1 = prev->s1;
    s2 = prev->s2;
    for (i = 0, j = 0; j < 32; i += channels, j++) {
        s0 = wav[i];
        d = ((s0 << COEFF_BITS) - c->coeff[0] * s1 - c->coeff[1] * s2) >> COEFF_BITS;
        if (max < d)
            max = d;
        if (min > d)
            min = d;
        s2 = s1;
        s1 = s0;
    }

    if (max == 0 && min == 0) {
        prev->s1 = s1;
        prev->s2 = s2;
        memset(adx, 0, BLOCK_SIZE);
        return;
    }

    if (max / 7 > -min / 8)
        scale = max / 7;
    else
        scale = -min / 8;

    if (scale == 0)
        scale = 1;

    AV_WB16(adx, scale);

    init_put_bits(&pb, adx + 2, 16);

    s1 = prev->s1;
    s2 = prev->s2;
    for (i = 0, j = 0; j < 32; i += channels, j++) {
        d = ((wav[i] << COEFF_BITS) - c->coeff[0] * s1 - c->coeff[1] * s2) >> COEFF_BITS;

        d = av_clip(ROUNDED_DIV(d, scale), -8, 7);

        put_sbits(&pb, 4, d);

        s0 = ((d << COEFF_BITS) * scale + c->coeff[0] * s1 + c->coeff[1] * s2) >> COEFF_BITS;
        s2 = s1;
        s1 = s0;
    }
    prev->s1 = s1;
    prev->s2 = s2;

    flush_put_bits(&pb);
}
Exemplo n.º 4
0
/*
 * Setup the systick timer to generate the tick interrupts at the required
 * frequency.
 */
void vPortSetupTimerInterrupt( void )
{
    /* Set interrupt priority */
    NVIC_SetPriority(SysTick_IRQn, configKERNEL_INTERRUPT_PRIORITY);
    /* Configure SysTick to interrupt at the requested rate. */
    SysTick->LOAD = ROUNDED_DIV(configSYSTICK_CLOCK_HZ, configTICK_RATE_HZ) - 1UL;
    SysTick->CTRL = ( portNVIC_SYSTICK_CLK_BIT | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk );
}
void
protocol_init(struct ir_protocol *protocol, uint8_t led_pin, struct rtc_ctx *c)
{
	ctx = c;
	context.protocol = protocol;
	context.led_pin = led_pin;

	// low freq clock
	NRF_CLOCK->LFCLKSRC = (CLOCK_LFCLKSRC_SRC_Xtal << CLOCK_LFCLKSRC_SRC_Pos);
	NRF_CLOCK->EVENTS_LFCLKSTARTED = 0;
	NRF_CLOCK->TASKS_LFCLKSTART = 1;
	while (NRF_CLOCK->EVENTS_LFCLKSTARTED == 0)
		/* NOTHING */;
	NRF_CLOCK->EVENTS_LFCLKSTARTED = 0;

	// rtc1 interrupt
	sd_nvic_ClearPendingIRQ(RTC1_IRQn);
	sd_nvic_SetPriority(RTC1_IRQn, NRF_APP_PRIORITY_LOW);
	sd_nvic_EnableIRQ(RTC1_IRQn);
	NRF_RTC1->EVTENSET = RTC_EVTENSET_COMPARE0_Msk;
	NRF_RTC1->INTENSET = RTC_INTENSET_COMPARE0_Msk;

	// high freq clock
	sd_clock_hfclk_request();

	// timer1
	NRF_TIMER1->TASKS_STOP = 1;
	NRF_TIMER1->TASKS_CLEAR = 1;
	NRF_TIMER1->PRESCALER = 4;
	NRF_TIMER1->MODE = TIMER_MODE_MODE_Timer;
	NRF_TIMER1->BITMODE = TIMER_BITMODE_BITMODE_16Bit;
	NRF_TIMER1->SHORTS = TIMER_SHORTS_COMPARE2_CLEAR_Msk;
	NRF_TIMER1->CC[0] = 1;
	NRF_TIMER1->CC[1] = ROUNDED_DIV(context.protocol->pulse_width, 3);
	NRF_TIMER1->CC[2] = context.protocol->pulse_width;

	// timer2 (counter)
	NRF_TIMER2->TASKS_STOP = 1;
	NRF_TIMER2->TASKS_CLEAR = 1;
	NRF_TIMER2->MODE = TIMER_MODE_MODE_Counter;
	NRF_TIMER2->BITMODE = TIMER_BITMODE_BITMODE_16Bit;
	NRF_TIMER2->TASKS_START = 1;
	NRF_TIMER2->SHORTS = TIMER_SHORTS_COMPARE0_CLEAR_Msk;

	// gpio (led)
	nrf_gpio_cfg_output(led_pin);

	// ppi's
	sd_ppi_channel_assign(0, &NRF_TIMER1->EVENTS_COMPARE[0], &NRF_GPIOTE->TASKS_OUT[0]); // toggle led
	sd_ppi_channel_assign(1, &NRF_TIMER1->EVENTS_COMPARE[1], &NRF_GPIOTE->TASKS_OUT[0]); // toggle led
	sd_ppi_channel_assign(2, &NRF_TIMER1->EVENTS_COMPARE[2], &NRF_TIMER2->TASKS_COUNT); // inc timer2
	sd_ppi_channel_assign(3, &NRF_TIMER2->EVENTS_COMPARE[0], &NRF_TIMER1->TASKS_STOP); // stops timer1 after timer2 reaches N
	sd_ppi_channel_enable_set(PPI_CHEN_CH0_Msk |
		PPI_CHEN_CH1_Msk |
		PPI_CHEN_CH2_Msk |
		PPI_CHEN_CH3_Msk);
}
Exemplo n.º 6
0
static inline void vect_division(int *res, int *vect, int div, int dim)
{
    int i;
    if (div > 1)
        for (i=0; i<dim; i++)
            res[i] = ROUNDED_DIV(vect[i],div);
    else if (res != vect)
        memcpy(res, vect, dim*sizeof(int));

}
/**@brief Function for initializing the RTC1 counter.
 *
 * @param[in] prescaler   Value of the RTC1 PRESCALER register. Set to 0 for no prescaling.
 */
static void rtc1_init(uint32_t prescaler)
{
    NRF_RTC1->PRESCALER = prescaler;
    NVIC_SetPriority(RTC1_IRQn, RTC1_IRQ_PRI);

    //Dhavaltest
    // Set the CC[1] register to the frequency of the counter, so the COMPARE[1] event will be triggered every second
    NRF_RTC1->CC[1] = (uint32_t)ROUNDED_DIV((uint64_t)APP_TIMER_CLOCK_FREQ, ((prescaler) + 1));
    //Dhaval test
}
Exemplo n.º 8
0
/**
 * This routine will precompute the combined DCT matrix with qscale
 * and DCT renorm needed by the MPEG encoder here. It is basically the
 * same as the routine with the same name in mpegvideo.c, except for
 * some coefficient changes. The matrix will be computed in two variations,
 * depending on the DCT version used. The second used by the MMX version of DCT.
 *
 * \param s MpegEncContext pointer
 * \param qmat[OUT] pointer to where the matrix is stored
 * \param qmat16[OUT] pointer to where matrix for MMX is stored.
 *		  This matrix is not permutated
 *                and second 64 entries are bias
 * \param quant_matrix[IN] the quantizion matrix to use
 * \param bias bias for the quantizer
 * \param qmin minimum qscale value to set up for
 * \param qmax maximum qscale value to set up for
 *
 * Only rows between qmin and qmax will be populated in the matrix.
 * In this MJPEG encoder, only the value 8 for qscale is used.
 */
static void convert_matrix(MpegEncContext *s, int (*qmat)[64],
		uint16_t (*qmat16)[2][64], const uint16_t *quant_matrix,
		int bias, int qmin, int qmax) {
	int qscale;

	for(qscale = qmin; qscale <= qmax; qscale++) {
		int i;
		if (s->dsp.fdct == ff_jpeg_fdct_islow_8) {
			for (i = 0; i < 64; i++) {
				const int j = s->dsp.idct_permutation[i];
/* 16 <= qscale * quant_matrix[i] <= 7905
 * 19952         <= aanscales[i] * qscale * quant_matrix[i]      <= 249205026
 * (1<<36)/19952 >= (1<<36)/(aanscales[i] * qscale * quant_matrix[i])
 *                                                       >= (1<<36)/249205026
 * 3444240       >= (1<<36)/(aanscales[i] * qscale * quant_matrix[i])  >= 275 */
				qmat[qscale][i] = (int)((UINT64_C(1) <<
					(QMAT_SHIFT-3))/
					(qscale*quant_matrix[j]));
			}
		} else if (s->dsp.fdct == ff_fdct_ifast) {
			for (i = 0; i < 64; i++) {
				const int j = s->dsp.idct_permutation[i];
/* 16 <= qscale * quant_matrix[i] <= 7905
 * 19952         <= aanscales[i] * qscale * quant_matrix[i]      <= 249205026
 * (1<<36)/19952 >= (1<<36)/(aanscales[i] * qscale * quant_matrix[i])
 *                                                       >= (1<<36)/249205026
 * 3444240       >= (1<<36)/(aanscales[i] * qscale * quant_matrix[i])  >= 275 */
				qmat[qscale][i] = (int)((UINT64_C(1) <<
					(QMAT_SHIFT + 11))/(aanscales[i]
					*qscale * quant_matrix[j]));
			}
		} else {
			for (i = 0; i < 64; i++) {
				const int j = s->dsp.idct_permutation[i];
/* We can safely assume that 16 <= quant_matrix[i] <= 255
 * So 16           <= qscale * quant_matrix[i]             <= 7905
 * so (1<<19) / 16 >= (1<<19) / (qscale * quant_matrix[i]) >= (1<<19) / 7905
 * so 32768        >= (1<<19) / (qscale * quant_matrix[i]) >= 67 */
				qmat[qscale][i] = (int)((UINT64_C(1) <<
						QMAT_SHIFT_MMX) / (qscale
							*quant_matrix[j]));
				qmat16[qscale][0][i] = (1 << QMAT_SHIFT_MMX)
						/(qscale * quant_matrix[j]);

				if (qmat16[qscale][0][i] == 0 ||
						qmat16[qscale][0][i] == 128*256)
					qmat16[qscale][0][i]=128*256-1;
				qmat16[qscale][1][i]=ROUNDED_DIV(bias
						<<(16-QUANT_BIAS_SHIFT),
						qmat16[qscale][0][i]);
			}
		}
	}
}
Exemplo n.º 9
0
uint32_t app_timer_start(app_timer_id_t timer_id, uint32_t timeout_ticks, void * p_context)
{
    if ((timeout_ticks < APP_TIMER_MIN_TIMEOUT_TICKS))
    {
        return NRF_ERROR_INVALID_PARAM;
    }
    uint32_t timeout_ms =
        ((uint32_t)ROUNDED_DIV(timeout_ticks * 1000 * (app_timer_control.prescaler + 1),
                               (uint32_t)APP_TIMER_CLOCK_FREQ));

    app_timer_info_t * p_timer_info = (app_timer_info_t *)timer_id;
    if (rt_id2obj((void *)p_timer_info->id) == NULL)
        return NRF_ERROR_INVALID_PARAM;

    // Pass p_context to timer_timeout_handler
    ((os_timer_cb *)(p_timer_info->id))->arg = p_context;

    if (((os_timer_cb *)(p_timer_info->id))->state == osTimerRunning)
    {
        return NRF_SUCCESS;
    }
    // osTimerStart() returns osErrorISR if it is called in interrupt routine.
    switch (osTimerStart((osTimerId)p_timer_info->id, timeout_ms) )
    {
        case osOK:
            return NRF_SUCCESS;

        case osErrorISR:
            break;

        case osErrorParameter:
            return NRF_ERROR_INVALID_PARAM;

        default:
            return NRF_ERROR_INVALID_PARAM;
    }

    // Start timer without svcCall
    switch (svcTimerStart((osTimerId)p_timer_info->id, timeout_ms))
    {
        case osOK:
            return NRF_SUCCESS;

        case osErrorISR:
            return NRF_ERROR_INVALID_STATE;

        case osErrorParameter:
            return NRF_ERROR_INVALID_PARAM;

        default:
            return NRF_ERROR_INVALID_PARAM;
    }
}
Exemplo n.º 10
0
uint32_t app_timer_start(app_timer_id_t timer_id, uint32_t timeout_ticks, void * p_context)
{
    app_timer_info_t * pinfo = (app_timer_info_t*)(timer_id);
    TimerHandle_t hTimer = pinfo->osHandle;
    uint32_t rtc_prescaler = portNRF_RTC_REG->PRESCALER  + 1;
    /* Get back the microseconds to wait */
    uint32_t timeout_corrected = ROUNDED_DIV(timeout_ticks * m_prescaler, rtc_prescaler);

    if (hTimer == NULL)
    {
        return NRF_ERROR_INVALID_STATE;
    }
    if (pinfo->active && (xTimerIsTimerActive(hTimer) != pdFALSE))
    {
        // Timer already running - exit silently
        return NRF_SUCCESS;
    }

    pinfo->argument = p_context;

    if (__get_IPSR() != 0)
    {
        BaseType_t yieldReq = pdFALSE;
        if (xTimerChangePeriodFromISR(hTimer, timeout_corrected, &yieldReq) != pdPASS)
        {
            return NRF_ERROR_NO_MEM;
        }

        if ( xTimerStartFromISR(hTimer, &yieldReq) != pdPASS )
        {
            return NRF_ERROR_NO_MEM;
        }

        portYIELD_FROM_ISR(yieldReq);
    }
    else
    {
        if (xTimerChangePeriod(hTimer, timeout_corrected, APP_TIMER_WAIT_FOR_QUEUE) != pdPASS)
        {
            return NRF_ERROR_NO_MEM;
        }

        if (xTimerStart(hTimer, APP_TIMER_WAIT_FOR_QUEUE) != pdPASS)
        {
            return NRF_ERROR_NO_MEM;
        }
    }

    pinfo->active = true;
    return NRF_SUCCESS;
}
Exemplo n.º 11
0
void ant_sdm_simulator_one_iteration(ant_sdm_simulator_t * p_simulator)
{
    if (p_simulator->_cb.auto_change)
    {
        UNUSED_PARAMETER(sensorsim_measure(&(p_simulator->_cb.sensorsim_state),
                                           &(p_simulator->_cb.sensorsim_cfg)));
    }

    p_simulator->_cb.time += SIMULATOR_TIME_INCREMENT;

    p_simulator->_cb.stride_incr += p_simulator->_cb.sensorsim_state.current_val *
                                   SIMULATOR_TIME_INCREMENT;
    p_simulator->p_profile->SDM_PROFILE_strides += p_simulator->_cb.stride_incr /
                                                   SIMULATOR_STRIDE_UNIT_REVERSAL;
    p_simulator->_cb.stride_incr = p_simulator->_cb.stride_incr %
                                  SIMULATOR_STRIDE_UNIT_REVERSAL;


    uint32_t distance = value_rescale(
        p_simulator->p_profile->SDM_PROFILE_strides * p_simulator->_cb.stride_length,
        SIMULATOR_STRIDE_LENGTH_UNIT_REVERSAL,
        ANT_SDM_DISTANCE_UNIT_REVERSAL);

    if (p_simulator->p_profile->SDM_PROFILE_capabilities.cadency_is_valid)
    {
        p_simulator->p_profile->SDM_PROFILE_cadence = p_simulator->_cb.sensorsim_state.current_val;
    }

    if (p_simulator->p_profile->SDM_PROFILE_capabilities.speed_is_valid)
    {
        p_simulator->p_profile->SDM_PROFILE_speed = value_rescale(
            p_simulator->_cb.sensorsim_state.current_val * p_simulator->_cb.stride_length,
            ANT_SDM_CADENCE_UNIT_REVERSAL * SIMULATOR_STRIDE_LENGTH_UNIT_REVERSAL * SEC_PER_MIN,
            ANT_SDM_SPEED_UNIT_REVERSAL);
    }

    if (p_simulator->p_profile->SDM_PROFILE_capabilities.distance_is_valid)
    {
        p_simulator->p_profile->SDM_PROFILE_distance = distance;
    }

    if (p_simulator->p_profile->SDM_PROFILE_capabilities.calorie_is_valid)
    {
        p_simulator->p_profile->SDM_PROFILE_calories = value_rescale(distance,
                                                                     SIMULATOR_BURN_RATE_UNIT
                                                                     * ANT_SDM_DISTANCE_UNIT_REVERSAL,
                                                                     p_simulator->_cb.burn_rate);
    }

    if (p_simulator->p_profile->SDM_PROFILE_capabilities.time_is_valid)
    {
        p_simulator->p_profile->SDM_PROFILE_time = value_rescale(p_simulator->_cb.time,
                                                                 SIMULATOR_TIME_UNIT_REVERSAL,
                                                                 ANT_SDM_TIME_UNIT_REVERSAL);
    }

    if (p_simulator->p_profile->SDM_PROFILE_capabilities.latency_is_valid)
    {
        p_simulator->p_profile->SDM_PROFILE_update_latency =
            ROUNDED_DIV(((uint64_t)p_simulator->_cb.stride_incr *
                         ANT_SDM_UPDATE_LATENCY_UNIT_REVERSAL),
                        (uint64_t)SIMULATOR_TIME_UNIT_REVERSAL *
                        p_simulator->_cb.sensorsim_state.current_val);
    }
}
Exemplo n.º 12
0
/**
 * Apply a simple delogo algorithm to the image in src and put the
 * result in dst.
 *
 * The algorithm is only applied to the region specified by the logo
 * parameters.
 *
 * @param w      width of the input image
 * @param h      height of the input image
 * @param logo_x x coordinate of the top left corner of the logo region
 * @param logo_y y coordinate of the top left corner of the logo region
 * @param logo_w width of the logo
 * @param logo_h height of the logo
 * @param band   the size of the band around the processed area
 * @param show   show a rectangle around the processed area, useful for
 *               parameters tweaking
 * @param direct if non-zero perform in-place processing
 */
static void apply_delogo(uint8_t *dst, int dst_linesize,
                         uint8_t *src, int src_linesize,
                         int w, int h, AVRational sar,
                         int logo_x, int logo_y, int logo_w, int logo_h,
                         unsigned int band, int show, int direct)
{
    int x, y;
    uint64_t interp, weightl, weightr, weightt, weightb, weight;
    uint8_t *xdst, *xsrc;

    uint8_t *topleft, *botleft, *topright;
    unsigned int left_sample, right_sample;
    int xclipl, xclipr, yclipt, yclipb;
    int logo_x1, logo_x2, logo_y1, logo_y2;

    xclipl = FFMAX(-logo_x, 0);
    xclipr = FFMAX(logo_x+logo_w-w, 0);
    yclipt = FFMAX(-logo_y, 0);
    yclipb = FFMAX(logo_y+logo_h-h, 0);

    logo_x1 = logo_x + xclipl;
    logo_x2 = logo_x + logo_w - xclipr - 1;
    logo_y1 = logo_y + yclipt;
    logo_y2 = logo_y + logo_h - yclipb - 1;

    topleft  = src+logo_y1 * src_linesize+logo_x1;
    topright = src+logo_y1 * src_linesize+logo_x2;
    botleft  = src+logo_y2 * src_linesize+logo_x1;

    if (!direct)
        av_image_copy_plane(dst, dst_linesize, src, src_linesize, w, h);

    dst += (logo_y1 + 1) * dst_linesize;
    src += (logo_y1 + 1) * src_linesize;

    for (y = logo_y1+1; y < logo_y2; y++) {
        left_sample = topleft[src_linesize*(y-logo_y1)]   +
                      topleft[src_linesize*(y-logo_y1-1)] +
                      topleft[src_linesize*(y-logo_y1+1)];
        right_sample = topright[src_linesize*(y-logo_y1)]   +
                       topright[src_linesize*(y-logo_y1-1)] +
                       topright[src_linesize*(y-logo_y1+1)];

        for (x = logo_x1+1,
             xdst = dst+logo_x1+1,
             xsrc = src+logo_x1+1; x < logo_x2; x++, xdst++, xsrc++) {

            if (show && (y == logo_y1+1 || y == logo_y2-1 ||
                         x == logo_x1+1 || x == logo_x2-1)) {
                *xdst = 0;
                continue;
            }

            /* Weighted interpolation based on relative distances, taking SAR into account */
            weightl = (uint64_t)              (logo_x2-x) * (y-logo_y1) * (logo_y2-y) * sar.den;
            weightr = (uint64_t)(x-logo_x1)               * (y-logo_y1) * (logo_y2-y) * sar.den;
            weightt = (uint64_t)(x-logo_x1) * (logo_x2-x)               * (logo_y2-y) * sar.num;
            weightb = (uint64_t)(x-logo_x1) * (logo_x2-x) * (y-logo_y1)               * sar.num;

            interp =
                left_sample * weightl
                +
                right_sample * weightr
                +
                (topleft[x-logo_x1]    +
                 topleft[x-logo_x1-1]  +
                 topleft[x-logo_x1+1]) * weightt
                +
                (botleft[x-logo_x1]    +
                 botleft[x-logo_x1-1]  +
                 botleft[x-logo_x1+1]) * weightb;
            weight = (weightl + weightr + weightt + weightb) * 3U;
            interp = ROUNDED_DIV(interp, weight);

            if (y >= logo_y+band && y < logo_y+logo_h-band &&
                x >= logo_x+band && x < logo_x+logo_w-band) {
                *xdst = interp;
            } else {
                unsigned dist = 0;

                if      (x < logo_x+band)
                    dist = FFMAX(dist, logo_x-x+band);
                else if (x >= logo_x+logo_w-band)
                    dist = FFMAX(dist, x-(logo_x+logo_w-1-band));

                if      (y < logo_y+band)
                    dist = FFMAX(dist, logo_y-y+band);
                else if (y >= logo_y+logo_h-band)
                    dist = FFMAX(dist, y-(logo_y+logo_h-1-band));

                *xdst = (*xsrc*dist + interp*(band-dist))/band;
            }
        }

        dst += dst_linesize;
        src += src_linesize;
    }
}
Exemplo n.º 13
0
uint64_t common_rtc_64bit_us_get(void)
{
    uint32_t ticks = common_rtc_32bit_ticks_get();
    // [ticks -> microseconds]
    return ROUNDED_DIV(((uint64_t)ticks) * 1000000, RTC_INPUT_FREQ);
}
Exemplo n.º 14
0
/**
 * Return the optimal value (0 or 1) for the ac_pred element for the given MB in mpeg4.
 * This function will also update s->block_last_index and s->ac_val.
 * @param[in,out] block MB coefficients, these will be updated if 1 is returned
 * @param[in] dir ac prediction direction for each 8x8 block
 * @param[out] st scantable for each 8x8 block
 * @param[out] zigzag_last_index index refering to the last non zero coefficient in zigzag order
 */
static inline int decide_ac_pred(MpegEncContext * s, DCTELEM block[6][64], const int dir[6], uint8_t *st[6], int zigzag_last_index[6])
{
    int score= 0;
    int i, n;
    int8_t * const qscale_table = s->current_picture.f.qscale_table;

    memcpy(zigzag_last_index, s->block_last_index, sizeof(int)*6);

    for(n=0; n<6; n++){
        int16_t *ac_val, *ac_val1;

        score -= get_block_rate(s, block[n], s->block_last_index[n], s->intra_scantable.permutated);

        ac_val = s->ac_val[0][0] + s->block_index[n] * 16;
        ac_val1= ac_val;
        if(dir[n]){
            const int xy= s->mb_x + s->mb_y*s->mb_stride - s->mb_stride;
            /* top prediction */
            ac_val-= s->block_wrap[n]*16;
            if(s->mb_y==0 || s->qscale == qscale_table[xy] || n==2 || n==3){
                /* same qscale */
                for(i=1; i<8; i++){
                    const int level= block[n][s->dsp.idct_permutation[i   ]];
                    block[n][s->dsp.idct_permutation[i   ]] = level - ac_val[i+8];
                    ac_val1[i  ]=    block[n][s->dsp.idct_permutation[i<<3]];
                    ac_val1[i+8]= level;
                }
            }else{
                /* different qscale, we must rescale */
                for(i=1; i<8; i++){
                    const int level= block[n][s->dsp.idct_permutation[i   ]];
                    block[n][s->dsp.idct_permutation[i   ]] = level - ROUNDED_DIV(ac_val[i + 8]*qscale_table[xy], s->qscale);
                    ac_val1[i  ]=    block[n][s->dsp.idct_permutation[i<<3]];
                    ac_val1[i+8]= level;
                }
            }
            st[n]= s->intra_h_scantable.permutated;
        }else{
            const int xy= s->mb_x-1 + s->mb_y*s->mb_stride;
            /* left prediction */
            ac_val-= 16;
            if(s->mb_x==0 || s->qscale == qscale_table[xy] || n==1 || n==3){
                /* same qscale */
                for(i=1; i<8; i++){
                    const int level= block[n][s->dsp.idct_permutation[i<<3]];
                    block[n][s->dsp.idct_permutation[i<<3]]= level - ac_val[i];
                    ac_val1[i  ]= level;
                    ac_val1[i+8]=    block[n][s->dsp.idct_permutation[i   ]];
                }
            }else{
                /* different qscale, we must rescale */
                for(i=1; i<8; i++){
                    const int level= block[n][s->dsp.idct_permutation[i<<3]];
                    block[n][s->dsp.idct_permutation[i<<3]]= level - ROUNDED_DIV(ac_val[i]*qscale_table[xy], s->qscale);
                    ac_val1[i  ]= level;
                    ac_val1[i+8]=    block[n][s->dsp.idct_permutation[i   ]];
                }
            }
            st[n]= s->intra_v_scantable.permutated;
        }

        for(i=63; i>0; i--) //FIXME optimize
            if(block[n][ st[n][i] ]) break;
        s->block_last_index[n]= i;

        score += get_block_rate(s, block[n], s->block_last_index[n], st[n]);
    }

    if(score < 0){
        return 1;
    }else{
        restore_ac_coeffs(s, block, dir, st, zigzag_last_index);
        return 0;
    }
}
Exemplo n.º 15
0
static void FN(inter_pred)(AVCodecContext *ctx)
{
    static const uint8_t bwlog_tab[2][N_BS_SIZES] = {
        { 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4 },
        { 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 4, 4 },
    };
    VP9Context *s = ctx->priv_data;
    VP9Block *b = s->b;
    int row = s->row, col = s->col;
    ThreadFrame *tref1 = &s->refs[s->refidx[b->ref[0]]], *tref2;
    AVFrame *ref1 = tref1->f, *ref2;
    int w1 = ref1->width, h1 = ref1->height, w2, h2;
    ptrdiff_t ls_y = s->y_stride, ls_uv = s->uv_stride;

    if (b->comp) {
        tref2 = &s->refs[s->refidx[b->ref[1]]];
        ref2 = tref2->f;
        w2 = ref2->width;
        h2 = ref2->height;
    }

    // y inter pred
    if (b->bs > BS_8x8) {
        if (b->bs == BS_8x4) {
            mc_luma_dir(s, mc[3][b->filter][0], s->dst[0], ls_y,
                        ref1->data[0], ref1->linesize[0], tref1,
                        row << 3, col << 3, &b->mv[0][0], 8, 4, w1, h1, 0);
            mc_luma_dir(s, mc[3][b->filter][0],
                        s->dst[0] + 4 * ls_y, ls_y,
                        ref1->data[0], ref1->linesize[0], tref1,
                        (row << 3) + 4, col << 3, &b->mv[2][0], 8, 4, w1, h1, 0);

            if (b->comp) {
                mc_luma_dir(s, mc[3][b->filter][1], s->dst[0], ls_y,
                            ref2->data[0], ref2->linesize[0], tref2,
                            row << 3, col << 3, &b->mv[0][1], 8, 4, w2, h2, 1);
                mc_luma_dir(s, mc[3][b->filter][1],
                            s->dst[0] + 4 * ls_y, ls_y,
                            ref2->data[0], ref2->linesize[0], tref2,
                            (row << 3) + 4, col << 3, &b->mv[2][1], 8, 4, w2, h2, 1);
            }
        } else if (b->bs == BS_4x8) {
            mc_luma_dir(s, mc[4][b->filter][0], s->dst[0], ls_y,
                        ref1->data[0], ref1->linesize[0], tref1,
                        row << 3, col << 3, &b->mv[0][0], 4, 8, w1, h1, 0);
            mc_luma_dir(s, mc[4][b->filter][0], s->dst[0] + 4, ls_y,
                        ref1->data[0], ref1->linesize[0], tref1,
                        row << 3, (col << 3) + 4, &b->mv[1][0], 4, 8, w1, h1, 0);

            if (b->comp) {
                mc_luma_dir(s, mc[4][b->filter][1], s->dst[0], ls_y,
                            ref2->data[0], ref2->linesize[0], tref2,
                            row << 3, col << 3, &b->mv[0][1], 4, 8, w2, h2, 1);
                mc_luma_dir(s, mc[4][b->filter][1], s->dst[0] + 4, ls_y,
                            ref2->data[0], ref2->linesize[0], tref2,
                            row << 3, (col << 3) + 4, &b->mv[1][1], 4, 8, w2, h2, 1);
            }
        } else {
            av_assert2(b->bs == BS_4x4);

            // FIXME if two horizontally adjacent blocks have the same MV,
            // do a w8 instead of a w4 call
            mc_luma_dir(s, mc[4][b->filter][0], s->dst[0], ls_y,
                        ref1->data[0], ref1->linesize[0], tref1,
                        row << 3, col << 3, &b->mv[0][0], 4, 4, w1, h1, 0);
            mc_luma_dir(s, mc[4][b->filter][0], s->dst[0] + 4, ls_y,
                        ref1->data[0], ref1->linesize[0], tref1,
                        row << 3, (col << 3) + 4, &b->mv[1][0], 4, 4, w1, h1, 0);
            mc_luma_dir(s, mc[4][b->filter][0],
                        s->dst[0] + 4 * ls_y, ls_y,
                        ref1->data[0], ref1->linesize[0], tref1,
                        (row << 3) + 4, col << 3, &b->mv[2][0], 4, 4, w1, h1, 0);
            mc_luma_dir(s, mc[4][b->filter][0],
                        s->dst[0] + 4 * ls_y + 4, ls_y,
                        ref1->data[0], ref1->linesize[0], tref1,
                        (row << 3) + 4, (col << 3) + 4, &b->mv[3][0], 4, 4, w1, h1, 0);

            if (b->comp) {
                mc_luma_dir(s, mc[4][b->filter][1], s->dst[0], ls_y,
                            ref2->data[0], ref2->linesize[0], tref2,
                            row << 3, col << 3, &b->mv[0][1], 4, 4, w2, h2, 1);
                mc_luma_dir(s, mc[4][b->filter][1], s->dst[0] + 4, ls_y,
                            ref2->data[0], ref2->linesize[0], tref2,
                            row << 3, (col << 3) + 4, &b->mv[1][1], 4, 4, w2, h2, 1);
                mc_luma_dir(s, mc[4][b->filter][1],
                            s->dst[0] + 4 * ls_y, ls_y,
                            ref2->data[0], ref2->linesize[0], tref2,
                            (row << 3) + 4, col << 3, &b->mv[2][1], 4, 4, w2, h2, 1);
                mc_luma_dir(s, mc[4][b->filter][1],
                            s->dst[0] + 4 * ls_y + 4, ls_y,
                            ref2->data[0], ref2->linesize[0], tref2,
                            (row << 3) + 4, (col << 3) + 4, &b->mv[3][1], 4, 4, w2, h2, 1);
            }
        }
    } else {
        int bwl = bwlog_tab[0][b->bs];
        int bw = bwh_tab[0][b->bs][0] * 4, bh = bwh_tab[0][b->bs][1] * 4;

        mc_luma_dir(s, mc[bwl][b->filter][0], s->dst[0], ls_y,
                    ref1->data[0], ref1->linesize[0], tref1,
                    row << 3, col << 3, &b->mv[0][0],bw, bh, w1, h1, 0);

        if (b->comp)
            mc_luma_dir(s, mc[bwl][b->filter][1], s->dst[0], ls_y,
                        ref2->data[0], ref2->linesize[0], tref2,
                        row << 3, col << 3, &b->mv[0][1], bw, bh, w2, h2, 1);
    }

    // uv inter pred
    {
        int bwl = bwlog_tab[1][b->bs];
        int bw = bwh_tab[1][b->bs][0] * 4, bh = bwh_tab[1][b->bs][1] * 4;
        VP56mv mvuv;

        w1 = (w1 + 1) >> 1;
        h1 = (h1 + 1) >> 1;
        if (b->comp) {
            w2 = (w2 + 1) >> 1;
            h2 = (h2 + 1) >> 1;
        }
        if (b->bs > BS_8x8) {
            mvuv.x = ROUNDED_DIV(b->mv[0][0].x + b->mv[1][0].x + b->mv[2][0].x + b->mv[3][0].x, 4);
            mvuv.y = ROUNDED_DIV(b->mv[0][0].y + b->mv[1][0].y + b->mv[2][0].y + b->mv[3][0].y, 4);
        } else {
            mvuv = b->mv[0][0];
        }

        mc_chroma_dir(s, mc[bwl][b->filter][0],
                      s->dst[1], s->dst[2], ls_uv,
                      ref1->data[1], ref1->linesize[1],
                      ref1->data[2], ref1->linesize[2], tref1,
                      row << 2, col << 2, &mvuv, bw, bh, w1, h1, 0);

        if (b->comp) {
            if (b->bs > BS_8x8) {
                mvuv.x = ROUNDED_DIV(b->mv[0][1].x + b->mv[1][1].x + b->mv[2][1].x + b->mv[3][1].x, 4);
                mvuv.y = ROUNDED_DIV(b->mv[0][1].y + b->mv[1][1].y + b->mv[2][1].y + b->mv[3][1].y, 4);
            } else {
                mvuv = b->mv[0][1];
            }
            mc_chroma_dir(s, mc[bwl][b->filter][1],
                          s->dst[1], s->dst[2], ls_uv,
                          ref2->data[1], ref2->linesize[1],
                          ref2->data[2], ref2->linesize[2], tref2,
                          row << 2, col << 2, &mvuv, bw, bh, w2, h2, 1);
        }
    }
Exemplo n.º 16
0
/**
 * Initialize the table_rV, table_gU[i], table_gV, and table_bU fields
 * in SwsContext
 *
 * @param inv_table the YUV -> RGB table (this is a line of Inverse_Table_6_9)
 * @param fullRange 0->MPEG YUV space 1->JPEG YUV space
*/
int yuv2rgb_c_init_tables(SwsContext *c, const int inv_table[4], int fullRange, int brightness, int contrast, int saturation)
{  
    int i;
    static uint8_t ytable[1024];
    int64_t cy, oy;
    int64_t crv, cbu, cgu, cgv;
    int entry_size = 0;
    uint8_t *table_r, *table_g, *table_b;
    int value;

    if ((inv_table[0] == 0) || (inv_table[1] == 0) || (inv_table[2] == 0) || (inv_table[3] == 0)) {
        MSG_ERR("Invalid YUV ---> RGB table!\n");

        return -1;
    }
    crv = inv_table[0];
    cbu = inv_table[1];
    cgu = inv_table[2];
    cgv = inv_table[3];
    if (fullRange) {
        cy = 1 << 16;
        oy = 0;
        crv= (crv*224) / 255;
        cbu= (cbu*224) / 255;
        cgu= (cgu*224) / 255;
        cgv= (cgv*224) / 255;
        //FIXME maybe its cleaner if the tables where based on full range (*244/255)
    } else {
        cy = ((1 << 16) * 255) / 219;
        oy= 16 << 16;
    }

    cy = (cy *contrast             )>>16;
    crv= (crv*contrast * saturation)>>32;
    cbu= (cbu*contrast * saturation)>>32;
    cgu= (cgu*contrast * saturation)>>32;
    cgv= (cgv*contrast * saturation)>>32;
    oy -= 256*brightness;

    for (i = 0; i < 1024; i++) {
        value = (cy*(((i - YTABLE_MIN)<<16) - oy) + (1<<31))>>32;
        ytable[i] = av_clip_uint8(value);
    }

    entry_size = get_entry_size(fmt_depth(c->dstFormat));
    av_free(c->yuvTable);
    c->yuvTable = allocate_tables(&table_r, &table_g, &table_b, fmt_depth(c->dstFormat));
    if (c->yuvTable == NULL) {
        return -1;
    }

    switch (fmt_depth(c->dstFormat)) {
        case 32:
            for (i = -198; i < 256 + 197; i++) {
                value = ytable[i + YTABLE_MIN];
                if (isBGR(c->dstFormat)) {
                    value <<= 16;
                }
                ((uint32_t *)table_r)[i] = value;
            }
            for (i = -133; i < 256 + 132; i++) {
                ((uint32_t *)table_g)[i] = ytable[i + YTABLE_MIN] << 8;
            }
            for (i = -233; i < 256 + 232; i++) {
                value = ytable[i + YTABLE_MIN];
                if (!isBGR(c->dstFormat)) {
                    value <<= 16;
                }
                ((uint32_t *)table_b)[i] = value;
            }
            break;

        case 24:
            for (i = -233; i < 256 + 232; i++) {
                ((uint8_t * )table_b)[i] = ytable[i + YTABLE_MIN];
            }
            break;

        case 15:
        case 16:
            for (i = -198; i < 256 + 197; i++) {
                value = ytable[i + YTABLE_MIN] >> 3;
                if (isBGR(c->dstFormat)) {
                    value <<= ((fmt_depth(c->dstFormat) == 16) ? 11 : 10);
                }
                ((uint16_t *)table_r)[i] = value;
            }
            for (i = -133; i < 256 + 132; i++) {
                value = ytable[i + YTABLE_MIN];
                value >>= ((fmt_depth(c->dstFormat) == 16) ? 2 : 3);
                ((uint16_t *)table_g)[i] = value << 5;
            }
            for (i = -233; i < 256 + 232; i++) {
                value = ytable[i + YTABLE_MIN] >> 3;
                if (!isBGR(c->dstFormat)) {
                    value <<= ((fmt_depth(c->dstFormat) == 16) ? 11 : 10);
                }
                ((uint16_t *)table_b)[i] = value;
            }
            break;
        case 8:
            for (i = -198; i < 256 + 197; i++) {
                value = (ytable[i + YTABLE_MIN - 16] + 18) / 36;
                if (isBGR(c->dstFormat)) {
                    value <<= 5;
                }
                ((uint8_t *)table_r)[i] = value;
            }
            for (i = -133; i < 256 + 132; i++) {
                value = (ytable[i + YTABLE_MIN - 16] + 18) / 36;
                if (!isBGR(c->dstFormat)) {
                    value <<= 1;
                }
                ((uint8_t *)table_g)[i] = value << 2;
            }
            for (i = -233; i < 256 + 232; i++) {
                value = (ytable[i + YTABLE_MIN - 37] + 43) / 85;
                if (!isBGR(c->dstFormat)) {
                    value <<= 6;
                }
                ((uint8_t *)table_b)[i] = value;
            }
            break;
        case 4:
            for (i = -198; i < 256 + 197; i++) {
                value = ytable[i + YTABLE_MIN - 110] >> 7;
                if (isBGR(c->dstFormat)) {
                    value <<= 3;
                }
                ((uint8_t *)table_r)[i] = value;
            }
            for (i = -133; i < 256 + 132; i++) {
                value = (ytable[i + YTABLE_MIN - 37]+ 43) / 85;
                ((uint8_t *)table_g)[i] = value << 1;
            }
            for (i = -233; i < 256 + 232; i++) {
                value = ytable[i + YTABLE_MIN - 110] >> 7;
                if (!isBGR(c->dstFormat)) {
                    value <<= 3;
                }
                ((uint8_t *)table_b)[i] = value;
            }
            break;
        case 1:
            for (i = 0; i < 256 + 256; i++) {
                value = ytable[i + YTABLE_MIN - 110] >> 7;
                ((uint8_t *)table_g)[i] = value;
            }
            break;
        default:
            MSG_ERR("%ibpp not supported by yuv2rgb\n", fmt_depth(c->dstFormat));
            av_free(c->yuvTable);
            c->yuvTable = NULL;

            return -1;
    }

    for (i = 0; i < 256; i++) {
        c->table_rV[i] = table_r +
                         entry_size * ROUNDED_DIV(crv * (i - 128), 76309);
        c->table_gU[i] = table_g +
                         entry_size * ROUNDED_DIV(cgu * (i - 128), 76309);
        c->table_gV[i] = entry_size * ROUNDED_DIV(cgv * (i - 128), 76309);
        c->table_bU[i] = table_b +
                         entry_size * ROUNDED_DIV(cbu * (i - 128), 76309);
    }

    return 0;
}
Exemplo n.º 17
0
void
RTC1_IRQHandler(void)
{
	if (NRF_RTC1->EVENTS_COMPARE[3] != 0)
	{
		// prepare the comparator for the next interval
		NRF_RTC1->CC[3] += ctx->rtc_x[3].period;

		// clear the event CC_x
		NRF_RTC1->EVENTS_COMPARE[3] = 0;

		//call the registered callback
		ctx->rtc_x[3].cb(ctx);
	}
	if (NRF_RTC1->EVENTS_COMPARE[0] == 0)
		return;
	NRF_RTC1->EVENTS_COMPARE[0] = 0;
	switch (context.state) {
	case PROTOCOL_STATE_IDLE:
		/* should not happen */
		break;
	case PROTOCOL_STATE_PREAMBLE_DONE:
		NRF_RTC1->TASKS_STOP = 1;
		NRF_RTC1->PRESCALER = ROUNDED_DIV(LFCLK_FREQUENCY, context.protocol->tick_freq) - 1;
		context.state = PROTOCOL_STATE_ADDRESS;
		context.bit_position = 0;
		NRF_RTC1->TASKS_START = 1;
		/* FALLTHROUGH */
	case PROTOCOL_STATE_ADDRESS:
		clock_bit_position(context.address);
		if (++context.bit_position == context.protocol->address.length) {
			context.bit_position = 0;
			if (context.protocol->address.send_complement) {
				if (context.invert == 0) {
					context.invert = 1;
				} else {
					context.invert = 0;
					context.state = PROTOCOL_STATE_COMMAND;
				}
			} else {
				context.state = PROTOCOL_STATE_COMMAND;
			}
		}
		break;
	case PROTOCOL_STATE_COMMAND:
		clock_bit_position(context.command);
		if (++context.bit_position == context.protocol->command.length) {
			context.bit_position = 0;
			if (context.protocol->command.send_complement) {
				if (context.invert == 0) {
					context.invert = 1;
				} else {
					context.invert = 0;
					context.state = PROTOCOL_STATE_LAST_BIT;
				}
			} else {
				context.state = PROTOCOL_STATE_LAST_BIT;
			}
		}
		break;
	case PROTOCOL_STATE_LAST_BIT:
		clock_bit_position(context.command);
		context.state = PROTOCOL_STATE_END;
		break;
	case PROTOCOL_STATE_END:
		// turn off GPIOTE to avoid overconsumption bug (PAN39)
		NRF_GPIOTE->POWER = GPIOTE_POWER_POWER_Disabled << GPIOTE_POWER_POWER_Pos;
		NRF_RTC1->TASKS_STOP = 1;
		NRF_RTC1->TASKS_CLEAR = 1;
		NRF_POWER->TASKS_LOWPWR = 1; // PAN 11 "HFCLK: Base current with HFCLK running is too high"
		context.state = PROTOCOL_STATE_IDLE;
		if (context.cb) {
			context.cb(context.address, context.command);
		}
		break;
	}
}
Exemplo n.º 18
0
static int
grabber_ffmpeg_properties_get (grabber_ffmpeg_t *ffmpeg,
                               AVFormatContext *ctx, file_data_t *data)
{
  int res;
  unsigned int i;
  unsigned int audio_streams = 0, video_streams = 0, sub_streams = 0;

  res = avformat_find_stream_info (ctx, NULL);
  if (res < 0)
  {
    vh_log (VALHALLA_MSG_VERBOSE,
            "FFmpeg can't find stream info: %s", data->file.path);
    return -1;
  }

  /*
   * The duration is in microsecond. We save in millisecond in order to
   * have the same unit as libplayer.
   */
  if (data->file.type != VALHALLA_FILE_TYPE_IMAGE && ctx->duration)
    vh_grabber_parse_int64 (data, ROUNDED_DIV (ctx->duration, 1000),
                            VALHALLA_METADATA_DURATION, ffmpeg->pl);

  for (i = 0; i < ctx->nb_streams; i++)
  {
    float value;
    const char *name;
    AVStream *st = ctx->streams[i];
    AVCodecParameters *codec = st->codecpar;

    switch (codec->codec_type)
    {
    case AVMEDIA_TYPE_AUDIO:
      audio_streams++;
      name = grabber_ffmpeg_codec_name (codec->codec_id);
      if (name)
        vh_metadata_add_auto (&data->meta_grabber,
                              VALHALLA_METADATA_AUDIO_CODEC,
                              name, VALHALLA_LANG_UNDEF, ffmpeg->pl);
      vh_grabber_parse_int (data, codec->channels,
                            VALHALLA_METADATA_AUDIO_CHANNELS, ffmpeg->pl);
      if (codec->bit_rate)
        vh_grabber_parse_int (data, codec->bit_rate,
                              VALHALLA_METADATA_AUDIO_BITRATE, ffmpeg->pl);
      break;

    case AVMEDIA_TYPE_VIDEO:
      /* Common part (image + video) */
      video_streams++;
      name = grabber_ffmpeg_codec_name (codec->codec_id);
      if (name)
        vh_metadata_add_auto (&data->meta_grabber,
                              VALHALLA_METADATA_VIDEO_CODEC,
                              name, VALHALLA_LANG_UNDEF, ffmpeg->pl);
      vh_grabber_parse_int (data, codec->width,
                            VALHALLA_METADATA_WIDTH, ffmpeg->pl);
      vh_grabber_parse_int (data, codec->height,
                            VALHALLA_METADATA_HEIGHT, ffmpeg->pl);

      /* Only for video */
      if (data->file.type == VALHALLA_FILE_TYPE_IMAGE)
        break;

      if (codec->bit_rate)
        vh_grabber_parse_int (data, codec->bit_rate,
                              VALHALLA_METADATA_VIDEO_BITRATE, ffmpeg->pl);

      if (st->sample_aspect_ratio.num)
        value = codec->width * st->sample_aspect_ratio.num
                / (float) (codec->height * st->sample_aspect_ratio.den);
      else
        value = codec->width * codec->sample_aspect_ratio.num
                / (float) (codec->height * codec->sample_aspect_ratio.den);
      /*
       * Save in integer with a ratio of 10000 like the constant
       * PLAYER_VIDEO_ASPECT_RATIO_MULT with libplayer (player.h).
       */
      vh_grabber_parse_int (data, (int) (value * 10000.0),
                            VALHALLA_METADATA_VIDEO_ASPECT, ffmpeg->pl);
      break;

    case AVMEDIA_TYPE_SUBTITLE:
      sub_streams++;
      break;

    default:
      break;
    }
  }

  if (audio_streams)
    vh_grabber_parse_int (data, audio_streams,
                          VALHALLA_METADATA_AUDIO_STREAMS, ffmpeg->pl);
  if (video_streams)
    vh_grabber_parse_int (data, video_streams,
                          VALHALLA_METADATA_VIDEO_STREAMS, ffmpeg->pl);
  if (sub_streams)
    vh_grabber_parse_int (data, sub_streams,
                          VALHALLA_METADATA_SUB_STREAMS, ffmpeg->pl);
  return 0;
}