static int a52_fillbuff(a52_buffer_t * buf)
{
	int length = 0;
	int flags = 0;
	int sample_rate = 0;
	int bit_rate = 0;

	buf->a_in_buffer_len = 0;

	while (1) {
		while (buf->a_in_buffer_len < 7) {
			int c = read_byte();
			if (c < 0)
				return -1;
			buf->a_in_buffer[buf->a_in_buffer_len++] = c;
		}
		length =
		    a52_syncinfo(buf->a_in_buffer, &flags, &sample_rate,
				 &bit_rate);
		//a52_flags |= flags;
		if (length >= 7 && length <= 3840)
			break;
		memmove(buf->a_in_buffer, buf->a_in_buffer + 1, 6);
		--buf->a_in_buffer_len;
	}

	buf->samplerate = sample_rate;
	buf->bps = bit_rate / 8;
	a52_read((buf->a_in_buffer + 7), (length - 7));

	return length;
}
int a52_fillbuff(sh_audio_t *sh_audio){
int length=0;
int flags=0;
int sample_rate=0;
int bit_rate=0;

    sh_audio->a_in_buffer_len=0;
    /* sync frame:*/
while(1){
    while(sh_audio->a_in_buffer_len<8){
	int c=demux_getc(sh_audio->ds);
	if(c<0) return -1; /* EOF*/
        sh_audio->a_in_buffer[sh_audio->a_in_buffer_len++]=c;
    }
    if(sh_audio->format!=0x2000) swab(sh_audio->a_in_buffer,sh_audio->a_in_buffer,8);
    length = a52_syncinfo (sh_audio->a_in_buffer, &flags, &sample_rate, &bit_rate);
    if(length>=7 && length<=3840) break; /* we're done.*/
    /* bad file => resync*/
    if(sh_audio->format!=0x2000) swab(sh_audio->a_in_buffer,sh_audio->a_in_buffer,8);
    memmove(sh_audio->a_in_buffer,sh_audio->a_in_buffer+1,7);
    --sh_audio->a_in_buffer_len;
}
    mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"a52: len=%d  flags=0x%X  %d Hz %d bit/s\n",length,flags,sample_rate,bit_rate);
    sh_audio->samplerate=sample_rate;
    sh_audio->i_bps=bit_rate/8;
    sh_audio->samplesize=sh_audio->sample_format==AF_FORMAT_FLOAT_NE ? 4 : 2;
    demux_read_data(sh_audio->ds,sh_audio->a_in_buffer+8,length-8);
    if(sh_audio->format!=0x2000)
	swab(sh_audio->a_in_buffer+8,sh_audio->a_in_buffer+8,length-8);
    
    if(crc16_block(sh_audio->a_in_buffer+2,length-2)!=0)
	mp_msg(MSGT_DECAUDIO,MSGL_STATUS,"a52: CRC check failed!  \n");
    
    return length;
}
Beispiel #3
0
/* Return 1 if it isn't an AC3 header */
int mpeg3_ac3_check(unsigned char *header)
{
	int flags, samplerate, bitrate;
	return !a52_syncinfo(header,
		&flags,
		&samplerate,
		&bitrate);
}
static GstFlowReturn
gst_a52dec_parse (GstAudioDecoder * bdec, GstAdapter * adapter,
    gint * _offset, gint * len)
{
  GstA52Dec *a52dec;
  const guint8 *data;
  gint av, size;
  gint length = 0, flags, sample_rate, bit_rate;
  GstFlowReturn result = GST_FLOW_EOS;

  a52dec = GST_A52DEC (bdec);

  size = av = gst_adapter_available (adapter);
  data = (const guint8 *) gst_adapter_map (adapter, av);

  /* find and read header */
  bit_rate = a52dec->bit_rate;
  sample_rate = a52dec->sample_rate;
  flags = 0;
  while (size >= 7) {
    length = a52_syncinfo ((guint8 *) data, &flags, &sample_rate, &bit_rate);

    if (length == 0) {
      /* shift window to re-find sync */
      data++;
      size--;
    } else if (length <= size) {
      GST_LOG_OBJECT (a52dec, "Sync: frame size %d", length);
      result = GST_FLOW_OK;
      break;
    } else {
      GST_LOG_OBJECT (a52dec, "Not enough data available (needed %d had %d)",
          length, size);
      break;
    }
  }
  gst_adapter_unmap (adapter);

  *_offset = av - size;
  *len = length;

  return result;
}
Beispiel #5
0
/* returns: number of available channels*/
static int a52_printinfo(sh_audio_t *sh_audio){
int flags, sample_rate, bit_rate;
char* mode="unknown";
int channels=0;
  a52_syncinfo (sh_audio->a_in_buffer, &flags, &sample_rate, &bit_rate);
  switch(flags&A52_CHANNEL_MASK){
    case A52_CHANNEL: mode="channel"; channels=2; break;
    case A52_MONO: mode="mono"; channels=1; break;
    case A52_STEREO: mode="stereo"; channels=2; break;
    case A52_3F: mode="3f";channels=3;break;
    case A52_2F1R: mode="2f+1r";channels=3;break;
    case A52_3F1R: mode="3f+1r";channels=4;break;
    case A52_2F2R: mode="2f+2r";channels=4;break;
    case A52_3F2R: mode="3f+2r";channels=5;break;
    case A52_CHANNEL1: mode="channel1"; channels=2; break;
    case A52_CHANNEL2: mode="channel2"; channels=2; break;
    case A52_DOLBY: mode="dolby"; channels=2; break;
  }
  mp_msg(MSGT_DECAUDIO,MSGL_V,"AC3: %d.%d (%s%s)  %d Hz  %3.1f kbit/s\n",
	channels, (flags&A52_LFE)?1:0,
	mode, (flags&A52_LFE)?"+lfe":"",
	sample_rate, bit_rate*0.001f);
  return (flags&A52_LFE) ? (channels+1) : channels;
}
Beispiel #6
0
static void a52_decode_data(uint8_t *start, uint8_t *end)
{
    static uint8_t *bufptr = buf;
    static uint8_t *bufpos = buf + 7;
    /*
     * sample_rate and flags are static because this routine could
     * exit between the a52_syncinfo() and the ao_setup(), and we want
     * to have the same values when we get back !
     */
    static int sample_rate;
    static int flags;
    int bit_rate;
    int len;

    while (1) {
        len = end - start;
        if (!len)
            break;
        if (len > bufpos - bufptr)
            len = bufpos - bufptr;
        memcpy(bufptr, start, len);
        bufptr += len;
        start += len;
        if (bufptr == bufpos) {
            if (bufpos == buf + 7) {
                int length;

                length = a52_syncinfo(buf, &flags, &sample_rate, &bit_rate);
                if (!length) {
                    //DEBUGF("skip\n");
                    for (bufptr = buf; bufptr < buf + 6; bufptr++)
                        bufptr[0] = bufptr[1];
                    continue;
                }
                bufpos = buf + length;
            } else {
                /* Unity gain is 1 << 26, and we want to end up on 28 bits
                   of precision instead of the default 30.
                 */
                level_t level = 1 << 24;
                sample_t bias = 0;
                int i;

                /* This is the configuration for the downmixing: */
                flags = A52_STEREO | A52_ADJUST_LEVEL;

                if (a52_frame(state, buf, &flags, &level, bias))
                    goto error;
                a52_dynrng(state, NULL, NULL);
                frequency = sample_rate;

                /* An A52 frame consists of 6 blocks of 256 samples
                   So we decode and output them one block at a time */
                for (i = 0; i < 6; i++) {
                    if (a52_block(state))
                        goto error;
                    output_audio(a52_samples(state));
                    samplesdone += 256;
                }
                ci->set_elapsed(samplesdone/(frequency/1000));
                bufptr = buf;
                bufpos = buf + 7;
                continue;
            error:
                //logf("Error decoding A52 stream\n");
                bufptr = buf;
                bufpos = buf + 7;
            }
        }   
    }
}
Beispiel #7
0
static GF_Err AC3_ProcessData(GF_MediaDecoder *ifcg,
		char *inBuffer, u32 inBufferLength,
		u16 ES_ID,
		char *outBuffer, u32 *outBufferLength,
		u8 PaddingBits, u32 mmlevel)
{
    short *out_samples;
	int i, len, bit_rate;
	sample_t level;
	A52CTX();

	/*check not using scalabilty*/
	if (ctx->ES_ID != ES_ID) return GF_BAD_PARAM;

	/*if late or seeking don't decode*/
	switch (mmlevel) {
	case GF_CODEC_LEVEL_SEEK:
	case GF_CODEC_LEVEL_DROP:
		*outBufferLength = 0;
		return GF_OK;
	default:
		break;
	}

	if (ctx->out_size > *outBufferLength) {
		*outBufferLength = ctx->out_size;
		return GF_BUFFER_TOO_SMALL;
	}

	GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[A52] Decoding AU\n"));

	len = a52_syncinfo(inBuffer, &ctx->flags, &ctx->sample_rate, &bit_rate);
	if (!len) return GF_NON_COMPLIANT_BITSTREAM;

	/*init decoder*/
	if (!ctx->out_size) {
		ctx->num_channels = ac3_channels[ctx->flags & 7];
		if (ctx->flags & A52_LFE) ctx->num_channels++;
		ctx->flags |= A52_ADJUST_LEVEL;

		ctx->out_size = ctx->num_channels * sizeof(short) * 1536;
		*outBufferLength = ctx->out_size;
		return GF_BUFFER_TOO_SMALL;
	}

	level = 1;
	if ( a52_frame(ctx->codec, inBuffer, &ctx->flags, &level, 384)) {
		GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[A52] Error decoding AU\n" ));
		*outBufferLength = 0;
		return GF_NON_COMPLIANT_BITSTREAM;
	}

	out_samples = (short*)outBuffer;
	for (i=0; i<6; i++) {
		if (a52_block(ctx->codec))
			return GF_NON_COMPLIANT_BITSTREAM;

		float_to_int(ctx->samples, out_samples + i * 256 * ctx->num_channels, ctx->num_channels);
	}

	*outBufferLength = 6 * ctx->num_channels * 256 * sizeof(short);

	return GF_OK;
}
uint8_t ADM_AudiocodecAC3::run(uint8_t *inptr, uint32_t nbIn, float *outptr,   uint32_t *nbOut)
{
    uint32_t avail;
    uint32_t length;
    int flags = 0, samprate = 0, bitrate = 0;
    uint8_t chan = _wavHeader->channels;
    *nbOut=0;

    //  Ready to decode
    while(nbIn)
    {
        if(nbIn<7)
        {
            if(nbIn)
                printf("[a52]: no data to decode avail %u\n",nbIn);
            break;
        }
        length = a52_syncinfo(inptr, &flags, &samprate, &bitrate);
        if(length==0)
        {
            printf("[a52] No startcode found\n");
            break;
        }
        if(length>nbIn)
        {
            // not enough data
            break;
        }


		CHANNEL_TYPE *p_ch_type = channelMapping;
		if (flags & A52_LFE) {
			*(p_ch_type++) = CHTYP_LFE;
		}
		switch (flags & A52_CHANNEL_MASK) {
			case A52_CHANNEL:
			case A52_MONO:
				*(p_ch_type++) = CHTYP_MONO;
			break;
			case A52_STEREO:
			case A52_DOLBY:
				*(p_ch_type++) = CHTYP_FRONT_LEFT;
				*(p_ch_type++) = CHTYP_FRONT_RIGHT;
			break;
			case A52_3F:
				*(p_ch_type++) = CHTYP_FRONT_LEFT;
				*(p_ch_type++) = CHTYP_FRONT_CENTER;
				*(p_ch_type++) = CHTYP_FRONT_RIGHT;
			break;
			case A52_2F1R:
				*(p_ch_type++) = CHTYP_FRONT_LEFT;
				*(p_ch_type++) = CHTYP_FRONT_RIGHT;
				*(p_ch_type++) = CHTYP_REAR_CENTER;
			break;
			case A52_3F1R:
				*(p_ch_type++) = CHTYP_FRONT_LEFT;
				*(p_ch_type++) = CHTYP_FRONT_CENTER;
				*(p_ch_type++) = CHTYP_FRONT_RIGHT;
				*(p_ch_type++) = CHTYP_REAR_CENTER;
			break;
			case A52_2F2R:
				*(p_ch_type++) = CHTYP_FRONT_LEFT;
				*(p_ch_type++) = CHTYP_FRONT_RIGHT;
				*(p_ch_type++) = CHTYP_REAR_LEFT;
				*(p_ch_type++) = CHTYP_REAR_RIGHT;
			break;
			case A52_3F2R:
				*(p_ch_type++) = CHTYP_FRONT_LEFT;
				*(p_ch_type++) = CHTYP_FRONT_CENTER;
				*(p_ch_type++) = CHTYP_FRONT_RIGHT;
				*(p_ch_type++) = CHTYP_REAR_LEFT;
				*(p_ch_type++) = CHTYP_REAR_RIGHT;
			break;
			default:
				ADM_assert(0);
		}
	

        sample_t level = 1, bias = 0;

        if (a52_frame(AC3_HANDLE, inptr, &flags, &level, bias))
        {
            printf("\n A52_frame failed!");
            inptr+=length;
            nbIn-=length;
            *nbOut += 256 * chan * 6;
            break;
        };
        inptr+=length;
        nbIn-=length;
        *nbOut += 256 * chan * 6;

        float *cur;
        for (int i = 0; i < 6; i++) {
                if (a52_block(AC3_HANDLE)) {
                        printf("\n A52_block failed! on fblock :%lu", i);
                        // in that case we silent out the chunk
                        memset(outptr, 0, 256 * chan * sizeof(float));
                } else {
                        for (int k = 0; k < chan; k++) {
                                sample_t *sample=(sample_t *)ac3_sample;
                                sample += 256 * k;
                                cur = outptr + k;
                                for (int j = 0; j < 256; j++) {
                                        *cur = *sample++;
                                        cur+=chan;
                                }
                        }
                }
                outptr += chan * 256;
        }
    }
    return 1; 

}
Beispiel #9
0
/* Decode AC3 header */
int mpeg3_ac3_header(mpeg3_ac3_t *audio, unsigned char *header)
{
	int result = 0;
	audio->flags = 0;

//printf("mpeg3_ac3_header %02x%02x%02x%02x%02x%02x%02x%02x\n", header[0], header[1], header[2], header[3], header[4], header[5], header[6], header[7]);
	result = a52_syncinfo(header, 
		&audio->flags,
        &audio->samplerate, 
		&audio->bitrate);


	if(result)
	{
//printf("%d\n", result);
		audio->framesize = result;
		audio->channels = 0;

		if(audio->flags & A52_LFE)
			audio->channels++;
/*
 * printf("mpeg3_ac3_header %08x %08x\n", 
 * audio->flags & A52_LFE, 
 * audio->flags & A52_CHANNEL_MASK);
 */
		switch(audio->flags & A52_CHANNEL_MASK)
		{
			case A52_CHANNEL:
				audio->channels++;
				break;
			case A52_MONO:
				audio->channels++;
				break;
			case A52_STEREO:
				audio->channels += 2;
				break;
			case A52_3F:
				audio->channels += 3;
				break;
			case A52_2F1R:
				audio->channels += 3;
				break;
			case A52_3F1R:
				audio->channels += 4;
				break;
			case A52_2F2R:
				audio->channels += 4;
				break;
			case A52_3F2R:
				audio->channels += 5;
				break;
			case A52_DOLBY:
				audio->channels += 2;
				break;
			default:
				printf("mpeg3_ac3_header: unknown channel code: %x\n", audio->flags & A52_CHANNEL_MASK);
				break;
		}
	}
//printf("mpeg3_ac3_header 1 %d\n", audio->channels);
	return result;
}
HRESULT TaudioCodecLiba52::decode(TbyteBuffer &src)
{
    unsigned char *p=src.size() ? &src[0] : NULL;
    unsigned char *base=p;
    unsigned char *end=p+src.size();

    while (end-p>7) {
        int size=0,flags,sample_rate,bit_rate;
        if ((size=a52_syncinfo(p,&flags,&sample_rate,&bit_rate))>0) {
            bool enoughData=p+size<=end;
            if (enoughData) {
                if (codecId==CODEC_ID_SPDIF_AC3) {
                    bpssum+=(lastbps=bit_rate/1000);
                    numframes++;
                    HRESULT hr=deciA->deliverSampleSPDIF(p,size,bit_rate,sample_rate,true);
                    if (hr!=S_OK) {
                        return hr;
                    }
                } else {
                    flags|=A52_ADJUST_LEVEL;
                    liba52::sample_t level=1,bias=0;
                    if (a52_frame(state,p,&flags,&level,bias)==0) {
                        bpssum+=(lastbps=bit_rate/1000);
                        numframes++;
                        // Dynamic range compression
                        if (deci->getParam2(IDFF_audio_decoder_DRC)) {
                            liba52::sample_t drcLevel = ((liba52::sample_t)deci->getParam2(IDFF_audio_decoder_DRC_Level) / 100);
                            a52_dynrngsetlevel(state, drcLevel);
                        } else {
                            a52_dynrngsetlevel(state, 0.0);
                        }
                        int scmapidx=std::min(flags&A52_CHANNEL_MASK,int(countof(scmaps)/2));
                        const Tscmap &scmap=scmaps[scmapidx+((flags&A52_LFE)?(countof(scmaps)/2):0)];
                        float *dst0,*dst;
                        dst0=dst=(float*)getDst(6*256*scmap.nchannels*sizeof(float));
                        int i=0;
                        for(; i<6 && a52_block(state)==0; i++) {
                            liba52::sample_t* samples=a52_samples(state);
                            for (int j=0; j<256; j++,samples++)
                                for (int ch=0; ch<scmap.nchannels; ch++) {
                                    *dst++=float(*(samples+256*scmap.ch[ch])/level);
                                }
                        }
                        if (i==6) {
                            fmt.sf=TsampleFormat::SF_FLOAT32;
                            fmt.freq=sample_rate;
                            fmt.setChannels(scmap.nchannels,scmap.channelMask);
                            HRESULT hr=sinkA->deliverDecodedSample(dst0,6*256,fmt);
                            if (hr!=S_OK) {
                                return hr;
                            }
                        }
                    }
                }
                p+=size;
            }
            memmove(base,p,end-p);
            end=base+(end-p);
            p=base;
            if (!enoughData) {
                break;
            }
        } else {
            p++;
        }
    }
    src.resize(end-p);
    return S_OK;
}
static GstFlowReturn
gst_a52dec_handle_frame (GstAudioDecoder * bdec, GstBuffer * buffer)
{
  GstA52Dec *a52dec;
  gint channels, i;
  gboolean need_reneg = FALSE;
  gint chans;
  gint length = 0, flags, sample_rate, bit_rate;
  GstMapInfo map;
  GstFlowReturn result = GST_FLOW_OK;
  GstBuffer *outbuf;
  const gint num_blocks = 6;

  a52dec = GST_A52DEC (bdec);

  /* no fancy draining */
  if (G_UNLIKELY (!buffer))
    return GST_FLOW_OK;

  /* parsed stuff already, so this should work out fine */
  gst_buffer_map (buffer, &map, GST_MAP_READ);
  g_assert (map.size >= 7);

  /* re-obtain some sync header info,
   * should be same as during _parse and could also be cached there,
   * but anyway ... */
  bit_rate = a52dec->bit_rate;
  sample_rate = a52dec->sample_rate;
  flags = 0;
  length = a52_syncinfo (map.data, &flags, &sample_rate, &bit_rate);
  g_assert (length == map.size);

  /* update stream information, renegotiate or re-streaminfo if needed */
  need_reneg = FALSE;
  if (a52dec->sample_rate != sample_rate) {
    GST_DEBUG_OBJECT (a52dec, "sample rate changed");
    need_reneg = TRUE;
    a52dec->sample_rate = sample_rate;
  }

  if (flags) {
    if (a52dec->stream_channels != (flags & (A52_CHANNEL_MASK | A52_LFE))) {
      GST_DEBUG_OBJECT (a52dec, "stream channel flags changed, marking update");
      a52dec->flag_update = TRUE;
    }
    a52dec->stream_channels = flags & (A52_CHANNEL_MASK | A52_LFE);
  }

  if (bit_rate != a52dec->bit_rate) {
    a52dec->bit_rate = bit_rate;
    gst_a52dec_update_streaminfo (a52dec);
  }

  /* If we haven't had an explicit number of channels chosen through properties
   * at this point, choose what to downmix to now, based on what the peer will
   * accept - this allows a52dec to do downmixing in preference to a
   * downstream element such as audioconvert.
   */
  if (a52dec->request_channels != A52_CHANNEL) {
    flags = a52dec->request_channels;
  } else if (a52dec->flag_update) {
    GstCaps *caps;

    a52dec->flag_update = FALSE;

    caps = gst_pad_get_allowed_caps (GST_AUDIO_DECODER_SRC_PAD (a52dec));
    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 orig_channels = flags ? gst_a52dec_channels (flags, NULL) : 6;
      gint fixed_channels = 0;
      const int a52_channels[6] = {
        A52_MONO,
        A52_STEREO,
        A52_STEREO | A52_LFE,
        A52_2F2R,
        A52_2F2R | A52_LFE,
        A52_3F2R | A52_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",
          orig_channels);

      if (gst_structure_get_int (structure, "channels", &fixed_channels)
          && fixed_channels <= 6) {
        if (fixed_channels < orig_channels)
          flags = a52_channels[fixed_channels - 1];
      } else {
        flags = a52_channels[5];
      }

      gst_caps_unref (copy);
    } else if (flags)
      flags = a52dec->stream_channels;
    else
      flags = A52_3F2R | A52_LFE;

    if (caps)
      gst_caps_unref (caps);
  } else {
    flags = a52dec->using_channels;
  }

  /* process */
  flags |= A52_ADJUST_LEVEL;
  a52dec->level = 1;
  if (a52_frame (a52dec->state, map.data, &flags, &a52dec->level, a52dec->bias)) {
    gst_buffer_unmap (buffer, &map);
    GST_AUDIO_DECODER_ERROR (a52dec, 1, STREAM, DECODE, (NULL),
        ("a52_frame error"), result);
    goto exit;
  }
  gst_buffer_unmap (buffer, &map);

  channels = flags & (A52_CHANNEL_MASK | A52_LFE);
  if (a52dec->using_channels != channels) {
    need_reneg = TRUE;
    a52dec->using_channels = channels;
  }

  /* negotiate if required */
  if (need_reneg) {
    GST_DEBUG_OBJECT (a52dec,
        "a52dec reneg: sample_rate:%d stream_chans:%d using_chans:%d",
        a52dec->sample_rate, a52dec->stream_channels, a52dec->using_channels);
    if (!gst_a52dec_reneg (a52dec))
      goto failed_negotiation;
  }

  if (a52dec->dynamic_range_compression == FALSE) {
    a52_dynrng (a52dec->state, NULL, NULL);
  }

  flags &= (A52_CHANNEL_MASK | A52_LFE);
  chans = gst_a52dec_channels (flags, NULL);
  if (!chans)
    goto invalid_flags;

  /* handle decoded data;
   * each frame has 6 blocks, one block is 256 samples, ea */
  outbuf =
      gst_buffer_new_and_alloc (256 * chans * (SAMPLE_WIDTH / 8) * num_blocks);

  gst_buffer_map (outbuf, &map, GST_MAP_WRITE);
  {
    guint8 *ptr = map.data;
    for (i = 0; i < num_blocks; i++) {
      if (a52_block (a52dec->state)) {
        /* also marks discont */
        GST_AUDIO_DECODER_ERROR (a52dec, 1, STREAM, DECODE, (NULL),
            ("error decoding block %d", i), result);
        if (result != GST_FLOW_OK) {
          gst_buffer_unmap (outbuf, &map);
          goto exit;
        }
      } else {
        gint n, c;
        gint *reorder_map = a52dec->channel_reorder_map;

        for (n = 0; n < 256; n++) {
          for (c = 0; c < chans; c++) {
            ((sample_t *) ptr)[n * chans + reorder_map[c]] =
                a52dec->samples[c * 256 + n];
          }
        }
      }
      ptr += 256 * chans * (SAMPLE_WIDTH / 8);
    }
  }
  gst_buffer_unmap (outbuf, &map);

  result = gst_audio_decoder_finish_frame (bdec, outbuf, 1);

exit:
  return result;

  /* ERRORS */
failed_negotiation:
  {
    GST_ELEMENT_ERROR (a52dec, CORE, NEGOTIATION, (NULL), (NULL));
    return GST_FLOW_ERROR;
  }
invalid_flags:
  {
    GST_ELEMENT_ERROR (GST_ELEMENT (a52dec), STREAM, DECODE, (NULL),
        ("Invalid channel flags: %d", flags));
    return GST_FLOW_ERROR;
  }
}
Beispiel #12
0
static GstFlowReturn
gst_a52dec_chain_raw (GstPad * pad, GstBuffer * buf)
{
  GstA52Dec *a52dec;
  guint8 *data;
  guint size;
  gint length = 0, flags, sample_rate, bit_rate;
  GstFlowReturn result = GST_FLOW_OK;

  a52dec = GST_A52DEC (GST_PAD_PARENT (pad));

  if (!a52dec->sent_segment) {
    GstSegment segment;

    /* Create a basic segment. Usually, we'll get a new-segment sent by 
     * another element that will know more information (a demuxer). If we're
     * just looking at a raw AC3 stream, we won't - so we need to send one
     * here, but we don't know much info, so just send a minimal TIME 
     * new-segment event
     */
    gst_segment_init (&segment, GST_FORMAT_TIME);
    gst_pad_push_event (a52dec->srcpad, gst_event_new_new_segment (FALSE,
            segment.rate, segment.format, segment.start,
            segment.duration, segment.start));
    a52dec->sent_segment = TRUE;
  }

  /* merge with cache, if any. Also make sure timestamps match */
  if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
    a52dec->time = GST_BUFFER_TIMESTAMP (buf);
    GST_DEBUG_OBJECT (a52dec,
        "Received buffer with ts %" GST_TIME_FORMAT " duration %"
        GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
        GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
  }

  if (a52dec->cache) {
    buf = gst_buffer_join (a52dec->cache, buf);
    a52dec->cache = NULL;
  }
  data = GST_BUFFER_DATA (buf);
  size = GST_BUFFER_SIZE (buf);

  /* find and read header */
  bit_rate = a52dec->bit_rate;
  sample_rate = a52dec->sample_rate;
  flags = 0;
  while (size >= 7) {
    length = a52_syncinfo (data, &flags, &sample_rate, &bit_rate);

    if (length == 0) {
      /* no sync */
      data++;
      size--;
    } else if (length <= size) {
      GST_DEBUG ("Sync: %d", length);

      if (flags != a52dec->prev_flags)
        a52dec->flag_update = TRUE;
      a52dec->prev_flags = flags;

      result = gst_a52dec_handle_frame (a52dec, data,
          length, flags, sample_rate, bit_rate);
      if (result != GST_FLOW_OK) {
        size = 0;
        break;
      }
      size -= length;
      data += length;
    } else {
      /* not enough data */
      GST_LOG ("Not enough data available");
      break;
    }
  }

  /* keep cache */
  if (length == 0) {
    GST_LOG ("No sync found");
  }

  if (size > 0) {
    a52dec->cache = gst_buffer_create_sub (buf,
        GST_BUFFER_SIZE (buf) - size, size);
  }

  gst_buffer_unref (buf);

  return result;
}