Ejemplo n.º 1
0
/*****************************************************************************
 * DoWork: decode a DTS frame.
 *****************************************************************************/
static void DoWork( aout_instance_t * p_aout, aout_filter_t * p_filter,
                    aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf )
{
    filter_sys_t    *p_sys = (filter_sys_t *)p_filter->p_sys;
    sample_t        i_sample_level = 1;
    int             i_flags = p_sys->i_flags;
    int             i_bytes_per_block = 256 * p_sys->i_nb_channels
                      * sizeof(float);
    int             i;

    /*
     * Do the actual decoding now.
     */

    /* Needs to be called so the decoder knows which type of bitstream it is
     * dealing with. */
    int i_sample_rate, i_bit_rate, i_frame_length;
    if( !dts_syncinfo( p_sys->p_libdts, p_in_buf->p_buffer, &i_flags,
                       &i_sample_rate, &i_bit_rate, &i_frame_length ) )
    {
        msg_Warn( p_filter, "libdts couldn't sync on frame" );
        p_out_buf->i_nb_samples = p_out_buf->i_nb_bytes = 0;
        return;
    }

    i_flags = p_sys->i_flags;
    dts_frame( p_sys->p_libdts, p_in_buf->p_buffer,
               &i_flags, &i_sample_level, 0 );

    if ( (i_flags & DTS_CHANNEL_MASK) != (p_sys->i_flags & DTS_CHANNEL_MASK)
          && !p_sys->b_dontwarn )
    {
        msg_Warn( p_filter,
                  "libdts couldn't do the requested downmix 0x%x->0x%x",
                  p_sys->i_flags  & DTS_CHANNEL_MASK,
                  i_flags & DTS_CHANNEL_MASK );

        p_sys->b_dontwarn = 1;
    }

    if( 0)//!p_sys->b_dynrng )
    {
        dts_dynrng( p_sys->p_libdts, NULL, NULL );
    }

    for ( i = 0; i < dts_blocks_num(p_sys->p_libdts); i++ )
    {
        sample_t * p_samples;

        if( dts_block( p_sys->p_libdts ) )
        {
            msg_Warn( p_filter, "dts_block failed for block %d", i );
            break;
        }

        p_samples = dts_samples( p_sys->p_libdts );

        if ( (p_sys->i_flags & DTS_CHANNEL_MASK) == DTS_MONO
              && (p_filter->output.i_physical_channels 
                   & (AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT)) )
        {
            Duplicate( (float *)(p_out_buf->p_buffer + i * i_bytes_per_block),
                       p_samples );
        }
        else if ( p_filter->output.i_original_channels
                    & AOUT_CHAN_REVERSESTEREO )
        {
            Exchange( (float *)(p_out_buf->p_buffer + i * i_bytes_per_block),
                      p_samples );
        }
        else
        {
            /* Interleave the *$£%ù samples. */
            Interleave( (float *)(p_out_buf->p_buffer + i * i_bytes_per_block),
                        p_samples, p_sys->i_nb_channels, p_sys->pi_chan_table);
        }
    }

    p_out_buf->i_nb_samples = p_in_buf->i_nb_samples;
    p_out_buf->i_nb_bytes = i_bytes_per_block * i;
}
Ejemplo n.º 2
0
static GstFlowReturn
gst_dtsdec_handle_frame (GstDtsDec * dts, guint8 * data,
    guint length, gint flags, gint sample_rate, gint bit_rate)
{
  gboolean need_renegotiation = FALSE;
  gint channels, num_blocks;
  GstBuffer *out;
  gint i, s, c, num_c;
  sample_t *samples;
  GstFlowReturn result = GST_FLOW_OK;

  /* go over stream properties, update caps/streaminfo if needed */
  if (dts->sample_rate != sample_rate) {
    need_renegotiation = TRUE;
    dts->sample_rate = sample_rate;
  }

  dts->stream_channels = flags;

  if (bit_rate != dts->bit_rate) {
    dts->bit_rate = bit_rate;
    gst_dtsdec_update_streaminfo (dts);
  }

  if (dts->request_channels == DTS_CHANNEL) {
    GstCaps *caps;

    caps = gst_pad_get_allowed_caps (dts->srcpad);
    if (caps && gst_caps_get_size (caps) > 0) {
      GstCaps *copy = gst_caps_copy_nth (caps, 0);
      GstStructure *structure = gst_caps_get_structure (copy, 0);
      gint channels;
      const int dts_channels[6] = {
        DTS_MONO,
        DTS_STEREO,
        DTS_STEREO | DTS_LFE,
        DTS_2F2R,
        DTS_2F2R | DTS_LFE,
        DTS_3F2R | DTS_LFE,
      };

      /* Prefer the original number of channels, but fixate to something 
       * preferred (first in the caps) downstream if possible.
       */
      gst_structure_fixate_field_nearest_int (structure, "channels",
          flags ? gst_dtsdec_channels (flags, NULL) : 6);
      gst_structure_get_int (structure, "channels", &channels);
      if (channels <= 6)
        dts->request_channels = dts_channels[channels - 1];
      else
        dts->request_channels = dts_channels[5];

      gst_caps_unref (copy);
    } else if (flags) {
      dts->request_channels = dts->stream_channels;
    } else {
      dts->request_channels = DTS_3F2R | DTS_LFE;
    }

    if (caps)
      gst_caps_unref (caps);
  }

  /* process */
  flags = dts->request_channels | DTS_ADJUST_LEVEL;
  dts->level = 1;

  if (dts_frame (dts->state, data, &flags, &dts->level, dts->bias)) {
    GST_WARNING ("dts_frame error");
    return GST_FLOW_OK;
  }

  channels = flags & (DTS_CHANNEL_MASK | DTS_LFE);

  if (dts->using_channels != channels) {
    need_renegotiation = TRUE;
    dts->using_channels = channels;
  }

  if (need_renegotiation == TRUE) {
    GST_DEBUG ("dtsdec: sample_rate:%d stream_chans:0x%x using_chans:0x%x",
        dts->sample_rate, dts->stream_channels, dts->using_channels);
    if (!gst_dtsdec_renegotiate (dts)) {
      GST_ELEMENT_ERROR (dts, CORE, NEGOTIATION, (NULL), (NULL));
      return GST_FLOW_ERROR;
    }
  }

  if (dts->dynamic_range_compression == FALSE) {
    dts_dynrng (dts->state, NULL, NULL);
  }

  /* handle decoded data, one block is 256 samples */
  num_blocks = dts_blocks_num (dts->state);
  for (i = 0; i < num_blocks; i++) {
    if (dts_block (dts->state)) {
      GST_WARNING ("dts_block error %d", i);
      continue;
    }

    samples = dts_samples (dts->state);
    num_c = gst_dtsdec_channels (dts->using_channels, NULL);

    result = gst_pad_alloc_buffer_and_set_caps (dts->srcpad, 0,
        (SAMPLE_WIDTH / 8) * 256 * num_c, GST_PAD_CAPS (dts->srcpad), &out);

    if (result != GST_FLOW_OK)
      break;

    GST_BUFFER_TIMESTAMP (out) = dts->current_ts;
    GST_BUFFER_DURATION (out) = GST_SECOND * 256 / dts->sample_rate;
    dts->current_ts += GST_BUFFER_DURATION (out);

    /* libdts returns buffers in 256-sample-blocks per channel,
     * we want interleaved. And we need to copy anyway... */
    data = GST_BUFFER_DATA (out);
    for (s = 0; s < 256; s++) {
      for (c = 0; c < num_c; c++) {
        *(sample_t *) data = samples[s + c * 256];
        data += (SAMPLE_WIDTH / 8);
      }
    }

    /* push on */
    result = gst_pad_push (dts->srcpad, out);

    if (result != GST_FLOW_OK)
      break;
  }

  return result;
}