Beispiel #1
0
/*****************************************************************************
 * gst_tiprepencbuf_prepare_output_buffer
 *    Function is used to allocate output buffer
 *****************************************************************************/
static GstFlowReturn
gst_tiprepencbuf_prepare_output_buffer(GstBaseTransform * trans,
    GstBuffer * inBuf, gint size, GstCaps * caps, GstBuffer ** outBuf)
{
    GstTIPrepEncBuf *prepencbuf = GST_TIPREPENCBUF(trans);
    Buffer_Handle    hOutBuf;

    GST_LOG("begin prepare output buffer\n");

    /* Get free buffer from buftab */
    if (!(hOutBuf = gst_tidmaibuftab_get_buf(prepencbuf->hOutBufTab))) {
        GST_ELEMENT_ERROR(prepencbuf, RESOURCE, READ,
            ("failed to get free buffer\n"), (NULL));
        return GST_FLOW_ERROR;
    }

    /* Create a DMAI transport buffer object to carry a DMAI buffer to
     * the source pad.  The transport buffer knows how to release the
     * buffer for re-use in this element when the source pad calls
     * gst_buffer_unref().
     */
    GST_LOG("creating dmai transport buffer\n");
    *outBuf = gst_tidmaibuffertransport_new(hOutBuf, prepencbuf->hOutBufTab, NULL, NULL);
    gst_buffer_set_data(*outBuf, (guint8 *) Buffer_getUserPtr(hOutBuf),
        Buffer_getSize(hOutBuf));
    gst_buffer_set_caps(*outBuf, GST_PAD_CAPS(trans->srcpad));

    GST_LOG("end prepare output buffer\n");

    return GST_FLOW_OK;
}
Beispiel #2
0
/*******************************************************************************
 * gst_tidmaivideosink_buffer_alloc
 *
 * Function used to allocate a buffer from upstream elements
*******************************************************************************/
static GstFlowReturn gst_tidmaivideosink_buffer_alloc(GstBaseSink *bsink, 
    guint64 offset, guint size, GstCaps *caps, GstBuffer **buf){
    Buffer_Handle hBuf;
    GstTIDmaiVideoSink *sink = GST_TIDMAIVIDEOSINK_CAST(bsink);

    if (!sink->zeromemcpy){
        return GST_FLOW_OK;
    }

    if (!sink->capsAreSet){
        if (!gst_tidmaivideosink_set_caps(bsink,caps)){
            return GST_FLOW_UNEXPECTED;
        }
    }

    if (!sink->dmaiElementUpstream){
        return GST_FLOW_OK;
    }

    hBuf = gst_tidmaivideosink_get_display_buffer(sink,NULL);

    if (hBuf){
        *buf = gst_tidmaibuffertransport_new(hBuf,NULL, NULL, FALSE);
        sink->allocatedBuffers[Buffer_getId(hBuf)] = *buf;
        gst_tidmaibuffertransport_set_release_callback(
            (GstTIDmaiBufferTransport *)*buf,
             allocated_buffer_release_cb,sink);
        gst_buffer_set_caps(*buf,caps);
        GST_BUFFER_SIZE(*buf) = gst_ti_calculate_bufSize(
            sink->oattrs.width,sink->oattrs.height,sink->colorSpace);
        sink->numAllocatedBuffers++;
        GST_LOG("Number of pad allocated buffers is %d, current %p",sink->numAllocatedBuffers,*buf);
        sink->lastAllocatedBuffer = *buf;
    } else {
        return GST_FLOW_UNEXPECTED;
    }

    GST_DEBUG("Leave with buffer %p",*buf);
    return GST_FLOW_OK;
}
Beispiel #3
0
static GstFlowReturn
create(GstPushSrc *base, GstBuffer **buf)
{
    GstTICaptureSrc *src = (GstTICaptureSrc *)base;
    Buffer_Handle       hDstBuf;
    GstBuffer   *outBuf;
    gint    ret = GST_FLOW_OK;
    BufferGfx_Attrs  gfxAttrs = BufferGfx_Attrs_DEFAULT;
    Int32   width, height;

    GST_LOG("create begin");

    /* create capture device */
    if (src->hCapture == NULL) {

        /* set framerate based on video standard */
        switch(dmai_video_std(src->video_standard)) {
            case VideoStd_D1_NTSC:
                    gst_value_set_fraction(&src->framerate,30000,1001);
                break;
            case VideoStd_D1_PAL:
                    gst_value_set_fraction(&src->framerate,25,1);
                break;
            default:
                    gst_value_set_fraction(&src->framerate,30,1);
                break;
        }

        /* set width & height based on video standard */

        src->cAttrs.videoStd = dmai_video_std(src->video_standard);

        VideoStd_getResolution(src->cAttrs.videoStd, &width, &height);
				width = 720;
				height = 576;
				GST_WARNING("force video size to %dx%d", src->width, src->height);

        src->width = width;
        src->height = height;
        
        gfxAttrs.dim.height = src->height;
        gfxAttrs.dim.width = src->width;
        src->cAttrs.captureDimension = &gfxAttrs.dim;

        if (!capture_create(src))
            return GST_FLOW_ERROR;
    }

    /* Get buffer from driver */
    if (Capture_get(src->hCapture, &hDstBuf)) {
        GST_ELEMENT_ERROR(src, RESOURCE, FAILED,
        ("Failed to allocate buffer\n"), (NULL));
        return GST_FLOW_ERROR;
    }

    /* Create a DMAI transport buffer object to carry a DMAI buffer to
     * the source pad.  The transport buffer knows how to release the
     * buffer for re-use in this element when the source pad calls
     * gst_buffer_unref().
     */
    outBuf = gst_tidmaibuffertransport_new(hDstBuf, src->hBufTab, capture_buffer_finalize, (void*)src);
    gst_buffer_set_data(outBuf, GST_BUFFER_DATA(outBuf), Buffer_getSize(hDstBuf));

    *buf = outBuf;

    /* set buffer metadata */
    if (G_LIKELY (ret == GST_FLOW_OK && *buf)) {
        GstClock *clock;
        GstClockTime timestamp;

        GST_BUFFER_OFFSET (*buf) = src->offset++;
        GST_BUFFER_OFFSET_END (*buf) = src->offset;

        /* timestamps, LOCK to get clock and base time. */
        GST_OBJECT_LOCK (src);
        if ((clock = GST_ELEMENT_CLOCK (src))) {
            /* we have a clock, get base time and ref clock */
            timestamp = GST_ELEMENT (src)->base_time;
            gst_object_ref (clock);
        } else {
            /* no clock, can't set timestamps */
            timestamp = GST_CLOCK_TIME_NONE;
        }
        GST_OBJECT_UNLOCK (src);

        if (G_LIKELY (clock)) {
            /* the time now is the time of the clock minus the base time */
            timestamp = gst_clock_get_time (clock) - timestamp;
            gst_object_unref (clock);

            /* if we have a framerate adjust timestamp for frame latency */
            if (GST_CLOCK_TIME_IS_VALID (src->duration)) {
                if (timestamp > src->duration)
                    timestamp -= src->duration;
                else
                    timestamp = 0;
            }

        }

        /* FIXME: use the timestamp from the buffer itself! */
        GST_BUFFER_TIMESTAMP (*buf) = timestamp;
        GST_BUFFER_DURATION (*buf) = src->duration;
    }

    /* Create caps for buffer */
    GstCaps *mycaps;
    GstStructure        *structure;

    mycaps = gst_caps_new_empty();

    if (src->cAttrs.colorSpace == ColorSpace_UYVY) {
        structure = gst_structure_new( "video/x-raw-yuv",
            "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC('U', 'Y', 'V', 'Y'),
            "framerate", GST_TYPE_FRACTION,
                gst_value_get_fraction_numerator(&src->framerate),
                gst_value_get_fraction_denominator(&src->framerate),
            "width", G_TYPE_INT,    src->width,
            "height", G_TYPE_INT,   src->height,
            (gchar*) NULL);

    }
    else if(src->cAttrs.colorSpace == ColorSpace_YUV420PSEMI) {
        structure = gst_structure_new( "video/x-raw-yuv",
            "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC('N', 'V', '1', '2'),
            "framerate", GST_TYPE_FRACTION,
                gst_value_get_fraction_numerator(&src->framerate),
                gst_value_get_fraction_denominator(&src->framerate),
            "width", G_TYPE_INT,    src->width,
            "height", G_TYPE_INT,   src->height,
            (gchar*) NULL);
    }
    else {
        GST_ERROR("unsupported fourcc\n");
        return FALSE;
    }

    gst_caps_append_structure(mycaps, gst_structure_copy (structure));
    gst_structure_free(structure);
    gst_buffer_set_caps(*buf, mycaps);
    gst_caps_unref(mycaps);

		{
			static int fn;
			fn++;
			GST_INFO("capture frame %d", fn);
		}

    GST_LOG("create end");
    return GST_FLOW_OK;
}
/* Default implementation for _chain */
static GstFlowReturn
gst_tidmai_base_video_dualencoder_default_realize_instance (GstTIDmaiBaseVideoDualEncoder *video_dualencoder,
	GstTIDmaiDualEncInstance *encoder_instance, GstBuffer *entry_buffer)
{

  GST_DEBUG_OBJECT (video_dualencoder, "Entry gst_tidmai_base_video_dualencoder_default_realize_instance");
  
  /* Only for test */
  //GstClockTime time_start, time_start2, time_end, time_end2;
  //GstClockTimeDiff time_diff;
  Buffer_Attrs	Attrs; 
  Buffer_Handle outBufHandle;
  //Buffer_Attrs	inAttrs; 
  //Buffer_Handle inBufHandle;
  GstTIDmaiVideoInfo *video_info;
  UInt32 phys = 10;
  Bool isContiguous = FALSE;
  
  //time_start = gst_util_get_timestamp ();
  
  int ret;
  GstBuffer *buffer_push_out;
  
  /* Tests if the buffer  */
  phys = Memory_getBufferPhysicalAddress(
                    GST_BUFFER_DATA(entry_buffer),
                    GST_BUFFER_SIZE(entry_buffer),
							&isContiguous);
	
  if(phys == 0) {
	GST_ERROR_OBJECT (video_dualencoder, "Entry buffer isn't CMEM");
	return GST_FLOW_NOT_SUPPORTED;
  }
  else {
	GST_DEBUG_OBJECT (video_dualencoder, "Using buffers with contiguos memory");
	encoder_instance->input_buffer = entry_buffer;
  }
	
  /* Check for the output_buffer */
  if (GST_TI_DMAI_BASE_DUALENCODER (video_dualencoder)->submitted_output_buffers == NULL) {
    
	video_info = (GstTIDmaiVideoInfo *) GST_TI_DMAI_BASE_DUALENCODER (video_dualencoder)->high_resolution_encoder->media_info;
	GST_TI_DMAI_BASE_DUALENCODER (video_dualencoder)->inBufSize = (video_info->width * video_info->height) * 1.8;
	
	
    if (GST_TI_DMAI_BASE_DUALENCODER (video_dualencoder)->outBufSize == 0) {
      /* Default value for the out buffer size */
      GST_TI_DMAI_BASE_DUALENCODER (video_dualencoder)->outBufSize =
          GST_TI_DMAI_BASE_DUALENCODER (video_dualencoder)->inBufSize * 5;
    }

    /* Add the free memory slice to the list */
    struct cmemSlice *slice = g_malloc0 (sizeof (struct cmemSlice));
    slice->start = 0;
    slice->end = GST_TI_DMAI_BASE_DUALENCODER (video_dualencoder)->outBufSize;
    slice->size = GST_TI_DMAI_BASE_DUALENCODER (video_dualencoder)->outBufSize;
#ifdef GLIB_2_31_AND_UP
    g_mutex_init(&(GST_TI_DMAI_BASE_DUALENCODER (video_dualencoder)->freeMutex));
#else
    GST_TI_DMAI_BASE_DUALENCODER (video_dualencoder)->freeMutex  = g_mutex_new();
#endif
    GST_TI_DMAI_BASE_DUALENCODER (video_dualencoder)->freeSlices =
        g_list_append (GST_TI_DMAI_BASE_DUALENCODER (video_dualencoder)->freeSlices, slice);

    /* Allocate the circular buffer */
	
	Attrs = Buffer_Attrs_DEFAULT;
	Attrs.useMask = gst_tidmaibuffertransport_GST_FREE;
	
	outBufHandle = Buffer_create(GST_TI_DMAI_BASE_DUALENCODER (video_dualencoder)->outBufSize, &Attrs);
	
	GST_TI_DMAI_BASE_DUALENCODER (video_dualencoder)->submitted_output_buffers = 
		gst_tidmaibuffertransport_new(outBufHandle, NULL, NULL, FALSE);
	
  }
  /* Encode the actual buffer */
  buffer_push_out =  gst_tidmai_base_dualencoder_encode (GST_TI_DMAI_BASE_DUALENCODER (video_dualencoder), 
						encoder_instance);

  
   	  
  gst_buffer_copy_metadata(buffer_push_out, entry_buffer, 
    GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS); 
  
  
  //time_end = gst_util_get_timestamp ();
   
    
  //time_diff = GST_CLOCK_DIFF (time_start, time_end);
  //g_print ("DualEncoder time: %" G_GUINT64_FORMAT " ns.\n", time_diff);
    
    
  /* push the buffer and check for any error */
  //time_start2 = gst_util_get_timestamp ();
	
  GST_BUFFER_CAPS (buffer_push_out) = gst_caps_ref(GST_PAD_CAPS(encoder_instance->src_pad)); 
  
  ret =
      gst_pad_push (encoder_instance->src_pad,
			buffer_push_out);
  
			
    //time_end2 = gst_util_get_timestamp ();
    
    
    //time_diff = GST_CLOCK_DIFF (time_start2, time_end2);
    
  //g_print ("\nPush time: %" G_GUINT64_FORMAT " ns.\n\n", time_diff);
    
    
  if (GST_FLOW_OK != ret) {
    GST_ERROR_OBJECT (video_dualencoder, "Push buffer return with error: %d",
        ret);
  }
 
  GST_DEBUG_OBJECT (video_dualencoder, "Leave gst_tidmai_base_video_dualencoder_default_realize_instance");
  
  return ret;
}
/******************************************************************************
 * gst_ticircbuffer_get_data
 ******************************************************************************/
GstBuffer* gst_ticircbuffer_get_data(GstTICircBuffer *circBuf)
{
    Buffer_Handle  hCircBufWindow;
    Buffer_Attrs   bAttrs;
    GstBuffer     *result;
    Int32          bufSize;

    if (circBuf == NULL) {
        return NULL;
    }

    /* Reset our mutex condition so calling wait_on_consumer will block */
    Rendezvous_reset(circBuf->waitOnProducer);

    /* Reset the read pointer to the beginning of the buffer when we're
     * approaching the buffer's end (see function definition for reset
     * conditions).
     */
    gst_ticircbuffer_reset_read_pointer(circBuf);

    /* Don't return any data util we have a full window available */
    while (!circBuf->drain && !gst_ticircbuffer_window_available(circBuf)) {

        GST_LOG("blocking output until a full window is available\n");
        gst_ticircbuffer_wait_on_producer(circBuf);
        GST_LOG("unblocking output\n");
        gst_ticircbuffer_reset_read_pointer(circBuf);

        /* Reset our mutex condition so calling wait_on_consumer will block */
        Rendezvous_reset(circBuf->waitOnProducer);
    }

    /* Set the size of the buffer to be no larger than the window size.  Some
     * audio codecs have an issue when you pass a buffer larger than 64K.
     * We need to pass it smaller buffer sizes though, as the EOS is detected
     * when we return a 0 size buffer.
     */
    bufSize = gst_ticircbuffer_data_available(circBuf);
    if (bufSize > circBuf->windowSize) {
        bufSize = circBuf->windowSize;
    }

    /* Return a reference buffer that points to the area of the circular
     * buffer we want to decode.
     */
    Buffer_getAttrs(circBuf->hBuf, &bAttrs);
    bAttrs.reference = TRUE;

    hCircBufWindow = Buffer_create(bufSize, &bAttrs);

    Buffer_setUserPtr(hCircBufWindow, circBuf->readPtr);
    Buffer_setNumBytesUsed(hCircBufWindow, bufSize);

    GST_LOG("returning data at offset %u\n", circBuf->readPtr - 
        Buffer_getUserPtr(circBuf->hBuf));

    result = (GstBuffer*)(gst_tidmaibuffertransport_new(hCircBufWindow, NULL));
    GST_BUFFER_TIMESTAMP(result) = circBuf->dataTimeStamp;
    GST_BUFFER_DURATION(result)  = GST_CLOCK_TIME_NONE;
    return result;
}
Beispiel #6
0
/*****************************************************************************
 * gst_tidmaiaccel_prepare_output_buffer
 *    Function is used to allocate output buffer
 *****************************************************************************/
static GstFlowReturn gst_tidmaiaccel_prepare_output_buffer (GstBaseTransform
    *trans, GstBuffer *inBuf, gint size, GstCaps *caps, GstBuffer **outBuf)
{
    GstTIDmaiaccel *dmaiaccel = GST_TIDMAIACCEL(trans);
    Buffer_Handle   hOutBuf;
    Bool isContiguous = FALSE;
    UInt32 phys = 0;

    /* Always check if the buffer is contiguous */
    phys = Memory_getBufferPhysicalAddress(
                    GST_BUFFER_DATA(inBuf),
                    GST_BUFFER_SIZE(inBuf),
                    &isContiguous);

    if (isContiguous && dmaiaccel->width){
        GST_DEBUG("Is contiguous video buffer");

        Memory_registerContigBuf((UInt32)GST_BUFFER_DATA(inBuf),
            GST_BUFFER_SIZE(inBuf),phys);
        /* This is a contiguous buffer, create a dmai buffer transport */
        BufferGfx_Attrs gfxAttrs    = BufferGfx_Attrs_DEFAULT;

        gfxAttrs.bAttrs.reference   = TRUE;
        gfxAttrs.dim.width          = dmaiaccel->width;
        gfxAttrs.dim.height         = dmaiaccel->height;
        gfxAttrs.colorSpace         = dmaiaccel->colorSpace;
        gfxAttrs.dim.lineLength     = dmaiaccel->lineLength;

        hOutBuf = Buffer_create(GST_BUFFER_SIZE(inBuf), &gfxAttrs.bAttrs);
        BufferGfx_setDimensions(hOutBuf,&gfxAttrs.dim);
        BufferGfx_setColorSpace(hOutBuf,gfxAttrs.colorSpace);
        Buffer_setUserPtr(hOutBuf, (Int8*)GST_BUFFER_DATA(inBuf));
        Buffer_setNumBytesUsed(hOutBuf, GST_BUFFER_SIZE(inBuf));
        *outBuf = gst_tidmaibuffertransport_new(hOutBuf, NULL, NULL, FALSE);
        gst_buffer_set_data(*outBuf, (guint8*) Buffer_getUserPtr(hOutBuf),
            Buffer_getSize(hOutBuf));
        gst_buffer_copy_metadata(*outBuf,inBuf,GST_BUFFER_COPY_ALL);
        gst_buffer_set_caps(*outBuf, GST_PAD_CAPS(trans->srcpad));

        /* We need to grab a reference to the input buffer since we have 
         * a pointer to his buffer */
        gst_buffer_ref(inBuf);

        gst_tidmaibuffertransport_set_release_callback(
            (GstTIDmaiBufferTransport *)*outBuf,
            dmaiaccel_release_cb,inBuf);

        return GST_FLOW_OK;
    } else {
        GST_DEBUG("Copying into contiguous video buffer");
        /* This is a contiguous buffer, create a dmai buffer transport */
        if (!dmaiaccel->bufTabAllocated){
            /* Initialize our buffer tab */
            BufferGfx_Attrs gfxAttrs    = BufferGfx_Attrs_DEFAULT;

            gfxAttrs.dim.width          = dmaiaccel->width;
            gfxAttrs.dim.height         = dmaiaccel->height;
            gfxAttrs.colorSpace         = dmaiaccel->colorSpace;
            gfxAttrs.dim.lineLength     = dmaiaccel->lineLength;

            dmaiaccel->hOutBufTab =
                        BufTab_create(2, GST_BUFFER_SIZE(inBuf),
                            BufferGfx_getBufferAttrs(&gfxAttrs));
            pthread_mutex_init(&dmaiaccel->bufTabMutex, NULL);
            pthread_cond_init(&dmaiaccel->bufTabCond, NULL);
            if (dmaiaccel->hOutBufTab == NULL) {
                GST_ELEMENT_ERROR(dmaiaccel,RESOURCE,NO_SPACE_LEFT,(NULL),
                    ("failed to create output buffer tab"));
                return GST_FLOW_ERROR;
            }
            dmaiaccel->bufTabAllocated = TRUE;
        }

        pthread_mutex_lock(&dmaiaccel->bufTabMutex);
        hOutBuf = BufTab_getFreeBuf(dmaiaccel->hOutBufTab);
        if (hOutBuf == NULL) {
            GST_INFO("Failed to get free buffer, waiting on bufTab\n");
            pthread_cond_wait(&dmaiaccel->bufTabCond, &dmaiaccel->bufTabMutex);

            hOutBuf = BufTab_getFreeBuf(dmaiaccel->hOutBufTab);

            if (hOutBuf == NULL) {
                GST_ELEMENT_ERROR(dmaiaccel,RESOURCE,NO_SPACE_LEFT,(NULL),
                    ("failed to get a free contiguous buffer from BufTab"));
                pthread_mutex_unlock(&dmaiaccel->bufTabMutex);
                return GST_FLOW_ERROR;
            }
        }
        pthread_mutex_unlock(&dmaiaccel->bufTabMutex);

        memcpy(Buffer_getUserPtr(hOutBuf),GST_BUFFER_DATA(inBuf),
            GST_BUFFER_SIZE(inBuf));
        Buffer_setNumBytesUsed(hOutBuf, GST_BUFFER_SIZE(inBuf));
        *outBuf = gst_tidmaibuffertransport_new(hOutBuf, &dmaiaccel->bufTabMutex,
            &dmaiaccel->bufTabCond, FALSE);
        gst_buffer_set_data(*outBuf, (guint8*) Buffer_getUserPtr(hOutBuf),
            Buffer_getSize(hOutBuf));
        gst_buffer_copy_metadata(*outBuf,inBuf,GST_BUFFER_COPY_ALL);
        gst_buffer_set_caps(*outBuf, GST_PAD_CAPS(trans->srcpad));

        return GST_FLOW_OK;
    }
}
Beispiel #7
0
/******************************************************************************
 * gst_tiaudenc1_encode_thread
 *     Call the audio codec to process a full input buffer
 ******************************************************************************/
static void* gst_tiaudenc1_encode_thread(void *arg)
{
    GstTIAudenc1   *audenc1    = GST_TIAUDENC1(gst_object_ref(arg));
    void          *threadRet = GstTIThreadSuccess;
    Buffer_Handle  hDstBuf;
    Int32          encDataConsumed;
    GstBuffer     *encDataWindow = NULL;
    GstClockTime   encDataTime;
    Buffer_Handle  hEncDataWindow;
    GstBuffer     *outBuf;
    GstClockTime   sampleDuration;
    guint          sampleRate;
    guint          numSamples;
    Int            bufIdx;
    Int            ret;

    GST_LOG("starting audenc encode thread\n");

    /* Initialize codec engine */
    ret = gst_tiaudenc1_codec_start(audenc1);

    /* Notify main thread that it is ok to continue initialization */
    Rendezvous_meet(audenc1->waitOnEncodeThread);
    Rendezvous_reset(audenc1->waitOnEncodeThread);

    if (ret == FALSE) {
        GST_ELEMENT_ERROR(audenc1, RESOURCE, FAILED,
        ("Failed to start codec\n"), (NULL));
        goto thread_exit;
    }

    while (TRUE) {

        /* Obtain an raw data frame */
        encDataWindow  = gst_ticircbuffer_get_data(audenc1->circBuf);
        encDataTime    = GST_BUFFER_TIMESTAMP(encDataWindow);
        hEncDataWindow = GST_TIDMAIBUFFERTRANSPORT_DMAIBUF(encDataWindow);

        /* Check if there is enough encoded data to be sent to the codec.
         * The last frame of data may not be sufficient to meet the codec
         * requirements for the amount of input data.  If so just throw
         * away the last bit of data rather than filling with bogus
         * data.
         */
        if (GST_BUFFER_SIZE(encDataWindow) <
            Aenc1_getInBufSize(audenc1->hAe)) {
            GST_LOG("Not enough audio data remains\n");
            if (!audenc1->drainingEOS) {
                goto thread_failure;
            }
            goto thread_exit;
        }

        /* Obtain a free output buffer for the encoded data */
        if (!(hDstBuf = gst_tidmaibuftab_get_buf(audenc1->hOutBufTab))) {
            GST_ELEMENT_ERROR(audenc1, RESOURCE, READ,
                ("Failed to get a free contiguous buffer from BufTab\n"),
                (NULL));
            goto thread_exit;
        }

        /* Invoke the audio encoder */
        GST_LOG("Invoking the audio encoder at 0x%08lx with %u bytes\n",
            (unsigned long)Buffer_getUserPtr(hEncDataWindow),
            GST_BUFFER_SIZE(encDataWindow));
        ret             = Aenc1_process(audenc1->hAe, hEncDataWindow, hDstBuf);
        encDataConsumed = Buffer_getNumBytesUsed(hEncDataWindow);

        if (ret < 0) {
            GST_ELEMENT_ERROR(audenc1, STREAM, ENCODE,
            ("Failed to encode audio buffer\n"), (NULL));
            goto thread_failure;
        }

        /* If no encoded data was used we cannot find the next frame */
        if (ret == Dmai_EBITERROR && encDataConsumed == 0) {
            GST_ELEMENT_ERROR(audenc1, STREAM, ENCODE,
            ("Fatal bit error\n"), (NULL));
            goto thread_failure;
        }

        if (ret > 0) {
            GST_LOG("Aenc1_process returned success code %d\n", ret); 
        }

        sampleRate     = audenc1->samplefreq;
        numSamples     = encDataConsumed / (2 * audenc1->channels) ;
        sampleDuration = GST_FRAMES_TO_CLOCK_TIME(numSamples, sampleRate);

        /* Release the reference buffer, and tell the circular buffer how much
         * data was consumed.
         */
        ret = gst_ticircbuffer_data_consumed(audenc1->circBuf, encDataWindow,
                  encDataConsumed);
        encDataWindow = NULL;

        if (!ret) {
            goto thread_failure;
        }

        /* Set the source pad capabilities based on the encoded frame
         * properties.
         */
        gst_tiaudenc1_set_source_caps(audenc1);

        /* Create a DMAI transport buffer object to carry a DMAI buffer to
         * the source pad.  The transport buffer knows how to release the
         * buffer for re-use in this element when the source pad calls
         * gst_buffer_unref().
         */
        outBuf = gst_tidmaibuffertransport_new(hDstBuf, audenc1->hOutBufTab, NULL, NULL);
        gst_buffer_set_data(outBuf, GST_BUFFER_DATA(outBuf),
            Buffer_getNumBytesUsed(hDstBuf));
        gst_buffer_set_caps(outBuf, GST_PAD_CAPS(audenc1->srcpad));

        /* Set timestamp on output buffer */
        if (audenc1->genTimeStamps) {
            GST_BUFFER_DURATION(outBuf)     = sampleDuration;
            GST_BUFFER_TIMESTAMP(outBuf)    = encDataTime;
        }
        else {
            GST_BUFFER_TIMESTAMP(outBuf)    = GST_CLOCK_TIME_NONE;
        }

        /* Tell circular buffer how much time we consumed */
        gst_ticircbuffer_time_consumed(audenc1->circBuf, sampleDuration);

        /* Push the transport buffer to the source pad */
        GST_LOG("pushing buffer to source pad with timestamp : %"
                GST_TIME_FORMAT ", duration: %" GST_TIME_FORMAT,
                GST_TIME_ARGS (GST_BUFFER_TIMESTAMP(outBuf)),
                GST_TIME_ARGS (GST_BUFFER_DURATION(outBuf)));

        if (gst_pad_push(audenc1->srcpad, outBuf) != GST_FLOW_OK) {
            GST_DEBUG("push to source pad failed\n");
            goto thread_failure;
        }

        /* Release buffers no longer in use by the codec */
        Buffer_freeUseMask(hDstBuf, gst_tidmaibuffer_CODEC_FREE);
    }

thread_failure:

    gst_tithread_set_status(audenc1, TIThread_CODEC_ABORTED);
    gst_ticircbuffer_consumer_aborted(audenc1->circBuf);
    threadRet = GstTIThreadFailure;

thread_exit:

    /* Re-claim any buffers owned by the codec */
    bufIdx = BufTab_getNumBufs(GST_TIDMAIBUFTAB_BUFTAB(audenc1->hOutBufTab));

    while (bufIdx-- > 0) {
        Buffer_Handle hBuf = BufTab_getBuf(
            GST_TIDMAIBUFTAB_BUFTAB(audenc1->hOutBufTab), bufIdx);
        Buffer_freeUseMask(hBuf, gst_tidmaibuffer_CODEC_FREE);
    }

    /* Release the last buffer we retrieved from the circular buffer */
    if (encDataWindow) {
        gst_ticircbuffer_data_consumed(audenc1->circBuf, encDataWindow, 0);
    }

    /* We have to wait to shut down this thread until we can guarantee that
     * no more input buffers will be queued into the circular buffer
     * (we're about to delete it).  
     */
    Rendezvous_meet(audenc1->waitOnEncodeThread);
    Rendezvous_reset(audenc1->waitOnEncodeThread);

    /* Notify main thread that we are done draining before we shutdown the
     * codec, or we will hang.  We proceed in this order so the EOS event gets
     * propagated downstream before we attempt to shut down the codec.  The
     * codec-shutdown process will block until all BufTab buffers have been
     * released, and downstream-elements may hang on to buffers until
     * they get the EOS.
     */
    Rendezvous_force(audenc1->waitOnEncodeDrain);

    /* Initialize codec engine */
    if (gst_tiaudenc1_codec_stop(audenc1) < 0) {
        GST_ERROR("failed to stop codec\n");
        GST_ELEMENT_ERROR(audenc1, RESOURCE, FAILED,
        ("Failed to stop codec\n"), (NULL));
    }

    gst_object_unref(audenc1);

    GST_LOG("exit audio encode_thread (%d)\n", (int)threadRet);
    return threadRet;
}