示例#1
0
static void
play_loop (GstPad * pad)
{
  GstFlowReturn ret;
  GstNsfDec *nsfdec;
  GstBuffer *out;
  gint64 value, offset, time;
  GstFormat format;

  nsfdec = GST_NSFDEC (gst_pad_get_parent (pad));

  out = gst_buffer_new_and_alloc (nsfdec->blocksize);
  gst_buffer_set_caps (out, GST_PAD_CAPS (pad));

  nsf_frame (nsfdec->nsf);
  apu_process (GST_BUFFER_DATA (out), nsfdec->blocksize / nsfdec->bps);

  /* get offset in samples */
  format = GST_FORMAT_DEFAULT;
  gst_nsfdec_src_convert (nsfdec->srcpad,
      GST_FORMAT_BYTES, nsfdec->total_bytes, &format, &offset);
  GST_BUFFER_OFFSET (out) = offset;

  /* get current timestamp */
  format = GST_FORMAT_TIME;
  gst_nsfdec_src_convert (nsfdec->srcpad,
      GST_FORMAT_BYTES, nsfdec->total_bytes, &format, &time);
  GST_BUFFER_TIMESTAMP (out) = time;

  /* update position and get new timestamp to calculate duration */
  nsfdec->total_bytes += nsfdec->blocksize;

  /* get offset in samples */
  format = GST_FORMAT_DEFAULT;
  gst_nsfdec_src_convert (nsfdec->srcpad,
      GST_FORMAT_BYTES, nsfdec->total_bytes, &format, &value);
  GST_BUFFER_OFFSET_END (out) = value;

  format = GST_FORMAT_TIME;
  gst_nsfdec_src_convert (nsfdec->srcpad,
      GST_FORMAT_BYTES, nsfdec->total_bytes, &format, &value);
  GST_BUFFER_DURATION (out) = value - time;

  if ((ret = gst_pad_push (nsfdec->srcpad, out)) != GST_FLOW_OK)
    goto pause;

done:
  gst_object_unref (nsfdec);

  return;

  /* ERRORS */
pause:
  {
    const gchar *reason = gst_flow_get_name (ret);

    GST_DEBUG_OBJECT (nsfdec, "pausing task, reason %s", reason);
    gst_pad_pause_task (pad);

    if (ret == GST_FLOW_UNEXPECTED) {
      /* perform EOS logic, FIXME, segment seek? */
      gst_pad_push_event (pad, gst_event_new_eos ());
    } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_UNEXPECTED) {
      /* for fatal errors we post an error message */
      GST_ELEMENT_ERROR (nsfdec, STREAM, FAILED,
          (NULL), ("streaming task paused, reason %s", reason));
      gst_pad_push_event (pad, gst_event_new_eos ());
    }
    goto done;
  }
}
示例#2
0
static GstFlowReturn
gst_video_mark_yuv (GstVideoMark * videomark, GstBuffer * buffer)
{
  GstVideoFormat format;
  gint i, pw, ph, row_stride, pixel_stride, offset;
  gint width, height, req_width, req_height;
  guint8 *d, *data;
  guint64 pattern_shift;
  guint8 color;

  data = GST_BUFFER_DATA (buffer);

  format = videomark->format;
  width = videomark->width;
  height = videomark->height;

  pw = videomark->pattern_width;
  ph = videomark->pattern_height;
  row_stride = gst_video_format_get_row_stride (format, 0, width);
  pixel_stride = gst_video_format_get_pixel_stride (format, 0);
  offset = gst_video_format_get_component_offset (format, 0, width, height);

  req_width =
      (videomark->pattern_count + videomark->pattern_data_count) * pw +
      videomark->left_offset;
  req_height = videomark->bottom_offset + ph;
  if (req_width > width || req_height > height) {
    GST_ELEMENT_ERROR (videomark, STREAM, WRONG_TYPE, (NULL),
        ("videomark pattern doesn't fit video, need at least %ix%i (stream has %ix%i)",
            req_width, req_height, width, height));
    return GST_FLOW_ERROR;
  }

  /* draw the bottom left pixels */
  for (i = 0; i < videomark->pattern_count; i++) {
    d = data + offset;
    /* move to start of bottom left */
    d += row_stride * (height - ph - videomark->bottom_offset) +
        pixel_stride * videomark->left_offset;
    /* move to i-th pattern */
    d += pixel_stride * pw * i;

    if (i & 1)
      /* odd pixels must be white */
      color = 255;
    else
      color = 0;

    /* draw box of width * height */
    gst_video_mark_draw_box (videomark, d, pw, ph, row_stride, pixel_stride,
        color);
  }

  pattern_shift = G_GUINT64_CONSTANT (1) << (videomark->pattern_data_count - 1);

  /* get the data of the pattern */
  for (i = 0; i < videomark->pattern_data_count; i++) {
    d = data + offset;
    /* move to start of bottom left, adjust for offsets */
    d += row_stride * (height - ph - videomark->bottom_offset) +
        pixel_stride * videomark->left_offset;
    /* move after the fixed pattern */
    d += pixel_stride * videomark->pattern_count * pw;
    /* move to i-th pattern data */
    d += pixel_stride * pw * i;

    if (videomark->pattern_data & pattern_shift)
      color = 255;
    else
      color = 0;

    gst_video_mark_draw_box (videomark, d, pw, ph, row_stride, pixel_stride,
        color);

    pattern_shift >>= 1;
  }

  return GST_FLOW_OK;
}
示例#3
0
bool nvxio::GStreamerBaseRenderImpl::flush()
{
    if (!pipeline)
        return false;

    glfwMakeContextCurrent(window_);

    if (glfwWindowShouldClose(window_))
        return false;

    gl_->PixelStorei(GL_PACK_ALIGNMENT, 1);
    gl_->PixelStorei(GL_PACK_ROW_LENGTH, wndWidth_);

    {
        GstClockTime duration = GST_SECOND / (double)GSTREAMER_DEFAULT_FPS;
        GstClockTime timestamp = num_frames * duration;

#if GST_VERSION_MAJOR == 0
        GstBuffer * buffer = gst_buffer_try_new_and_alloc(wndHeight_ * wndWidth_ * 4);
        if (!buffer)
        {
            NVXIO_PRINT("Cannot create GStreamer buffer");
            FinalizeGStreamerPipeline();
            return false;
        }

        gl_->ReadPixels(0, 0, wndWidth_, wndHeight_, GL_RGBA, GL_UNSIGNED_BYTE, GST_BUFFER_DATA (buffer));

        GST_BUFFER_TIMESTAMP(buffer) = timestamp;
        if (!GST_BUFFER_TIMESTAMP_IS_VALID(buffer))
            NVXIO_PRINT("Failed to setup timestamp");
#else
        GstBuffer * buffer = gst_buffer_new_allocate(NULL, wndHeight_ * wndWidth_ * 4, NULL);

        GstMapInfo info;
        gst_buffer_map(buffer, &info, GST_MAP_READ);
        gl_->ReadPixels(0, 0, wndWidth_, wndHeight_, GL_RGBA, GL_UNSIGNED_BYTE, info.data);
        gst_buffer_unmap(buffer, &info);

        GST_BUFFER_PTS(buffer) = timestamp;
        if (!GST_BUFFER_PTS_IS_VALID(buffer))
            NVXIO_PRINT("Failed to setup PTS");

        GST_BUFFER_DTS(buffer) = timestamp;
        if (!GST_BUFFER_DTS_IS_VALID(buffer))
            NVXIO_PRINT("Failed to setup DTS");
#endif
        GST_BUFFER_DURATION(buffer) = duration;
        if (!GST_BUFFER_DURATION_IS_VALID(buffer))
            NVXIO_PRINT("Failed to setup duration");

        GST_BUFFER_OFFSET(buffer) = num_frames++;
        if (!GST_BUFFER_OFFSET_IS_VALID(buffer))
            NVXIO_PRINT("Failed to setup offset");

        if (gst_app_src_push_buffer(appsrc, buffer) != GST_FLOW_OK)
        {
            NVXIO_PRINT("Error pushing buffer to GStreamer pipeline");
            FinalizeGStreamerPipeline();
            return false;
        }
    }

    // reset state
    gl_->PixelStorei(GL_PACK_ALIGNMENT, 4);
    gl_->PixelStorei(GL_PACK_ROW_LENGTH, 0);

    glfwSwapBuffers(window_);

    clearGlBuffer();

    return true;
}
示例#4
0
HRESULT AudioFakeSink::DoRenderSample(IMediaSample *pMediaSample)
{
  GstBuffer *out_buf = NULL;
  gboolean in_seg = FALSE;
  GstClockTime buf_start, buf_stop;
  gint64 clip_start = 0, clip_stop = 0;
  guint start_offset = 0, stop_offset;
  GstClockTime duration;

  if(pMediaSample)
  {
    BYTE *pBuffer = NULL;
    LONGLONG lStart = 0, lStop = 0;
    long size = pMediaSample->GetActualDataLength();

    pMediaSample->GetPointer(&pBuffer);
    pMediaSample->GetTime(&lStart, &lStop);
    
    if (!GST_CLOCK_TIME_IS_VALID (mDec->timestamp)) {
      // Convert REFERENCE_TIME to GST_CLOCK_TIME
      mDec->timestamp = (GstClockTime)lStart * 100;
    }
    duration = (lStop - lStart) * 100;

    buf_start = mDec->timestamp;
    buf_stop = mDec->timestamp + duration;

    /* save stop position to start next buffer with it */
    mDec->timestamp = buf_stop;

    /* check if this buffer is in our current segment */
    in_seg = gst_segment_clip (mDec->segment, GST_FORMAT_TIME,
        buf_start, buf_stop, &clip_start, &clip_stop);

    /* if the buffer is out of segment do not push it downstream */
    if (!in_seg) {
      GST_DEBUG_OBJECT (mDec,
          "buffer is out of segment, start %" GST_TIME_FORMAT " stop %"
          GST_TIME_FORMAT, GST_TIME_ARGS (buf_start), GST_TIME_ARGS (buf_stop));
      goto done;
    }

    /* buffer is entirely or partially in-segment, so allocate a
     * GstBuffer for output, and clip if required */

    /* allocate a new buffer for raw audio */
    mDec->last_ret = gst_pad_alloc_buffer (mDec->srcpad, 
        GST_BUFFER_OFFSET_NONE,
        size,
        GST_PAD_CAPS (mDec->srcpad), &out_buf);
    if (!out_buf) {
      GST_WARNING_OBJECT (mDec, "cannot allocate a new GstBuffer");
      goto done;
    }

    /* set buffer properties */
    GST_BUFFER_TIMESTAMP (out_buf) = buf_start;
    GST_BUFFER_DURATION (out_buf) = duration;
    memcpy (GST_BUFFER_DATA (out_buf), pBuffer,
        MIN ((unsigned int)size, GST_BUFFER_SIZE (out_buf)));

    /* we have to remove some heading samples */
    if ((GstClockTime) clip_start > buf_start) {
      start_offset = (guint)gst_util_uint64_scale_int (clip_start - buf_start,
          mDec->rate, GST_SECOND) * mDec->depth / 8 * mDec->channels;
    }
    else
      start_offset = 0;
    /* we have to remove some trailing samples */
    if ((GstClockTime) clip_stop < buf_stop) {
      stop_offset = (guint)gst_util_uint64_scale_int (buf_stop - clip_stop,
          mDec->rate, GST_SECOND) * mDec->depth / 8 * mDec->channels;
    }
    else
      stop_offset = size;

    /* truncating */
    if ((start_offset != 0) || (stop_offset != (size_t) size)) {
      GstBuffer *subbuf = gst_buffer_create_sub (out_buf, start_offset,
          stop_offset - start_offset);

      if (subbuf) {
        gst_buffer_set_caps (subbuf, GST_PAD_CAPS (mDec->srcpad));
        gst_buffer_unref (out_buf);
        out_buf = subbuf;
      }
    }

    GST_BUFFER_TIMESTAMP (out_buf) = clip_start;
    GST_BUFFER_DURATION (out_buf) = clip_stop - clip_start;

    /* replace the saved stop position by the clipped one */
    mDec->timestamp = clip_stop;

    GST_DEBUG_OBJECT (mDec,
        "push_buffer (size %d)=> pts %" GST_TIME_FORMAT " stop %" GST_TIME_FORMAT
        " duration %" GST_TIME_FORMAT, size,
        GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (out_buf)),
        GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (out_buf) +
            GST_BUFFER_DURATION (out_buf)),
        GST_TIME_ARGS (GST_BUFFER_DURATION (out_buf)));

    mDec->last_ret = gst_pad_push (mDec->srcpad, out_buf);
  }

done:
  return S_OK;
}
示例#5
0
static OSErr
data_proc (SGChannel c, Ptr p, long len, long * offset, long chRefCon,
           TimeValue time, short writeType, long refCon)
{
    GstOSXVideoSrc * self;
    gint fps_n, fps_d;
    GstClockTime duration, timestamp, latency;
    CodecFlags flags;
    ComponentResult err;
    PixMapHandle hPixMap;
    Rect portRect;
    int pix_rowBytes;
    void *pix_ptr;
    int pix_height;
    int pix_size;

    self = GST_OSX_VIDEO_SRC (refCon);

    if (self->buffer != NULL) {
        gst_buffer_unref (self->buffer);
        self->buffer = NULL;
    }

    err = DecompressSequenceFrameS (self->dec_seq, p, len, 0, &flags, NULL);
    if (err != noErr) {
        GST_ERROR_OBJECT (self, "DecompressSequenceFrameS returned %d", (int) err);
        return err;
    }

    hPixMap = GetGWorldPixMap (self->world);
    LockPixels (hPixMap);
    GetPortBounds (self->world, &portRect);
    pix_rowBytes = (int) GetPixRowBytes (hPixMap);
    pix_ptr = GetPixBaseAddr (hPixMap);
    pix_height = (portRect.bottom - portRect.top);
    pix_size = pix_rowBytes * pix_height;

    GST_DEBUG_OBJECT (self, "num=%5d, height=%d, rowBytes=%d, size=%d",
                      self->seq_num, pix_height, pix_rowBytes, pix_size);

    fps_n = FRAMERATE;
    fps_d = 1;

    duration = gst_util_uint64_scale_int (GST_SECOND, fps_d, fps_n);
    latency = duration;

    timestamp = gst_clock_get_time (GST_ELEMENT_CAST (self)->clock);
    timestamp -= gst_element_get_base_time (GST_ELEMENT_CAST (self));
    if (timestamp > latency)
        timestamp -= latency;
    else
        timestamp = 0;

    self->buffer = gst_buffer_new_and_alloc (pix_size);
    GST_BUFFER_OFFSET (self->buffer) = self->seq_num;
    GST_BUFFER_TIMESTAMP (self->buffer) = timestamp;
    memcpy (GST_BUFFER_DATA (self->buffer), pix_ptr, pix_size);

    self->seq_num++;

    UnlockPixels (hPixMap);

    return noErr;
}
示例#6
0
static GstFlowReturn
gst_scene_change_filter_ip_I420 (GstVideoFilter2 * videofilter2,
    GstBuffer * buf, int start, int end)
{
  GstSceneChange *scenechange;
  double score_min;
  double score_max;
  double threshold;
  double score;
  gboolean change;
  int i;
  int width;
  int height;

  g_return_val_if_fail (GST_IS_SCENE_CHANGE (videofilter2), GST_FLOW_ERROR);
  scenechange = GST_SCENE_CHANGE (videofilter2);

  width = GST_VIDEO_FILTER2_WIDTH (videofilter2);
  height = GST_VIDEO_FILTER2_HEIGHT (videofilter2);

  if (!scenechange->oldbuf) {
    scenechange->n_diffs = 0;
    memset (scenechange->diffs, 0, sizeof (double) * SC_N_DIFFS);
    scenechange->oldbuf = gst_buffer_ref (buf);
    return GST_FLOW_OK;
  }

  score = get_frame_score (GST_BUFFER_DATA (scenechange->oldbuf),
      GST_BUFFER_DATA (buf), width, height);

  memmove (scenechange->diffs, scenechange->diffs + 1,
      sizeof (double) * (SC_N_DIFFS - 1));
  scenechange->diffs[SC_N_DIFFS - 1] = score;
  scenechange->n_diffs++;

  gst_buffer_unref (scenechange->oldbuf);
  scenechange->oldbuf = gst_buffer_ref (buf);

  score_min = scenechange->diffs[0];
  score_max = scenechange->diffs[0];
  for (i = 1; i < SC_N_DIFFS - 1; i++) {
    score_min = MIN (score_min, scenechange->diffs[i]);
    score_max = MAX (score_max, scenechange->diffs[i]);
  }

  threshold = 1.8 * score_max - 0.8 * score_min;

  if (scenechange->n_diffs > 2) {
    if (score < 5) {
      change = FALSE;
    } else if (score / threshold < 1.0) {
      change = FALSE;
    } else if (score / threshold > 2.5) {
      change = TRUE;
    } else if (score > 50) {
      change = TRUE;
    } else {
      change = FALSE;
    }
  } else {
    change = FALSE;
  }

#ifdef TESTING
  if (change != is_shot_change (scenechange->n_diffs)) {
    g_print ("%d %g %g %g %d\n", scenechange->n_diffs, score / threshold,
        score, threshold, change);
  }
#endif

  if (change) {
    GstEvent *event;

    GST_DEBUG_OBJECT (scenechange, "%d %g %g %g %d",
        scenechange->n_diffs, score / threshold, score, threshold, change);

    event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM,
        gst_structure_new ("GstForceKeyUnit", NULL));

    gst_pad_push_event (GST_BASE_TRANSFORM_SRC_PAD (scenechange), event);
  }

  return GST_FLOW_OK;
}
示例#7
0
static GstFlowReturn gst_devsound_src_create(GstBaseSrc *src, guint64 offset,
        guint size, GstBuffer **buf)
    {
    GstDevsoundSrc *dsrc= GST_DEVSOUND_SRC(src);
    int bufferpos=0;
    int ret = KErrNone;
    
    if(!g_queue_get_length(dataqueue) && (dsrc->eosreceived == TRUE))
        {
        pthread_mutex_lock(&(create_mutex1));
        pthread_cond_signal(&(create_condition1));
        pthread_mutex_unlock(&(create_mutex1));
        post_symbian_error( src,KErrCancel );
        return GST_FLOW_UNEXPECTED;
        }
    
    //gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) dsrc, "gst_devsound_src_create ENTER ");

    //gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) dsrc, "Before Buffer Alloc in CREATE ",NULL);
    *buf = gst_buffer_try_new_and_alloc(size);
    //gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) dsrc, "AFter Buffer Alloc in CREATE ",NULL);
    if(*buf == NULL)
    {
        post_symbian_error( src,KErrNoMemory );
        return GST_FLOW_UNEXPECTED;
    }        
    
    while (size > 0)
        {
        if (dataleft >= size)
            {
            // if there is some data left in the popped buffer previously whose size
            // is more then the buffer which is incoming fresh to get filled, fill it
            //here. and if the data left in the popped buffer is 0, then unref it
            //gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) dsrc, "dataleft >=size in CREATE ", NULL);
            memcpy(GST_BUFFER_DATA(*buf)+bufferpos,GST_BUFFER_DATA(popBuffer)+dataCopied,size);
            bufferpos+=size;
            dataCopied += size;
            dataleft = GST_BUFFER_SIZE(popBuffer) - dataCopied;
            size = 0;
            if (dataleft == 0)
                {
                dataCopied = 0;
                gst_buffer_unref(popBuffer);
                popBuffer = NULL;
                }
            }
        else
            {
            // if the dataleft in the popped buffer is greater then 0 and  less then
            // the size of data needed for the fresh buffer. copy the remaining data
            // from the popped buffer and then unref it.
            if (dataleft > 0)
                {
                //gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) dsrc, "dataleft >0 in CREATE ",NULL);
                memcpy(GST_BUFFER_DATA(*buf)+bufferpos,GST_BUFFER_DATA(popBuffer)+dataCopied,dataleft);
                size -= dataleft;
                bufferpos += dataleft;
                dataCopied = 0;
                dataleft = 0;
                gst_buffer_unref(popBuffer);
                popBuffer = NULL;
                }

            // we wait here if the dataqueue length is 0 and we need data
            // to be filled in the queue from the DevSound Thread
            if (!g_queue_get_length(dataqueue))
                {
                //gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) dsrc, "Before WAIT in CREATE ",NULL);
                if(dsrc->eosreceived == TRUE)
                    {
                    post_symbian_error( src,KErrCancel );
                    return GST_FLOW_UNEXPECTED;
                    }
                else
                    {
                    cmd = RECORDING;
                    return_error = KErrNone;
                    pthread_mutex_lock(&(create_mutex1));
                    pthread_cond_signal(&(create_condition1));
                    pthread_mutex_unlock(&(create_mutex1));
                    
                    pthread_mutex_lock(&(create_mutex1));
                    pthread_cond_wait(&(create_condition1), &(create_mutex1));
                    ret = return_error;
                    pthread_mutex_unlock(&(create_mutex1));
                    }
                //gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) dsrc, "AFTER WAIT in CREATE ",NULL);
                }
            if( ret )
            { 
                post_symbian_error( src,ret );
                return GST_FLOW_UNEXPECTED;
            }
            //gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) dsrc, "Before POP in CREATE ",NULL);
            GST_OBJECT_LOCK(dsrc);
            popBuffer = (GstBuffer*)g_queue_pop_tail(dataqueue);
            GST_OBJECT_UNLOCK(dsrc);
           
            if(!popBuffer )
            {
                post_symbian_error( src,KErrNoMemory );
                return GST_FLOW_UNEXPECTED;
            }
            if(dsrc->firstTimeInit != kPlayed)
                {        
                dsrc->prevbuffersize = gst_base_src_get_blocksize(src);
                gst_base_src_set_blocksize (src, GST_BUFFER_SIZE(popBuffer));
                (*buf)->size = GST_BUFFER_SIZE(popBuffer);
                }
            // copy the data from the popped buffer based on how much of the incoming
            //buffer size is left to fill. we might have filled the fresh buffer somewhat
            // where the size of the fresh buffer is more then the data remaining in the
            // popped buffer.
            if (size < GST_BUFFER_SIZE(popBuffer))
                {
                //gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) dsrc, "SIZE < POPBUFFER CREATE ",NULL);
                memcpy(GST_BUFFER_DATA(*buf)+ bufferpos,GST_BUFFER_DATA(popBuffer),size);
                bufferpos+=size;
                dataCopied = size;
                dataleft = GST_BUFFER_SIZE(popBuffer) - dataCopied;
                size = 0;
                }
            else
                {
                //gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) dsrc, "SIZE >= POPBUFFER CREATE ",NULL);
                memcpy(GST_BUFFER_DATA(*buf)+ bufferpos,GST_BUFFER_DATA(popBuffer),GST_BUFFER_SIZE(popBuffer));
                bufferpos+=GST_BUFFER_SIZE(popBuffer);
                dataCopied = 0;
                dataleft = 0;
                size = size - GST_BUFFER_SIZE(popBuffer);
                }

            if (!dataleft)
                {
                gst_buffer_unref(popBuffer);
                popBuffer = NULL;
                }
            }
        if (dsrc->firstTimeInit == kPlayBufferPreRoll)
            {
            gst_base_src_set_blocksize (src, dsrc->prevbuffersize);
            dsrc->firstTimeInit = kPlayed;
            return GST_FLOW_OK;
            }
        
        if (dsrc->firstTimeInit == kPausedToPlaying)
            {
            dsrc->firstTimeInit = kPlayBufferPreRoll;
            return GST_FLOW_OK;
            }
       }
    //gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) dsrc, "gst_devsound_src_create EXIT ",NULL);
    return GST_FLOW_OK;
    }
示例#8
0
static GstFlowReturn
gst_identity_transform_ip (GstBaseTransform * trans, GstBuffer * buf)
{
  GstFlowReturn ret = GST_FLOW_OK;
  GstIdentity *identity = GST_IDENTITY (trans);
  GstClockTime runtimestamp = G_GINT64_CONSTANT (0);

  if (identity->check_perfect)
    gst_identity_check_perfect (identity, buf);
  if (identity->check_imperfect_timestamp)
    gst_identity_check_imperfect_timestamp (identity, buf);
  if (identity->check_imperfect_offset)
    gst_identity_check_imperfect_offset (identity, buf);

  /* update prev values */
  identity->prev_timestamp = GST_BUFFER_TIMESTAMP (buf);
  identity->prev_duration = GST_BUFFER_DURATION (buf);
  identity->prev_offset_end = GST_BUFFER_OFFSET_END (buf);
  identity->prev_offset = GST_BUFFER_OFFSET (buf);

  if (identity->error_after >= 0) {
    identity->error_after--;
    if (identity->error_after == 0) {
      GST_ELEMENT_ERROR (identity, CORE, FAILED,
          (_("Failed after iterations as requested.")), (NULL));
      return GST_FLOW_ERROR;
    }
  }

  if (identity->drop_probability > 0.0) {
    if ((gfloat) (1.0 * rand () / (RAND_MAX)) < identity->drop_probability) {
      if (!identity->silent) {
        GST_OBJECT_LOCK (identity);
        g_free (identity->last_message);
        identity->last_message =
            g_strdup_printf
            ("dropping   ******* (%s:%s)i (%d bytes, timestamp: %"
            GST_TIME_FORMAT ", duration: %" GST_TIME_FORMAT ", offset: %"
            G_GINT64_FORMAT ", offset_end: % " G_GINT64_FORMAT
            ", flags: %d) %p", GST_DEBUG_PAD_NAME (trans->sinkpad),
            GST_BUFFER_SIZE (buf), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
            GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_BUFFER_OFFSET (buf),
            GST_BUFFER_OFFSET_END (buf), GST_BUFFER_FLAGS (buf), buf);
        GST_OBJECT_UNLOCK (identity);
        gst_identity_notify_last_message (identity);
      }
      /* return DROPPED to basetransform. */
      return GST_BASE_TRANSFORM_FLOW_DROPPED;
    }
  }

  if (identity->dump) {
    gst_util_dump_mem (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
  }

  if (!identity->silent) {
    GST_OBJECT_LOCK (identity);
    g_free (identity->last_message);
    identity->last_message =
        g_strdup_printf ("chain   ******* (%s:%s)i (%d bytes, timestamp: %"
        GST_TIME_FORMAT ", duration: %" GST_TIME_FORMAT ", offset: %"
        G_GINT64_FORMAT ", offset_end: % " G_GINT64_FORMAT ", flags: %d) %p",
        GST_DEBUG_PAD_NAME (trans->sinkpad), GST_BUFFER_SIZE (buf),
        GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
        GST_TIME_ARGS (GST_BUFFER_DURATION (buf)),
        GST_BUFFER_OFFSET (buf), GST_BUFFER_OFFSET_END (buf),
        GST_BUFFER_FLAGS (buf), buf);
    GST_OBJECT_UNLOCK (identity);
    gst_identity_notify_last_message (identity);
  }

  if (identity->datarate > 0) {
    GstClockTime time = gst_util_uint64_scale_int (identity->offset,
        GST_SECOND, identity->datarate);

    GST_BUFFER_TIMESTAMP (buf) = time;
    GST_BUFFER_DURATION (buf) =
        GST_BUFFER_SIZE (buf) * GST_SECOND / identity->datarate;
  }

  if (identity->signal_handoffs)
    g_signal_emit (identity, gst_identity_signals[SIGNAL_HANDOFF], 0, buf);

  if (trans->segment.format == GST_FORMAT_TIME)
    runtimestamp = gst_segment_to_running_time (&trans->segment,
        GST_FORMAT_TIME, GST_BUFFER_TIMESTAMP (buf));

  if ((identity->sync) && (trans->segment.format == GST_FORMAT_TIME)) {
    GstClock *clock;

    GST_OBJECT_LOCK (identity);
    if ((clock = GST_ELEMENT (identity)->clock)) {
      GstClockReturn cret;
      GstClockTime timestamp;

      timestamp = runtimestamp + GST_ELEMENT (identity)->base_time;

      /* save id if we need to unlock */
      /* FIXME: actually unlock this somewhere in the state changes */
      identity->clock_id = gst_clock_new_single_shot_id (clock, timestamp);
      GST_OBJECT_UNLOCK (identity);

      cret = gst_clock_id_wait (identity->clock_id, NULL);

      GST_OBJECT_LOCK (identity);
      if (identity->clock_id) {
        gst_clock_id_unref (identity->clock_id);
        identity->clock_id = NULL;
      }
      if (cret == GST_CLOCK_UNSCHEDULED)
        ret = GST_FLOW_UNEXPECTED;
    }
    GST_OBJECT_UNLOCK (identity);
  }

  identity->offset += GST_BUFFER_SIZE (buf);

  if (identity->sleep_time && ret == GST_FLOW_OK)
    g_usleep (identity->sleep_time);

  if (identity->single_segment && (trans->segment.format == GST_FORMAT_TIME)
      && (ret == GST_FLOW_OK)) {
    GST_BUFFER_TIMESTAMP (buf) = runtimestamp;
    GST_BUFFER_OFFSET (buf) = GST_CLOCK_TIME_NONE;
    GST_BUFFER_OFFSET_END (buf) = GST_CLOCK_TIME_NONE;
  }

  return ret;
}
static GstFlowReturn
gst_slvideo_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size,
			  GstCaps * caps, GstBuffer ** buf)
{
	gint width, height;
	GstStructure *structure = NULL;
	GstSLVideo *slvideo;
	slvideo = GST_SLVIDEO(bsink);

	// caps == requested caps
	// we can ignore these and reverse-negotiate our preferred dimensions with
	// the peer if we like - we need to do this to obey dynamic resize requests
	// flowing in from the app.
	structure = llgst_caps_get_structure (caps, 0);
	if (!llgst_structure_get_int(structure, "width", &width) ||
	    !llgst_structure_get_int(structure, "height", &height))
	{
		GST_WARNING_OBJECT (slvideo, "no width/height in caps %" GST_PTR_FORMAT, caps);
		return GST_FLOW_NOT_NEGOTIATED;
	}

	GstBuffer *newbuf = llgst_buffer_new();
	bool made_bufferdata_ptr = false;
#define MAXDEPTHHACK 4
	
	GST_OBJECT_LOCK(slvideo);
	if (slvideo->resize_forced_always) // app is giving us a fixed size to work with
	{
		gint slwantwidth, slwantheight;
		slwantwidth = slvideo->resize_try_width;
		slwantheight = slvideo->resize_try_height;
	
		if (slwantwidth != width ||
		    slwantheight != height)
		{
			// don't like requested caps, we will issue our own suggestion - copy
			// the requested caps but substitute our own width and height and see
			// if our peer is happy with that.
		
			GstCaps *desired_caps;
			GstStructure *desired_struct;
			desired_caps = llgst_caps_copy (caps);
			desired_struct = llgst_caps_get_structure (desired_caps, 0);
			
			GValue value = {0};
			g_value_init(&value, G_TYPE_INT);
			g_value_set_int(&value, slwantwidth);
			llgst_structure_set_value (desired_struct, "width", &value);
			g_value_unset(&value);
			g_value_init(&value, G_TYPE_INT);
			g_value_set_int(&value, slwantheight);
			llgst_structure_set_value (desired_struct, "height", &value);
			
			if (llgst_pad_peer_accept_caps (GST_VIDEO_SINK_PAD (slvideo),
							desired_caps))
			{
				// todo: re-use buffers from a pool?
				// todo: set MALLOCDATA to null, set DATA to point straight to shm?
				
				// peer likes our cap suggestion
				DEBUGMSG("peer loves us :)");
				GST_BUFFER_SIZE(newbuf) = slwantwidth * slwantheight * MAXDEPTHHACK;
				GST_BUFFER_MALLOCDATA(newbuf) = (guint8*)g_malloc(GST_BUFFER_SIZE(newbuf));
				GST_BUFFER_DATA(newbuf) = GST_BUFFER_MALLOCDATA(newbuf);
				llgst_buffer_set_caps (GST_BUFFER_CAST(newbuf), desired_caps);

				made_bufferdata_ptr = true;
			} else {
				// peer hates our cap suggestion
				INFOMSG("peer hates us :(");
				llgst_caps_unref(desired_caps);
			}
		}
	}

	GST_OBJECT_UNLOCK(slvideo);

	if (!made_bufferdata_ptr) // need to fallback to malloc at original size
	{
		GST_BUFFER_SIZE(newbuf) = width * height * MAXDEPTHHACK;
		GST_BUFFER_MALLOCDATA(newbuf) = (guint8*)g_malloc(GST_BUFFER_SIZE(newbuf));
		GST_BUFFER_DATA(newbuf) = GST_BUFFER_MALLOCDATA(newbuf);
		llgst_buffer_set_caps (GST_BUFFER_CAST(newbuf), caps);
	}

	*buf = GST_BUFFER_CAST(newbuf);

	return GST_FLOW_OK;
}
示例#10
0
static GstFlowReturn
gst_amrwbenc_chain (GstPad * pad, GstBuffer * buffer)
{
  GstAmrwbEnc *amrwbenc;
  GstFlowReturn ret = GST_FLOW_OK;
  const int buffer_size = sizeof (Word16) * L_FRAME16k;

  amrwbenc = GST_AMRWBENC (gst_pad_get_parent (pad));

  g_return_val_if_fail (amrwbenc->handle, GST_FLOW_WRONG_STATE);

  if (amrwbenc->rate == 0 || amrwbenc->channels == 0) {
    ret = GST_FLOW_NOT_NEGOTIATED;
    goto done;
  }

  /* discontinuity clears adapter, FIXME, maybe we can set some
   * encoder flag to mask the discont. */
  if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT)) {
    gst_adapter_clear (amrwbenc->adapter);
    amrwbenc->ts = 0;
    amrwbenc->discont = TRUE;
  }

  if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer))
    amrwbenc->ts = GST_BUFFER_TIMESTAMP (buffer);

  ret = GST_FLOW_OK;
  gst_adapter_push (amrwbenc->adapter, buffer);

  /* Collect samples until we have enough for an output frame */
  while (gst_adapter_available (amrwbenc->adapter) >= buffer_size) {
    GstBuffer *out;
    guint8 *data;
    gint outsize;

    out = gst_buffer_new_and_alloc (buffer_size);
    GST_BUFFER_DURATION (out) = GST_SECOND * L_FRAME16k /
        (amrwbenc->rate * amrwbenc->channels);
    GST_BUFFER_TIMESTAMP (out) = amrwbenc->ts;
    if (amrwbenc->ts != -1) {
      amrwbenc->ts += GST_BUFFER_DURATION (out);
    }
    if (amrwbenc->discont) {
      GST_BUFFER_FLAG_SET (out, GST_BUFFER_FLAG_DISCONT);
      amrwbenc->discont = FALSE;
    }
    gst_buffer_set_caps (out, gst_pad_get_caps (amrwbenc->srcpad));

    data = (guint8 *) gst_adapter_peek (amrwbenc->adapter, buffer_size);

    /* encode */
    outsize =
        E_IF_encode (amrwbenc->handle, amrwbenc->bandmode, (Word16 *) data,
        (UWord8 *) GST_BUFFER_DATA (out), 0);

    gst_adapter_flush (amrwbenc->adapter, buffer_size);
    GST_BUFFER_SIZE (out) = outsize;

    /* play */
    if ((ret = gst_pad_push (amrwbenc->srcpad, out)) != GST_FLOW_OK)
      break;
  }

done:

  gst_object_unref (amrwbenc);
  return ret;

}
示例#11
0
static GstTagDemuxResult
gst_ape_demux_parse_tag (GstTagDemux * demux, GstBuffer * buffer,
    gboolean start_tag, guint * tag_size, GstTagList ** tags)
{
  const guint8 *data;
  const guint8 *footer;
  gboolean have_header;
  gboolean end_tag = !start_tag;
  GstCaps *sink_caps;
  guint version, footer_size;

  GST_LOG_OBJECT (demux, "Parsing buffer of size %u", GST_BUFFER_SIZE (buffer));

  data = GST_BUFFER_DATA (buffer);
  footer = GST_BUFFER_DATA (buffer) + GST_BUFFER_SIZE (buffer) - 32;

  GST_LOG_OBJECT (demux, "Checking for footer at offset 0x%04x",
      (guint) (footer - data));
  if (footer > data && memcmp (footer, "APETAGEX", 8) == 0) {
    GST_DEBUG_OBJECT (demux, "Found footer");
    footer_size = 32;
  } else {
    GST_DEBUG_OBJECT (demux, "No footer");
    footer_size = 0;
  }

  /* APE tags at the end must have a footer */
  if (end_tag && footer_size == 0) {
    GST_WARNING_OBJECT (demux, "Tag at end of file without footer!");
    return GST_TAG_DEMUX_RESULT_BROKEN_TAG;
  }

  /* don't trust the header/footer flags, better detect them ourselves */
  have_header = (memcmp (data, "APETAGEX", 8) == 0);

  if (start_tag && !have_header) {
    GST_DEBUG_OBJECT (demux, "Tag at beginning of file without header!");
    return GST_TAG_DEMUX_RESULT_BROKEN_TAG;
  }

  if (end_tag && !have_header) {
    GST_DEBUG_OBJECT (demux, "Tag at end of file has no header (APEv1)");
    *tag_size -= 32;            /* adjust tag size */
  }

  if (have_header) {
    version = GST_READ_UINT32_LE (data + 8);
  } else {
    version = GST_READ_UINT32_LE (footer + 8);
  }

  /* skip header */
  if (have_header) {
    data += 32;
  }

  GST_DEBUG_OBJECT (demux, "APE tag with version %u, size %u at offset 0x%08"
      G_GINT64_MODIFIER "x", version, *tag_size,
      GST_BUFFER_OFFSET (buffer) + ((have_header) ? 0 : 32));

  if (APE_VERSION_MAJOR (version) != 1 && APE_VERSION_MAJOR (version) != 2) {
    GST_WARNING ("APE tag is version %u.%03u, but decoder only supports "
        "v1 or v2. Ignoring.", APE_VERSION_MAJOR (version), version % 1000);
    return GST_TAG_DEMUX_RESULT_OK;
  }

  *tags = ape_demux_parse_tags (data, *tag_size - footer_size);

  sink_caps = gst_static_pad_template_get_caps (&sink_factory);
  gst_pb_utils_add_codec_description_to_tag_list (*tags,
      GST_TAG_CONTAINER_FORMAT, sink_caps);
  gst_caps_unref (sink_caps);

  return GST_TAG_DEMUX_RESULT_OK;
}
static GstFlowReturn
gst_base_rtp_audio_payload_push_buffer (GstBaseRTPAudioPayload *
    baseaudiopayload, GstBuffer * buffer)
{
  GstBaseRTPPayload *basepayload;
  GstBaseRTPAudioPayloadPrivate *priv;
  GstBuffer *outbuf;
  GstClockTime timestamp;
  guint8 *payload;
  guint payload_len;
  GstFlowReturn ret;

  priv = baseaudiopayload->priv;
  basepayload = GST_BASE_RTP_PAYLOAD (baseaudiopayload);

  payload_len = GST_BUFFER_SIZE (buffer);
  timestamp = GST_BUFFER_TIMESTAMP (buffer);

  GST_DEBUG_OBJECT (baseaudiopayload, "Pushing %d bytes ts %" GST_TIME_FORMAT,
      payload_len, GST_TIME_ARGS (timestamp));

  if (priv->buffer_list) {
    /* create just the RTP header buffer */
    outbuf = gst_rtp_buffer_new_allocate (0, 0, 0);
  } else {
    /* create buffer to hold the payload */
    outbuf = gst_rtp_buffer_new_allocate (payload_len, 0, 0);
  }

  /* set metadata */
  gst_base_rtp_audio_payload_set_meta (baseaudiopayload, outbuf, payload_len,
      timestamp);

  if (priv->buffer_list) {
    GstBufferList *list;
    GstBufferListIterator *it;

    list = gst_buffer_list_new ();
    it = gst_buffer_list_iterate (list);

    /* add both buffers to the buffer list */
    gst_buffer_list_iterator_add_group (it);
    gst_buffer_list_iterator_add (it, outbuf);
    gst_buffer_list_iterator_add (it, buffer);

    gst_buffer_list_iterator_free (it);

    GST_DEBUG_OBJECT (baseaudiopayload, "Pushing list %p", list);
    ret = gst_basertppayload_push_list (basepayload, list);
  } else {
    /* copy payload */
    payload = gst_rtp_buffer_get_payload (outbuf);
    memcpy (payload, GST_BUFFER_DATA (buffer), payload_len);
    gst_buffer_unref (buffer);

    GST_DEBUG_OBJECT (baseaudiopayload, "Pushing buffer %p", outbuf);
    ret = gst_basertppayload_push (basepayload, outbuf);
  }

  return ret;
}
示例#13
0
文件: gstpgmdec.c 项目: ladiko/walet
static GstFlowReturn gst_pgmdec_chain (GstPad * pad, GstBuffer * in)
{
	GstFlowReturn ret = GST_FLOW_OK;
	GstBuffer *out;
	Gstpgmdec *filter = GST_PGMDEC (GST_OBJECT_PARENT (pad));
	//GstCaps *caps = GST_PAD_CAPS (filter->srcpad);
	GstCaps *caps;
	guint byts=0;
	gchar line[4][20];
	//const gchar *l;
	gint  i;
	//GstStructure *structure = gst_caps_get_structure (caps, 0);

	guint8 *outbuf;
	guint8 *inbuf;

	//Get pgm header
	if(!GST_BUFFER_OFFSET(in)){
		//filter->buff = in;
		inbuf = (guint8 *) GST_BUFFER_DATA (in);
		byts = sscanf(inbuf, "%s%s%s%s", line[0], line[1], line[2], line[3]);
		if (strcmp(line[0], "P5") != 0) {
			GST_WARNING ("It's not PGM file");
			return FALSE;
		}
		filter->width = atoi(line[1]);
		filter->height = atoi(line[2]);
		filter->bpp = (atoi(line[3]) > 256) ? 16 : 8;
		for(i=0; i<4; i++) byts += strlen(line[i]);
		filter->size = (filter->bpp == 8) ? filter->width*filter->height : filter->width*filter->height*2;

		//gst_buffer_set_data(filter->buff, &inbuf[byts], GST_BUFFER_SIZE(in)-byts);
		//filter->buff = &inbuf[byts];

		GST_DEBUG_OBJECT (filter, "The file type is : %s width = %d height = %d bpp = %d",
				line[0], filter->width, filter->height, filter->bpp);
		GST_DEBUG_OBJECT (filter, "DATA = %p SIZE = %d OFFSET = %d",
				GST_BUFFER_DATA(in), GST_BUFFER_SIZE(in), GST_BUFFER_OFFSET(in));

		filter->buff = gst_buffer_new_and_alloc(filter->size);
		for(i=0;i < GST_BUFFER_SIZE(in)-byts; i++) GST_BUFFER_DATA(filter->buff)[i] = GST_BUFFER_DATA(in)[byts+i];
		GST_BUFFER_OFFSET(filter->buff) = GST_BUFFER_SIZE(in)-byts;
		gst_buffer_unref(in);

		return GST_FLOW_OK;

		//gst_event_new_seek (1.0,
		//      GST_FORMAT_BYTES,
		//      GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SEGMENT |GST_SEEK_FLAG_ACCURATE,
		//      GST_SEEK_TYPE_SET, byts,
		//      GST_SEEK_TYPE_SET, filter->size + byts);

	}

	//Check for the buffer size
	if(GST_BUFFER_OFFSET(filter->buff) < GST_BUFFER_SIZE(filter->buff)) {
		for(i=0; i < GST_BUFFER_SIZE(in); i++) GST_BUFFER_DATA(filter->buff)[GST_BUFFER_OFFSET(filter->buff) + i] = GST_BUFFER_DATA(in)[i];
		GST_BUFFER_OFFSET(filter->buff) += GST_BUFFER_SIZE(in);
		//GST_DEBUG_OBJECT (filter, "DATA = %p SIZE = %d OFFSET = %d",GST_BUFFER_DATA(filter->buff), GST_BUFFER_SIZE(filter->buff),GST_BUFFER_OFFSET(filter->buff));
		gst_buffer_unref(in);
		if(GST_BUFFER_OFFSET(filter->buff) != GST_BUFFER_SIZE(filter->buff)) return GST_FLOW_OK;
	}

	GST_DEBUG_OBJECT (filter, "DATA = %p SIZE = %d OFFSET = %d",
				GST_BUFFER_DATA(filter->buff), GST_BUFFER_SIZE(filter->buff), GST_BUFFER_OFFSET(filter->buff));

	caps = gst_caps_new_simple ("video/x-raw-bayer",
								"width", G_TYPE_INT, filter->width,
								"height", G_TYPE_INT, filter->height,
								"bpp", G_TYPE_INT, filter->bpp,
								"framerate", GST_TYPE_FRACTION, 0, 1,
								NULL);
	gst_buffer_set_caps(filter->buff, caps);
	gst_pad_set_caps (filter->srcpad, caps);
	gst_pad_use_fixed_caps (filter->srcpad);
	gst_caps_unref (caps);

  /* just push out the incoming buffer without touching it */
	ret = gst_pad_push(filter->srcpad, filter->buff);
	return ret;
}
示例#14
0
static gboolean
start_play_tune (GstNsfDec * nsfdec)
{
  gboolean res;

  nsfdec->nsf = nsf_load (NULL, GST_BUFFER_DATA (nsfdec->tune_buffer),
      GST_BUFFER_SIZE (nsfdec->tune_buffer));

  if (!nsfdec->nsf)
    goto could_not_load;

  if (!nsfdec_negotiate (nsfdec))
    goto could_not_negotiate;

  nsfdec->taglist = gst_tag_list_new ();
  gst_tag_list_add (nsfdec->taglist, GST_TAG_MERGE_REPLACE,
      GST_TAG_AUDIO_CODEC, "NES Sound Format", NULL);

  if (nsfdec->nsf->artist_name)
    gst_tag_list_add (nsfdec->taglist, GST_TAG_MERGE_REPLACE,
        GST_TAG_ARTIST, nsfdec->nsf->artist_name, NULL);

  if (nsfdec->nsf->song_name)
    gst_tag_list_add (nsfdec->taglist, GST_TAG_MERGE_REPLACE,
        GST_TAG_TITLE, nsfdec->nsf->song_name, NULL);

  gst_element_post_message (GST_ELEMENT_CAST (nsfdec),
      gst_message_new_tag (GST_OBJECT (nsfdec),
          gst_tag_list_copy (nsfdec->taglist)));

  nsf_playtrack (nsfdec->nsf,
      nsfdec->tune_number, nsfdec->frequency, nsfdec->bits, nsfdec->stereo);
  nsf_setfilter (nsfdec->nsf, nsfdec->filter);

  nsfdec->bps = (nsfdec->bits >> 3) * nsfdec->channels;
  /* calculate the number of bytes we need to output after each call to
   * nsf_frame(). */
  nsfdec->blocksize =
      nsfdec->bps * nsfdec->frequency / nsfdec->nsf->playback_rate;

  gst_pad_push_event (nsfdec->srcpad,
      gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME, 0, -1, 0));

  res = gst_pad_start_task (nsfdec->srcpad,
      (GstTaskFunction) play_loop, nsfdec->srcpad, NULL);

  return res;

  /* ERRORS */
could_not_load:
  {
    GST_ELEMENT_ERROR (nsfdec, LIBRARY, INIT,
        ("Could not load tune"), ("Could not load tune"));
    return FALSE;
  }
could_not_negotiate:
  {
    GST_ELEMENT_ERROR (nsfdec, CORE, NEGOTIATION,
        ("Could not negotiate format"), ("Could not negotiate format"));
    return FALSE;
  }
}
static GstV4l2Buffer *
gst_v4l2_buffer_new (GstV4l2BufferPool * pool, guint index, GstCaps * caps)
{
  GstV4l2Buffer *ret;
  guint8 *data;

  ret = (GstV4l2Buffer *) gst_mini_object_new (GST_TYPE_V4L2_BUFFER);

  GST_LOG_OBJECT (pool->v4l2elem, "creating buffer %u, %p in pool %p", index,
      ret, pool);

  ret->pool =
      (GstV4l2BufferPool *) gst_mini_object_ref (GST_MINI_OBJECT (pool));

  ret->vbuffer.index = index;
  ret->vbuffer.type = pool->type;
  ret->vbuffer.memory = V4L2_MEMORY_MMAP;

  if (v4l2_ioctl (pool->video_fd, VIDIOC_QUERYBUF, &ret->vbuffer) < 0)
    goto querybuf_failed;

  GST_LOG_OBJECT (pool->v4l2elem, "  index:     %u", ret->vbuffer.index);
  GST_LOG_OBJECT (pool->v4l2elem, "  type:      %d", ret->vbuffer.type);
  GST_LOG_OBJECT (pool->v4l2elem, "  bytesused: %u", ret->vbuffer.bytesused);
  GST_LOG_OBJECT (pool->v4l2elem, "  flags:     %08x", ret->vbuffer.flags);
  GST_LOG_OBJECT (pool->v4l2elem, "  field:     %d", ret->vbuffer.field);
  GST_LOG_OBJECT (pool->v4l2elem, "  memory:    %d", ret->vbuffer.memory);
  if (ret->vbuffer.memory == V4L2_MEMORY_MMAP)
    GST_LOG_OBJECT (pool->v4l2elem, "  MMAP offset:  %u",
        ret->vbuffer.m.offset);
  GST_LOG_OBJECT (pool->v4l2elem, "  length:    %u", ret->vbuffer.length);
  //GST_LOG_OBJECT (pool->v4l2elem, "  input:     %u", ret->vbuffer.input);

  data = (guint8 *) v4l2_mmap (0, ret->vbuffer.length,
      PROT_READ | PROT_WRITE, MAP_SHARED, pool->video_fd,
      ret->vbuffer.m.offset);

  if (data == MAP_FAILED)
    goto mmap_failed;

  GST_BUFFER_DATA (ret) = data;
  GST_BUFFER_SIZE (ret) = ret->vbuffer.length;

  GST_BUFFER_FLAG_SET (ret, GST_BUFFER_FLAG_READONLY);

  gst_buffer_set_caps (GST_BUFFER (ret), caps);

  return ret;

  /* ERRORS */
querybuf_failed:
  {
    gint errnosave = errno;

    GST_WARNING ("Failed QUERYBUF: %s", g_strerror (errnosave));
    gst_buffer_unref (GST_BUFFER (ret));
    errno = errnosave;
    return NULL;
  }
mmap_failed:
  {
    gint errnosave = errno;

    GST_WARNING ("Failed to mmap: %s", g_strerror (errnosave));
    gst_buffer_unref (GST_BUFFER (ret));
    errno = errnosave;
    return NULL;
  }
}
示例#16
0
GstFlowReturn
gst_kate_util_decoder_base_chain_kate_packet (GstKateDecoderBase * decoder,
    GstElement * element, GstPad * pad, GstBuffer * buf, GstPad * srcpad,
    GstPad * tagpad, GstCaps ** src_caps, const kate_event ** ev)
{
  kate_packet kp;
  int ret;
  GstFlowReturn rflow = GST_FLOW_OK;
  gboolean is_header;

  GST_DEBUG_OBJECT (element, "got kate packet, %u bytes, type %02x",
      GST_BUFFER_SIZE (buf),
      GST_BUFFER_SIZE (buf) == 0 ? -1 : GST_BUFFER_DATA (buf)[0]);

  is_header = GST_BUFFER_SIZE (buf) > 0 && (GST_BUFFER_DATA (buf)[0] & 0x80);

  if (!is_header && decoder->tags) {
    /* after we've processed headers, send any tags before processing the data packet */
    GST_DEBUG_OBJECT (element, "Not a header, sending tags for pad %s:%s",
        GST_DEBUG_PAD_NAME (tagpad));
    gst_element_found_tags_for_pad (element, tagpad, decoder->tags);
    decoder->tags = NULL;
  }

  kate_packet_wrap (&kp, GST_BUFFER_SIZE (buf), GST_BUFFER_DATA (buf));
  ret = kate_high_decode_packetin (&decoder->k, &kp, ev);
  if (G_UNLIKELY (ret < 0)) {
    GST_ELEMENT_ERROR (element, STREAM, DECODE, (NULL),
        ("Failed to decode Kate packet: %s",
            gst_kate_util_get_error_message (ret)));
    return GST_FLOW_ERROR;
  }

  if (G_UNLIKELY (ret > 0)) {
    GST_DEBUG_OBJECT (element,
        "kate_high_decode_packetin has received EOS packet");
  }

  /* headers may be interesting to retrieve information from */
  if (G_UNLIKELY (is_header)) {
    switch (GST_BUFFER_DATA (buf)[0]) {
      case 0x80:               /* ID header */
        GST_INFO_OBJECT (element, "Parsed ID header: language %s, category %s",
            decoder->k.ki->language, decoder->k.ki->category);
        if (src_caps) {
          if (*src_caps) {
            gst_caps_unref (*src_caps);
            *src_caps = NULL;
          }
          if (strcmp (decoder->k.ki->category, "K-SPU") == 0 ||
              strcmp (decoder->k.ki->category, "spu-subtitles") == 0) {
            *src_caps = gst_caps_new_simple ("video/x-dvd-subpicture", NULL);
          } else if (decoder->k.ki->text_markup_type == kate_markup_none) {
            *src_caps = gst_caps_new_simple ("text/plain", NULL);
          } else {
            *src_caps = gst_caps_new_simple ("text/x-pango-markup", NULL);
          }
          GST_INFO_OBJECT (srcpad, "Setting caps: %" GST_PTR_FORMAT, *src_caps);
          if (!gst_pad_set_caps (srcpad, *src_caps)) {
            GST_ERROR_OBJECT (srcpad, "Failed to set caps %" GST_PTR_FORMAT,
                *src_caps);
          }
        }
        if (decoder->k.ki->language && *decoder->k.ki->language) {
          GstTagList *old = decoder->tags, *tags = gst_tag_list_new ();
          if (tags) {
            gchar *lang_code;

            /* en_GB -> en */
            lang_code = g_ascii_strdown (decoder->k.ki->language, -1);
            g_strdelimit (lang_code, NULL, '\0');
            gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_LANGUAGE_CODE,
                lang_code, NULL);
            g_free (lang_code);
            /* TODO: category - where should it go ? */
            decoder->tags =
                gst_tag_list_merge (decoder->tags, tags, GST_TAG_MERGE_REPLACE);
            gst_tag_list_free (tags);
            if (old)
              gst_tag_list_free (old);
          }
        }

        /* update properties */
        if (decoder->language)
          g_free (decoder->language);
        decoder->language = g_strdup (decoder->k.ki->language);
        if (decoder->category)
          g_free (decoder->category);
        decoder->category = g_strdup (decoder->k.ki->category);
        decoder->original_canvas_width = decoder->k.ki->original_canvas_width;
        decoder->original_canvas_height = decoder->k.ki->original_canvas_height;

        /* we can now send away any event we've delayed, as the src pad now has caps */
        gst_kate_util_decoder_base_drain_event_queue (decoder);

        break;

      case 0x81:               /* Vorbis comments header */
        GST_INFO_OBJECT (element, "Parsed comments header");
        {
          gchar *encoder = NULL;
          GstTagList *old = decoder->tags, *list =
              gst_tag_list_from_vorbiscomment_buffer (buf,
              (const guint8 *) "\201kate\0\0\0\0", 9, &encoder);
          if (list) {
            decoder->tags =
                gst_tag_list_merge (decoder->tags, list, GST_TAG_MERGE_REPLACE);
            gst_tag_list_free (list);
          }

          if (!decoder->tags) {
            GST_ERROR_OBJECT (element, "failed to decode comment header");
            decoder->tags = gst_tag_list_new ();
          }
          if (encoder) {
            gst_tag_list_add (decoder->tags, GST_TAG_MERGE_REPLACE,
                GST_TAG_ENCODER, encoder, NULL);
            g_free (encoder);
          }
          gst_tag_list_add (decoder->tags, GST_TAG_MERGE_REPLACE,
              GST_TAG_SUBTITLE_CODEC, "Kate", NULL);
          gst_tag_list_add (decoder->tags, GST_TAG_MERGE_REPLACE,
              GST_TAG_ENCODER_VERSION, decoder->k.ki->bitstream_version_major,
              NULL);

          if (old)
            gst_tag_list_free (old);

          if (decoder->initialized) {
            gst_element_found_tags_for_pad (element, tagpad, decoder->tags);
            decoder->tags = NULL;
          } else {
            /* Only push them as messages for the time being. *
             * They will be pushed on the pad once the decoder is initialized */
            gst_element_post_message (element,
                gst_message_new_tag (GST_OBJECT (element),
                    gst_tag_list_copy (decoder->tags)));
          }
        }
        break;

      default:
        break;
    }
  }
#if ((KATE_VERSION_MAJOR<<16)|(KATE_VERSION_MINOR<<8)|KATE_VERSION_PATCH) >= 0x000400
  else if (*ev && (*ev)->meta) {
    int count = kate_meta_query_count ((*ev)->meta);
    if (count > 0) {
      GstTagList *evtags = gst_tag_list_new ();
      int idx;
      GST_DEBUG_OBJECT (decoder, "Kate event has %d attached metadata", count);
      for (idx = 0; idx < count; ++idx) {
        const char *tag, *value;
        size_t len;
        if (kate_meta_query ((*ev)->meta, idx, &tag, &value, &len) < 0) {
          GST_WARNING_OBJECT (decoder, "Failed to retrieve metadata %d", idx);
        } else {
          if (gst_kate_util_is_utf8_string (value, len)) {
            gchar *compound = g_strdup_printf ("%s=%s", tag, value);
            GST_DEBUG_OBJECT (decoder, "Metadata %d: %s=%s (%zu bytes)", idx,
                tag, value, len);
            gst_tag_list_add (evtags, GST_TAG_MERGE_APPEND,
                GST_TAG_EXTENDED_COMMENT, compound, NULL);
            g_free (compound);
          } else {
            GST_INFO_OBJECT (decoder,
                "Metadata %d, (%s, %zu bytes) is binary, ignored", idx, tag,
                len);
          }
        }
      }
      if (gst_tag_list_is_empty (evtags))
        gst_tag_list_free (evtags);
      else
        gst_element_found_tags_for_pad (element, tagpad, evtags);
    }
  }
#endif

  return rflow;
}
示例#17
0
static GstElement *
setup_jitterbuffer (gint num_buffers)
{
  GstElement *jitterbuffer;
  GstClock *clock;
  GstBuffer *buffer;
  GstCaps *caps;
  /* generated with
   * gst-launch audiotestsrc wave=silence blocksize=40 num-buffers=3 ! 
   *    "audio/x-raw-int,channels=1,rate=8000" ! mulawenc ! rtppcmupay !
   *     fakesink dump=1
   */
  guint8 in[] = {               /* first 4 bytes are rtp-header, next 4 bytes are timestamp */
    0x80, 0x80, 0x1c, 0x24, 0x46, 0xcd, 0xb7, 0x11, 0x3c, 0x3a, 0x7c, 0x5b,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
  };
  GstClockTime ts = G_GUINT64_CONSTANT (0);
  GstClockTime tso = gst_util_uint64_scale (RTP_FRAME_SIZE, GST_SECOND, 8000);
  /*guint latency = GST_TIME_AS_MSECONDS (num_buffers*tso); */
  gint i;

  GST_DEBUG ("setup_jitterbuffer");
  jitterbuffer = gst_check_setup_element ("gstrtpjitterbuffer");
  /* we need a clock here */
  clock = gst_system_clock_obtain ();
  gst_element_set_clock (jitterbuffer, clock);
  gst_object_unref (clock);
  /* setup latency */
  /* latency would be 7 for 3 buffers here, default is 200
     g_object_set (G_OBJECT (jitterbuffer), "latency", latency, NULL);
     GST_INFO_OBJECT (jitterbuffer, "set latency to %u ms", latency);
   */

  mysrcpad = gst_check_setup_src_pad (jitterbuffer, &srctemplate, NULL);
  mysinkpad = gst_check_setup_sink_pad (jitterbuffer, &sinktemplate, NULL);
  gst_pad_set_active (mysrcpad, TRUE);
  gst_pad_set_active (mysinkpad, TRUE);

  /* create n buffers */
  caps = gst_caps_from_string (RTP_CAPS_STRING);
  for (i = 0; i < num_buffers; i++) {
    buffer = gst_buffer_new_and_alloc (sizeof (in));
    memcpy (GST_BUFFER_DATA (buffer), in, sizeof (in));
    gst_buffer_set_caps (buffer, caps);
    GST_BUFFER_TIMESTAMP (buffer) = ts;
    GST_BUFFER_DURATION (buffer) = tso;

    if (!i)
      GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);

    inbuffers = g_list_append (inbuffers, buffer);

    /* hackish way to update the rtp header */
    in[1] = 0x00;
    in[3]++;                    /* seqnumber */
    in[7] += RTP_FRAME_SIZE;    /* inc. timestamp with framesize */
    ts += tso;
  }
  gst_caps_unref (caps);

  return jitterbuffer;
}
示例#18
0
static GstFlowReturn
gst_mve_video_create_buffer (GstMveDemux * mve, guint8 version,
    const guint8 * data, guint16 len)
{
  GstBuffer *buf;
  guint16 w, h, n, true_color, bpp;
  guint required, size;

  GST_DEBUG_OBJECT (mve, "create video buffer");

  if (mve->video_stream == NULL) {
    GST_ELEMENT_ERROR (mve, STREAM, DECODE, (NULL),
        ("trying to create video buffer for uninitialized stream"));
    return GST_FLOW_ERROR;
  }

  /* need 4 to 8 more bytes */
  required = (version > 1) ? 8 : (version * 2);
  if (len < required)
    return gst_mve_stream_error (mve, required, len);

  w = GST_READ_UINT16_LE (data) << 3;
  h = GST_READ_UINT16_LE (data + 2) << 3;

  if (version > 0)
    n = GST_READ_UINT16_LE (data + 4);
  else
    n = 1;

  if (version > 1)
    true_color = GST_READ_UINT16_LE (data + 6);
  else
    true_color = 0;

  bpp = (true_color ? 2 : 1);
  size = w * h * bpp;

  if (mve->video_stream->buffer != NULL) {
    GST_DEBUG_OBJECT (mve, "video buffer already created");

    if (GST_BUFFER_SIZE (mve->video_stream->buffer) == size * 2)
      return GST_FLOW_OK;

    GST_DEBUG_OBJECT (mve, "video buffer size has changed");
    gst_buffer_unref (mve->video_stream->buffer);
  }

  GST_DEBUG_OBJECT (mve,
      "allocating video buffer, w:%u, h:%u, n:%u, true_color:%u", w, h, n,
      true_color);

  /* we need a buffer to keep the last 2 frames, since those may be
     needed for decoding the next one */
  buf = gst_buffer_new_and_alloc (size * 2);

  mve->video_stream->bpp = bpp;
  mve->video_stream->width = w;
  mve->video_stream->height = h;
  mve->video_stream->buffer = buf;
  mve->video_stream->back_buf1 = GST_BUFFER_DATA (buf);
  mve->video_stream->back_buf2 = mve->video_stream->back_buf1 + size;
  mve->video_stream->max_block_offset = (h - 7) * w - 8;
  memset (mve->video_stream->back_buf1, 0, size * 2);

  return GST_FLOW_OK;
}
示例#19
0
static void *StartDevSoundThread(void *threadarg)
    {
    GstDevsoundSrc *devsoundsrc= GST_DEVSOUND_SRC (threadarg);
    int buffersize;
    TUint8* gBuffer;
    GstBuffer* pushBuffer= NULL;
    //gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) devsoundsrc, "StartDevSoundThread ",NULL);
    int ret = open_devsound(&(devsoundsrc->handle));
    
    if( KErrNone != ret )
        {
        pthread_mutex_lock(&(create_mutex1));
        return_error = ret;
        pthread_cond_signal(&(create_condition1));
        pthread_mutex_unlock(&(create_mutex1));
        pthread_exit(NULL);
        }

    getsupporteddatatypes(devsoundsrc);

// TODO obtain mutex to update variable here???
    consumer_thread_state = CONSUMER_THREAD_INITIALIZED;
	
    //pre_init_setconf(devsoundsrc);

    //gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) devsoundsrc, "After Record Init ",NULL);

    pthread_mutex_lock(&(create_mutex1));
    return_error = ret;
    pthread_cond_signal(&(create_condition1));
    pthread_mutex_unlock(&(create_mutex1));

    // Wait until we receive a command from the main thread
    // TODO obtain mutex to read variable here???
    while ( cmd == OPEN )
        {
        pthread_mutex_lock(&create_mutex1);
        pthread_cond_wait(&create_condition1, &create_mutex1);
        pthread_mutex_unlock(&create_mutex1);
        }

    // This could happen if client creates sink and deletes it
    // without putting it to play state
    if ( cmd != CLOSE )
        {
        gst_update_devsound_speech_bitrate(devsoundsrc);
        ret = initialize_devsound(devsoundsrc);
        if( KErrNone == ret )
            {
                ret = recordinit(devsoundsrc->handle);
                if( KErrNone == ret )
                    initproperties(devsoundsrc);
        
            }
        /// if initialization of devsound failed, return error,
        /// on return other thread will send CLOSE cmd to exit from thread.
        if( ret )
            {
            pthread_mutex_lock(&(create_mutex1));
            return_error = ret;
            pthread_cond_signal(&(create_condition1));
            pthread_mutex_unlock(&(create_mutex1));
            
            pthread_mutex_lock(&create_mutex1);
            pthread_cond_wait(&create_condition1, &create_mutex1);
            pthread_mutex_unlock(&create_mutex1);
            }
        }

    while (TRUE)
        {
        switch (cmd)
            {
            case PAUSE:
                pause_devsound(devsoundsrc);
                break;
                
            case RESUME:
                resume_devsound(devsoundsrc);
                break;
            
            case STOP:
                stop_devsound(devsoundsrc);
                break;
                
            case RECORDING:
                {
                pre_init_setconf(devsoundsrc);
//                gst_Apply_SpeechEncoder_Update(devsoundsrc);
                gst_Apply_G711Encoder_Update(devsoundsrc);
                gst_Apply_G729Encoder_Update(devsoundsrc );
                gst_Apply_IlbcEncoder_Update(devsoundsrc );

                populateproperties(devsoundsrc);

                supportedbitrates = devsoundsrc->supportedbitrates;
                //numofbitrates = devsoundsrc->numofbitrates;
                speechbitrate = devsoundsrc->speechbitrate;
                speechvadmode = devsoundsrc->speechvadmode;
                g711vadmode = devsoundsrc->g711vadmode;
                g729vadmode  = devsoundsrc->g729vadmode;
                ilbcvadmode = devsoundsrc->ilbcvadmode;

                buffersize = get_databuffer_size(devsoundsrc->handle);
                get_databuffer(devsoundsrc->handle, &gBuffer);
                pushBuffer = gst_buffer_new_and_alloc(buffersize);
                memcpy(GST_BUFFER_DATA(pushBuffer),gBuffer,buffersize);
                
                GST_OBJECT_LOCK(devsoundsrc);
                g_queue_push_head (dataqueue,pushBuffer);
                GST_OBJECT_UNLOCK(devsoundsrc);
                
                record_data(devsoundsrc->handle);
                }
                break;
            case CLOSE:
                {
                //gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) devsoundsrc, "Before Close DevSound ",NULL);
                close_devsound(devsoundsrc);
                //gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) devsoundsrc, "After Close DevSound ",NULL);
                devsoundsrc->handle= NULL;
                //gst_debug_log(devsound_debug, GST_LEVEL_LOG, "", "", 0, (GObject *) devsoundsrc, "After handle NULL ",NULL);

                pthread_mutex_lock(&(create_mutex1));
                pthread_cond_signal(&(create_condition1));
                pthread_mutex_unlock(&(create_mutex1));
                // TODO obtain mutex here
                consumer_thread_state = CONSUMER_THREAD_UNINITIALIZED;
                pthread_exit(NULL);
                }
                break;
            default:
                // TODO obtain mutex here
                consumer_thread_state = CONSUMER_THREAD_UNINITIALIZED;          
                pthread_exit(NULL);
                break;
            }
        pthread_mutex_lock(&(create_mutex1));
        return_error = call_back_error(devsoundsrc->handle);
        pthread_cond_signal(&(create_condition1));
        pthread_mutex_unlock(&(create_mutex1));
        
        pthread_mutex_lock(&create_mutex1);
        pthread_cond_wait(&create_condition1, &create_mutex1);
        pthread_mutex_unlock(&create_mutex1);
        }
    }
示例#20
0
static GstFlowReturn
gst_mve_video_palette (GstMveDemux * mve, const guint8 * data, guint16 len)
{
  GstBuffer *buf;
  guint16 start, count;
  const guint8 *pal;
  guint32 *pal_ptr;
  gint i;

  GST_DEBUG_OBJECT (mve, "video palette");

  if (mve->video_stream == NULL) {
    GST_ELEMENT_ERROR (mve, STREAM, DECODE, (NULL),
        ("found palette before video stream was initialized"));
    return GST_FLOW_ERROR;
  }

  /* need 4 more bytes now, more later */
  if (len < 4)
    return gst_mve_stream_error (mve, 4, len);

  len -= 4;

  start = GST_READ_UINT16_LE (data);
  count = GST_READ_UINT16_LE (data + 2);
  GST_DEBUG_OBJECT (mve, "found palette start:%u, count:%u", start, count);

  /* need more bytes */
  if (len < count * 3)
    return gst_mve_stream_error (mve, count * 3, len);

  /* make sure we don't exceed the buffer */
  if (start + count > MVE_PALETTE_COUNT) {
    GST_ELEMENT_ERROR (mve, STREAM, DECODE, (NULL),
        ("palette too large for buffer"));
    return GST_FLOW_ERROR;
  }

  if (mve->video_stream->palette != NULL) {
    /* older buffers floating around might still use the old
       palette, so make sure we can update it */
    buf = gst_buffer_make_writable (mve->video_stream->palette);
  } else {
    buf = gst_buffer_new_and_alloc (MVE_PALETTE_COUNT * 4);
    memset (GST_BUFFER_DATA (buf), 0, GST_BUFFER_SIZE (buf));
  }

  mve->video_stream->palette = buf;

  pal = data + 4;
  pal_ptr = ((guint32 *) GST_BUFFER_DATA (buf)) + start;
  for (i = 0; i < count; ++i) {
    /* convert from 6-bit VGA to 8-bit palette */
    guint8 r, g, b;

    r = (*pal) << 2;
    ++pal;
    g = (*pal) << 2;
    ++pal;
    b = (*pal) << 2;
    ++pal;
    *pal_ptr = (r << 16) | (g << 8) | (b);
    ++pal_ptr;
  }
  return GST_FLOW_OK;
}
示例#21
0
static void
gst_snapshot_chain (GstPad * pad, GstData * _data)
{
  GstBuffer *buf = GST_BUFFER (_data);
  GstSnapshot *snapshot;
  guchar *data;
  gulong size;
  gint i;
  png_byte *row_pointers[MAX_HEIGHT];
  FILE *fp;

  g_return_if_fail (pad != NULL);
  g_return_if_fail (GST_IS_PAD (pad));
  g_return_if_fail (buf != NULL);

  snapshot = GST_SNAPSHOT (GST_OBJECT_PARENT (pad));

  data = GST_BUFFER_DATA (buf);
  size = GST_BUFFER_SIZE (buf);

  GST_DEBUG ("snapshot: have buffer of %d\n", GST_BUFFER_SIZE (buf));

  snapshot->cur_frame++;
  if (snapshot->cur_frame == snapshot->frame ||
      snapshot->snapshot_asked == TRUE) {
    snapshot->snapshot_asked = FALSE;

    GST_INFO ("dumpfile : %s\n", snapshot->location);
    fp = fopen (snapshot->location, "wb");
    if (fp == NULL)
      g_warning (" Can not open %s\n", snapshot->location);
    else {
      snapshot->png_struct_ptr =
          png_create_write_struct (PNG_LIBPNG_VER_STRING, (png_voidp) NULL,
          user_error_fn, user_warning_fn);
      if (snapshot->png_struct_ptr == NULL)
        g_warning ("Failed to initialize png structure");

      snapshot->png_info_ptr =
          png_create_info_struct (snapshot->png_struct_ptr);

      if (setjmp (snapshot->png_struct_ptr->jmpbuf))
        png_destroy_write_struct (&snapshot->png_struct_ptr,
            &snapshot->png_info_ptr);

      png_set_filter (snapshot->png_struct_ptr, 0,
          PNG_FILTER_NONE | PNG_FILTER_VALUE_NONE);
      png_init_io (snapshot->png_struct_ptr, fp);
      png_set_compression_level (snapshot->png_struct_ptr, 9);
      png_set_IHDR (snapshot->png_struct_ptr,
          snapshot->png_info_ptr,
          snapshot->width,
          snapshot->height,
          snapshot->to_bpp / 3,
          PNG_COLOR_TYPE_RGB,
          PNG_INTERLACE_NONE,
          PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);

      for (i = 0; i < snapshot->height; i++)
        row_pointers[i] = data + (snapshot->width * i * snapshot->to_bpp / 8);

      png_write_info (snapshot->png_struct_ptr, snapshot->png_info_ptr);
      png_write_image (snapshot->png_struct_ptr, row_pointers);
      png_write_end (snapshot->png_struct_ptr, NULL);
      png_destroy_info_struct (snapshot->png_struct_ptr,
          &snapshot->png_info_ptr);
      png_destroy_write_struct (&snapshot->png_struct_ptr, (png_infopp) NULL);
      fclose (fp);
    }
  }

  gst_pad_push (snapshot->srcpad, GST_DATA (buf));
}
示例#22
0
static GstFlowReturn
gst_mve_video_data (GstMveDemux * mve, const guint8 * data, guint16 len,
    GstBuffer ** output)
{
  GstFlowReturn ret = GST_FLOW_OK;
  gint16 cur_frame, last_frame;
  gint16 x_offset, y_offset;
  gint16 x_size, y_size;
  guint16 flags;
  gint dec;
  GstBuffer *buf = NULL;
  GstMveDemuxStream *s = mve->video_stream;

  GST_LOG_OBJECT (mve, "video data");

  if (s == NULL) {
    GST_ELEMENT_ERROR (mve, STREAM, DECODE, (NULL),
        ("trying to decode video data before stream was initialized"));
    return GST_FLOW_ERROR;
  }

  if (GST_CLOCK_TIME_IS_VALID (mve->frame_duration)) {
    if (GST_CLOCK_TIME_IS_VALID (s->last_ts))
      s->last_ts += mve->frame_duration;
    else
      s->last_ts = 0;
  }

  if (!s->code_map_avail) {
    GST_ELEMENT_ERROR (mve, STREAM, DECODE, (NULL),
        ("no code map available for decoding"));
    return GST_FLOW_ERROR;
  }

  /* need at least 14 more bytes */
  if (len < 14)
    return gst_mve_stream_error (mve, 14, len);

  len -= 14;

  cur_frame = GST_READ_UINT16_LE (data);
  last_frame = GST_READ_UINT16_LE (data + 2);
  x_offset = GST_READ_UINT16_LE (data + 4);
  y_offset = GST_READ_UINT16_LE (data + 6);
  x_size = GST_READ_UINT16_LE (data + 8);
  y_size = GST_READ_UINT16_LE (data + 10);
  flags = GST_READ_UINT16_LE (data + 12);
  data += 14;

  GST_DEBUG_OBJECT (mve,
      "video data hot:%d, cold:%d, xoff:%d, yoff:%d, w:%d, h:%d, flags:%x",
      cur_frame, last_frame, x_offset, y_offset, x_size, y_size, flags);

  if (flags & MVE_VIDEO_DELTA_FRAME) {
    guint8 *temp = s->back_buf1;

    s->back_buf1 = s->back_buf2;
    s->back_buf2 = temp;
  }

  ret = gst_mve_buffer_alloc_for_pad (s, s->width * s->height * s->bpp, &buf);
  if (ret != GST_FLOW_OK)
    return ret;

  if (s->bpp == 2) {
    dec = ipvideo_decode_frame16 (s, data, len);
  } else {
    if (s->palette == NULL) {
      GST_ELEMENT_ERROR (mve, STREAM, DECODE, (NULL), ("no palette available"));
      goto error;
    }

    dec = ipvideo_decode_frame8 (s, data, len);
  }
  if (dec != 0)
    goto error;

  memcpy (GST_BUFFER_DATA (buf), s->back_buf1, GST_BUFFER_SIZE (buf));
  GST_BUFFER_DURATION (buf) = mve->frame_duration;
  GST_BUFFER_OFFSET_END (buf) = ++s->offset;

  if (s->bpp == 1) {
    GstCaps *caps;

    /* set the palette on the outgoing buffer */
    caps = gst_caps_copy (s->caps);
    gst_caps_set_simple (caps,
        "palette_data", GST_TYPE_BUFFER, s->palette, NULL);
    gst_buffer_set_caps (buf, caps);
    gst_caps_unref (caps);
  }

  *output = buf;
  return GST_FLOW_OK;

error:
  gst_buffer_unref (buf);
  return GST_FLOW_ERROR;
}
示例#23
0
static AM_MEDIA_TYPE *
dshowaudiodec_set_input_format (GstDshowAudioDec *adec, GstCaps *caps)
{
  AM_MEDIA_TYPE *mediatype;
  WAVEFORMATEX *format;
  GstDshowAudioDecClass *klass =
      (GstDshowAudioDecClass *) G_OBJECT_GET_CLASS (adec);
  const AudioCodecEntry *codec_entry = klass->entry;
  int size;

  mediatype = (AM_MEDIA_TYPE *)g_malloc0 (sizeof(AM_MEDIA_TYPE));
  mediatype->majortype = MEDIATYPE_Audio;
  GUID subtype = GUID_MEDIASUBTYPE_FROM_FOURCC (0x00000000);
  subtype.Data1 = codec_entry->format;
  mediatype->subtype = subtype;
  mediatype->bFixedSizeSamples = TRUE;
  mediatype->bTemporalCompression = FALSE;
  if (adec->block_align)
    mediatype->lSampleSize = adec->block_align;
  else
    mediatype->lSampleSize = 8192; /* need to evaluate it dynamically */
  mediatype->formattype = FORMAT_WaveFormatEx;

  /* We need this special behaviour for layers 1 and 2 (layer 3 uses a different
   * decoder which doesn't need this */
  if (adec->layer == 1 || adec->layer == 2) {
    MPEG1WAVEFORMAT *mpeg1_format;
    int samples, version;
    GstStructure *structure = gst_caps_get_structure (caps, 0);

    size = sizeof (MPEG1WAVEFORMAT);
    format = (WAVEFORMATEX *)g_malloc0 (size);
    format->cbSize = sizeof (MPEG1WAVEFORMAT) - sizeof (WAVEFORMATEX);
    format->wFormatTag = WAVE_FORMAT_MPEG;

    mpeg1_format = (MPEG1WAVEFORMAT *) format;

    mpeg1_format->wfx.nChannels = adec->channels;
    if (adec->channels == 2)
      mpeg1_format->fwHeadMode = ACM_MPEG_STEREO;
    else
      mpeg1_format->fwHeadMode = ACM_MPEG_SINGLECHANNEL;
    
    mpeg1_format->fwHeadModeExt = 0;
    mpeg1_format->wHeadEmphasis = 0;
    mpeg1_format->fwHeadFlags = 0;

    switch (adec->layer) {
      case 1:
        mpeg1_format->fwHeadLayer = ACM_MPEG_LAYER3;
        break;
      case 2:
        mpeg1_format->fwHeadLayer = ACM_MPEG_LAYER2;
        break;
      case 3:
        mpeg1_format->fwHeadLayer = ACM_MPEG_LAYER1;
        break;
    };

    gst_structure_get_int (structure, "mpegaudioversion", &version);
    if (adec->layer == 1) {
      samples = 384;
    } else {
      if (version == 1) {
        samples = 576;
      } else {
        samples = 1152;
      }
    }
    mpeg1_format->wfx.nBlockAlign = (WORD) samples;
    mpeg1_format->wfx.nSamplesPerSec = adec->rate;
    mpeg1_format->dwHeadBitrate = 128000; /* This doesn't seem to matter */
    mpeg1_format->wfx.nAvgBytesPerSec = mpeg1_format->dwHeadBitrate / 8;
  } 
  else 
  {
    size = sizeof (WAVEFORMATEX) +
        (adec->codec_data ? GST_BUFFER_SIZE (adec->codec_data) : 0);

    if (adec->layer == 3) {
      MPEGLAYER3WAVEFORMAT *mp3format;

      /* The WinXP mp3 decoder doesn't actually check the size of this structure, 
       * but requires that this be allocated and filled out (or we get obscure
       * random crashes)
       */
      size = sizeof (MPEGLAYER3WAVEFORMAT);
      mp3format = (MPEGLAYER3WAVEFORMAT *)g_malloc0 (size);
      format = (WAVEFORMATEX *)mp3format;
      format->cbSize = MPEGLAYER3_WFX_EXTRA_BYTES;

      mp3format->wID = MPEGLAYER3_ID_MPEG;
      mp3format->fdwFlags = MPEGLAYER3_FLAG_PADDING_ISO; /* No idea what this means for a decoder */

      /* The XP decoder divides by nBlockSize, so we must set this to a
         non-zero value, but it doesn't matter what - this is meaningless
         for VBR mp3 anyway */
      mp3format->nBlockSize = 1;
      mp3format->nFramesPerBlock = 1;
      mp3format->nCodecDelay = 0;
    }
    else {
      format = (WAVEFORMATEX *)g_malloc0 (size);
      if (adec->codec_data) {     /* Codec data is appended after our header */
        memcpy (((guchar *) format) + sizeof (WAVEFORMATEX),
            GST_BUFFER_DATA (adec->codec_data),
            GST_BUFFER_SIZE (adec->codec_data));
        format->cbSize = GST_BUFFER_SIZE (adec->codec_data);
      }
    }

    format->wFormatTag = codec_entry->format;
    format->nChannels = adec->channels;
    format->nSamplesPerSec = adec->rate;
    format->nAvgBytesPerSec = adec->bitrate / 8;
    format->nBlockAlign = adec->block_align;
    format->wBitsPerSample = adec->depth;
  }

  mediatype->cbFormat = size;
  mediatype->pbFormat = (BYTE *) format;

  return mediatype;
}
示例#24
0
static GstFlowReturn
gst_mve_audio_data (GstMveDemux * mve, guint8 type, const guint8 * data,
    guint16 len, GstBuffer ** output)
{
  GstFlowReturn ret;
  GstMveDemuxStream *s = mve->audio_stream;
  GstBuffer *buf = NULL;
  guint16 stream_mask;
  guint16 size;

  GST_LOG_OBJECT (mve, "audio data");

  if (s == NULL) {
    GST_ELEMENT_ERROR (mve, STREAM, DECODE, (NULL),
        ("trying to queue samples with no audio stream"));
    return GST_FLOW_ERROR;
  }

  /* need at least 6 more bytes */
  if (len < 6)
    return gst_mve_stream_error (mve, 6, len);

  len -= 6;

  stream_mask = GST_READ_UINT16_LE (data + 2);
  size = GST_READ_UINT16_LE (data + 4);
  data += 6;

  if (stream_mask & MVE_DEFAULT_AUDIO_STREAM) {
    guint16 n_samples = size / s->n_channels / (s->sample_size / 8);
    GstClockTime duration = (GST_SECOND / s->sample_rate) * n_samples;

    if (type == MVE_OC_AUDIO_DATA) {
      guint16 required = (s->compression ? size / 2 + s->n_channels : size);

      if (len < required)
        return gst_mve_stream_error (mve, required, len);

      ret = gst_mve_buffer_alloc_for_pad (s, size, &buf);

      if (ret != GST_FLOW_OK)
        return ret;

      if (s->compression)
        ipaudio_uncompress ((gint16 *) GST_BUFFER_DATA (buf), size,
            data, s->n_channels);
      else
        memcpy (GST_BUFFER_DATA (buf), data, size);

      GST_DEBUG_OBJECT (mve, "created audio buffer, size:%u, stream_mask:%x",
          size, stream_mask);
    } else {
      /* silence - create a minimal buffer with no sound */
      size = s->n_channels * (s->sample_size / 8);
      ret = gst_mve_buffer_alloc_for_pad (s, size, &buf);
      memset (GST_BUFFER_DATA (buf), 0, size);
    }

    GST_BUFFER_DURATION (buf) = duration;
    GST_BUFFER_OFFSET_END (buf) = s->offset + n_samples;
    *output = buf;

    s->offset += n_samples;
    s->last_ts += duration;
  } else {
    /* alternate audio streams not supported.
       are there any movies which use them? */
    if (type == MVE_OC_AUDIO_DATA)
      GST_WARNING_OBJECT (mve, "found non-empty alternate audio stream");
  }

  return GST_FLOW_OK;
}
示例#25
0
static GstFlowReturn
gst_rtp_amr_pay_handle_buffer (GstBaseRTPPayload * basepayload,
    GstBuffer * buffer)
{
  GstRtpAMRPay *rtpamrpay;
  const gint *frame_size;
  GstFlowReturn ret;
  guint size, payload_len;
  GstBuffer *outbuf;
  guint8 *payload, *data, *payload_amr;
  GstClockTime timestamp, duration;
  guint packet_len, mtu;
  gint i, num_packets, num_nonempty_packets;
  gint amr_len;
  gboolean sid = FALSE;

  rtpamrpay = GST_RTP_AMR_PAY (basepayload);
  mtu = GST_BASE_RTP_PAYLOAD_MTU (rtpamrpay);

  size = GST_BUFFER_SIZE (buffer);
  data = GST_BUFFER_DATA (buffer);
  timestamp = GST_BUFFER_TIMESTAMP (buffer);
  duration = GST_BUFFER_DURATION (buffer);

  /* setup frame size pointer */
  if (rtpamrpay->mode == GST_RTP_AMR_P_MODE_NB)
    frame_size = nb_frame_size;
  else
    frame_size = wb_frame_size;

  GST_DEBUG_OBJECT (basepayload, "got %d bytes", size);

  /* FIXME, only
   * octet aligned, no interleaving, single channel, no CRC,
   * no robust-sorting. To fix this you need to implement the downstream
   * negotiation function. */

  /* first count number of packets and total amr frame size */
  amr_len = num_packets = num_nonempty_packets = 0;
  for (i = 0; i < size; i++) {
    guint8 FT;
    gint fr_size;

    FT = (data[i] & 0x78) >> 3;

    fr_size = frame_size[FT];
    GST_DEBUG_OBJECT (basepayload, "frame type %d, frame size %d", FT, fr_size);
    /* FIXME, we don't handle this yet.. */
    if (fr_size <= 0)
      goto wrong_size;

    if (fr_size == 5)
      sid = TRUE;

    amr_len += fr_size;
    num_nonempty_packets++;
    num_packets++;
    i += fr_size;
  }
  if (amr_len > size)
    goto incomplete_frame;

  /* we need one extra byte for the CMR, the ToC is in the input
   * data */
  payload_len = size + 1;

  /* get packet len to check against MTU */
  packet_len = gst_rtp_buffer_calc_packet_len (payload_len, 0, 0);
  if (packet_len > mtu)
    goto too_big;

  /* now alloc output buffer */
  outbuf = gst_rtp_buffer_new_allocate (payload_len, 0, 0);

  /* copy timestamp */
  GST_BUFFER_TIMESTAMP (outbuf) = timestamp;

  if (duration != GST_CLOCK_TIME_NONE)
    GST_BUFFER_DURATION (outbuf) = duration;
  else {
    GST_BUFFER_DURATION (outbuf) = num_packets * 20 * GST_MSECOND;
  }

  if (GST_BUFFER_IS_DISCONT (buffer)) {
    GST_DEBUG_OBJECT (basepayload, "discont, setting marker bit");
    GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
    gst_rtp_buffer_set_marker (outbuf, TRUE);
    gst_rtp_amr_pay_recalc_rtp_time (rtpamrpay, timestamp);
  }

  if (G_UNLIKELY (sid)) {
    gst_rtp_amr_pay_recalc_rtp_time (rtpamrpay, timestamp);
  }

  /* perfect rtptime */
  if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (rtpamrpay->first_ts))) {
    rtpamrpay->first_ts = timestamp;
    rtpamrpay->first_rtp_time = rtpamrpay->next_rtp_time;
  }
  GST_BUFFER_OFFSET (outbuf) = rtpamrpay->next_rtp_time;
  rtpamrpay->next_rtp_time +=
      (num_packets * 160) << (rtpamrpay->mode == GST_RTP_AMR_P_MODE_WB);

  /* get payload, this is now writable */
  payload = gst_rtp_buffer_get_payload (outbuf);

  /*   0 1 2 3 4 5 6 7
   *  +-+-+-+-+-+-+-+-+
   *  |  CMR  |R|R|R|R|
   *  +-+-+-+-+-+-+-+-+
   */
  payload[0] = 0xF0;            /* CMR, no specific mode requested */

  /* this is where we copy the AMR data, after num_packets FTs and the
   * CMR. */
  payload_amr = payload + num_packets + 1;

  /* copy data in payload, first we copy all the FTs then all
   * the AMR data. The last FT has to have the F flag cleared. */
  for (i = 1; i <= num_packets; i++) {
    guint8 FT;
    gint fr_size;

    /*   0 1 2 3 4 5 6 7
     *  +-+-+-+-+-+-+-+-+
     *  |F|  FT   |Q|P|P| more FT...
     *  +-+-+-+-+-+-+-+-+
     */
    FT = (*data & 0x78) >> 3;

    fr_size = frame_size[FT];

    if (i == num_packets)
      /* last packet, clear F flag */
      payload[i] = *data & 0x7f;
    else
      /* set F flag */
      payload[i] = *data | 0x80;

    memcpy (payload_amr, &data[1], fr_size);

    /* all sizes are > 0 since we checked for that above */
    data += fr_size + 1;
    payload_amr += fr_size;
  }

  gst_buffer_unref (buffer);

  ret = gst_basertppayload_push (basepayload, outbuf);

  return ret;

  /* ERRORS */
wrong_size:
  {
    GST_ELEMENT_ERROR (basepayload, STREAM, FORMAT,
        (NULL), ("received AMR frame with size <= 0"));
    gst_buffer_unref (buffer);

    return GST_FLOW_ERROR;
  }
incomplete_frame:
  {
    GST_ELEMENT_ERROR (basepayload, STREAM, FORMAT,
        (NULL), ("received incomplete AMR frames"));
    gst_buffer_unref (buffer);

    return GST_FLOW_ERROR;
  }
too_big:
  {
    GST_ELEMENT_ERROR (basepayload, STREAM, FORMAT,
        (NULL), ("received too many AMR frames for MTU"));
    gst_buffer_unref (buffer);

    return GST_FLOW_ERROR;
  }
}
示例#26
0
static void
deinterlace_frame_di_greedyh_packed (GstDeinterlaceMethod * method,
    const GstDeinterlaceField * history, guint history_count,
    GstBuffer * outbuf)
{
  GstDeinterlaceMethodGreedyH *self = GST_DEINTERLACE_METHOD_GREEDY_H (method);
  GstDeinterlaceMethodGreedyHClass *klass =
      GST_DEINTERLACE_METHOD_GREEDY_H_GET_CLASS (self);
  gint InfoIsOdd = 0;
  gint Line;
  gint RowStride = method->row_stride[0];
  gint FieldHeight = method->frame_height / 2;
  gint Pitch = method->row_stride[0] * 2;
  const guint8 *L1;             // ptr to Line1, of 3
  const guint8 *L2;             // ptr to Line2, the weave line
  const guint8 *L3;             // ptr to Line3
  const guint8 *L2P;            // ptr to prev Line2
  guint8 *Dest = GST_BUFFER_DATA (outbuf);
  ScanlineFunction scanline;

  switch (method->format) {
    case GST_VIDEO_FORMAT_YUY2:
    case GST_VIDEO_FORMAT_YVYU:
      scanline = klass->scanline_yuy2;
      break;
    case GST_VIDEO_FORMAT_UYVY:
      scanline = klass->scanline_uyvy;
      break;
    case GST_VIDEO_FORMAT_AYUV:
      scanline = klass->scanline_ayuv;
      break;
    default:
      g_assert_not_reached ();
      break;
  }

  // copy first even line no matter what, and the first odd line if we're
  // processing an EVEN field. (note diff from other deint rtns.)

  if (history[history_count - 1].flags == PICTURE_INTERLACED_BOTTOM) {
    InfoIsOdd = 1;

    L1 = GST_BUFFER_DATA (history[history_count - 2].buf);
    if (history[history_count - 2].flags & PICTURE_INTERLACED_BOTTOM)
      L1 += RowStride;

    L2 = GST_BUFFER_DATA (history[history_count - 1].buf);
    if (history[history_count - 1].flags & PICTURE_INTERLACED_BOTTOM)
      L2 += RowStride;

    L3 = L1 + Pitch;
    L2P = GST_BUFFER_DATA (history[history_count - 3].buf);
    if (history[history_count - 3].flags & PICTURE_INTERLACED_BOTTOM)
      L2P += RowStride;

    // copy first even line
    memcpy (Dest, L1, RowStride);
    Dest += RowStride;
  } else {
    InfoIsOdd = 0;
    L1 = GST_BUFFER_DATA (history[history_count - 2].buf);
    if (history[history_count - 2].flags & PICTURE_INTERLACED_BOTTOM)
      L1 += RowStride;

    L2 = GST_BUFFER_DATA (history[history_count - 1].buf) + Pitch;
    if (history[history_count - 1].flags & PICTURE_INTERLACED_BOTTOM)
      L2 += RowStride;

    L3 = L1 + Pitch;
    L2P = GST_BUFFER_DATA (history[history_count - 3].buf) + Pitch;
    if (history[history_count - 3].flags & PICTURE_INTERLACED_BOTTOM)
      L2P += RowStride;

    // copy first even line
    memcpy (Dest, L1, RowStride);
    Dest += RowStride;
    // then first odd line
    memcpy (Dest, L1, RowStride);
    Dest += RowStride;
  }

  for (Line = 0; Line < (FieldHeight - 1); ++Line) {
    scanline (self, L1, L2, L3, L2P, Dest, RowStride);
    Dest += RowStride;
    memcpy (Dest, L3, RowStride);
    Dest += RowStride;

    L1 += Pitch;
    L2 += Pitch;
    L3 += Pitch;
    L2P += Pitch;
  }

  if (InfoIsOdd) {
    memcpy (Dest, L2, RowStride);
  }
}
示例#27
0
static void
gst_decklink_src_task (void *priv)
{
  GstDecklinkSrc *decklinksrc = GST_DECKLINK_SRC (priv);
  GstBuffer *buffer;
  GstBuffer *audio_buffer;
  IDeckLinkVideoInputFrame *video_frame;
  IDeckLinkAudioInputPacket *audio_frame;
  void *data;
  int n_samples;
  GstFlowReturn ret;
  const GstDecklinkMode *mode;

  GST_DEBUG_OBJECT (decklinksrc, "task");

  g_mutex_lock (decklinksrc->mutex);
  while (decklinksrc->video_frame == NULL && !decklinksrc->stop) {
    g_cond_wait (decklinksrc->cond, decklinksrc->mutex);
  }
  video_frame = decklinksrc->video_frame;
  audio_frame = decklinksrc->audio_frame;
  decklinksrc->video_frame = NULL;
  decklinksrc->audio_frame = NULL;
  g_mutex_unlock (decklinksrc->mutex);

  if (decklinksrc->stop) {
    if (video_frame)
      video_frame->Release ();
    if (audio_frame)
      audio_frame->Release ();
    GST_DEBUG ("stopping task");
    return;
  }

  /* warning on dropped frames */
  if (decklinksrc->dropped_frames - decklinksrc->dropped_frames_old > 0) {
    GST_ELEMENT_WARNING (decklinksrc, RESOURCE, READ,
        ("Dropped %d frame(s), for a total of %d frame(s)",
            decklinksrc->dropped_frames - decklinksrc->dropped_frames_old,
            decklinksrc->dropped_frames), (NULL));
    decklinksrc->dropped_frames_old = decklinksrc->dropped_frames;
  }

  if (!decklinksrc->video_new_segment) {
    GstEvent *event;
    gboolean ret;

    event = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME,
        0, GST_CLOCK_TIME_NONE, 0);

    ret = gst_pad_push_event (decklinksrc->videosrcpad, event);
    if (!ret) {
      GST_WARNING ("new segment event not handled");
    }

    decklinksrc->video_new_segment = TRUE;
  }

  mode = gst_decklink_get_mode (decklinksrc->mode);

  video_frame->GetBytes (&data);
  if (decklinksrc->copy_data) {
    buffer = gst_buffer_new_and_alloc (mode->width * mode->height * 2);

    memcpy (GST_BUFFER_DATA (buffer), data, mode->width * mode->height * 2);

    video_frame->Release ();
  } else {
    VideoFrame *vf;

    vf = (VideoFrame *) g_malloc0 (sizeof (VideoFrame));
    buffer = gst_buffer_new ();
    GST_BUFFER_SIZE (buffer) = mode->width * mode->height * 2;

    GST_BUFFER_DATA (buffer) = (guint8 *) data;

    GST_BUFFER_FREE_FUNC (buffer) = video_frame_free;
    GST_BUFFER_MALLOCDATA (buffer) = (guint8 *) vf;
    vf->frame = video_frame;
    vf->input = decklinksrc->input;
    vf->input->AddRef ();
  }

  GST_BUFFER_TIMESTAMP (buffer) =
      gst_util_uint64_scale_int (decklinksrc->frame_num * GST_SECOND,
      mode->fps_d, mode->fps_n);
  GST_BUFFER_DURATION (buffer) =
      gst_util_uint64_scale_int ((decklinksrc->frame_num + 1) * GST_SECOND,
      mode->fps_d, mode->fps_n) - GST_BUFFER_TIMESTAMP (buffer);
  GST_BUFFER_OFFSET (buffer) = decklinksrc->frame_num;
  GST_BUFFER_OFFSET_END (buffer) = decklinksrc->frame_num;
  if (decklinksrc->frame_num == 0) {
    GstEvent *event;
    gboolean ret;

    GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);

    event = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME, 0,
        GST_CLOCK_TIME_NONE, 0);

    if (gst_pad_is_linked (decklinksrc->videosrcpad)) {
      gst_event_ref (event);
      ret = gst_pad_push_event (decklinksrc->videosrcpad, event);
      if (!ret) {
        GST_ERROR_OBJECT (decklinksrc, "new segment event ret=%d", ret);
        gst_event_unref (event);
        return;
      }
    } else {
      gst_event_unref (event);
    }

    if (gst_pad_is_linked (decklinksrc->audiosrcpad)) {
      ret = gst_pad_push_event (decklinksrc->audiosrcpad, event);
      if (!ret) {
        GST_ERROR_OBJECT (decklinksrc, "new segment event ret=%d", ret);
        gst_event_unref (event);
      }
    } else {
      gst_event_unref (event);
    }

  }

  if (decklinksrc->video_caps == NULL) {
    decklinksrc->video_caps = gst_decklink_mode_get_caps (decklinksrc->mode);
  }
  gst_buffer_set_caps (buffer, decklinksrc->video_caps);

  ret = gst_pad_push (decklinksrc->videosrcpad, buffer);
  if (!(ret == GST_FLOW_OK || ret == GST_FLOW_NOT_LINKED ||
          ret == GST_FLOW_WRONG_STATE)) {
    GST_ELEMENT_ERROR (decklinksrc, STREAM, FAILED,
        ("Internal data stream error."),
        ("stream stopped, reason %s", gst_flow_get_name (ret)));
  }

  if (gst_pad_is_linked (decklinksrc->audiosrcpad)) {
    if (!decklinksrc->audio_new_segment) {
      GstEvent *event;
      gboolean ret;

      event = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME,
          0, GST_CLOCK_TIME_NONE, 0);

      ret = gst_pad_push_event (decklinksrc->audiosrcpad, event);
      if (!ret) {
        GST_WARNING ("new segment event not handled");
      }

      decklinksrc->audio_new_segment = TRUE;
    }

    n_samples = audio_frame->GetSampleFrameCount ();
    audio_frame->GetBytes (&data);
    audio_buffer = gst_buffer_new_and_alloc (n_samples * 2 * 2);
    memcpy (GST_BUFFER_DATA (audio_buffer), data, n_samples * 2 * 2);

    GST_BUFFER_TIMESTAMP (audio_buffer) =
        gst_util_uint64_scale_int (decklinksrc->num_audio_samples * GST_SECOND,
        1, 48000);
    GST_BUFFER_DURATION (audio_buffer) =
        gst_util_uint64_scale_int (n_samples * GST_SECOND, 1, 48000);
    decklinksrc->num_audio_samples += n_samples;

    if (decklinksrc->audio_caps == NULL) {
      decklinksrc->audio_caps = gst_caps_new_simple ("audio/x-raw-int",
          "endianness", G_TYPE_INT, G_LITTLE_ENDIAN,
          "signed", G_TYPE_BOOLEAN, TRUE,
          "depth", G_TYPE_INT, 16,
          "width", G_TYPE_INT, 16,
          "channels", G_TYPE_INT, 2, "rate", G_TYPE_INT, 48000, NULL);
    }
    gst_buffer_set_caps (audio_buffer, decklinksrc->audio_caps);

    ret = gst_pad_push (decklinksrc->audiosrcpad, audio_buffer);
    if (!(ret == GST_FLOW_OK || ret == GST_FLOW_NOT_LINKED ||
            ret == GST_FLOW_WRONG_STATE)) {
      GST_ELEMENT_ERROR (decklinksrc, STREAM, FAILED,
          ("Internal data stream error."),
          ("stream stopped, reason %s", gst_flow_get_name (ret)));
    }
  }
  if (audio_frame)
    audio_frame->Release ();
}
static GstFlowReturn mfw_gst_vpuenc_chain(GstPad * pad, GstBuffer * buffer)
{
	GstVPU_Enc *vpu_enc = NULL;
	GstFlowReturn retval = GST_FLOW_OK;
	GstCaps *src_caps;
	GstBuffer *outbuffer;
	gint i = 0;
	int ret;
	struct pollfd pollfd;
	unsigned long type = V4L2_BUF_TYPE_VIDEO_OUTPUT;

	GST_DEBUG(__func__);

	vpu_enc = MFW_GST_VPU_ENC(GST_PAD_PARENT(pad));

	if (vpu_enc->init == FALSE) {
		retval = mfw_gst_vpuenc_init_encoder(pad, vpu_enc->memory);
		if (retval != GST_FLOW_OK)
			return retval;
		printf("VPU ENC initialised\n");
	}

	i = 0;
	if (vpu_enc->memory == V4L2_MEMORY_USERPTR) {
		for (i = 0; i < NUM_BUFFERS; i++) {
			if (vpu_enc->buf_v4l2[i].m.userptr == (long int)GST_BUFFER_DATA (buffer))
				break;
		}
		if (i == NUM_BUFFERS) {
			for (i = 0; i < NUM_BUFFERS; i++) {
				if (!vpu_enc->buf_v4l2[i].m.userptr)
					break;
			}
		}
		i = i % NUM_BUFFERS;
	}

	if (i == NUM_BUFFERS) {
		printf("NO BUFFER AVAILABLE\n");
		return GST_FLOW_ERROR;
	}

	if (!buffer)
		return GST_FLOW_OK;

	if (vpu_enc->memory == V4L2_MEMORY_MMAP) {
		/* copy the input Frame into the allocated buffer */
		memcpy(vpu_enc->buf_data[i], GST_BUFFER_DATA(buffer), GST_BUFFER_SIZE(buffer));
		gst_buffer_unref(buffer);
	} else {
		vpu_enc->buf_v4l2[i].m.userptr = (long int)GST_BUFFER_DATA (buffer);
		vpu_enc->buf_v4l2[i].length = GST_BUFFER_SIZE (buffer);
	}

	pollfd.fd = vpu_enc->vpu_fd;
	pollfd.events = POLLIN | POLLOUT;

	ret = ioctl(vpu_enc->vpu_fd, VIDIOC_QBUF, &vpu_enc->buf_v4l2[i]);
	if (ret) {
		if (vpu_enc->memory == V4L2_MEMORY_USERPTR) {
			/* fallback to mmap */
			vpu_enc->init = FALSE;
			vpu_enc->memory = V4L2_MEMORY_MMAP;
			GST_WARNING("mfw_gst_vpuenc_chain: fallback to mmap");
			return mfw_gst_vpuenc_chain(pad, buffer);
		}
		GST_ERROR("VIDIOC_QBUF failed: %s\n", strerror(errno));
		return GST_FLOW_ERROR;
	}

	if (!vpu_enc->once) {
		retval = ioctl(vpu_enc->vpu_fd, VIDIOC_STREAMON, &type);
		if (retval) {
			printf("streamon failed with %d", retval);
			return GST_FLOW_ERROR;
		}
		vpu_enc->once = 1;
	}

	ret = ioctl(vpu_enc->vpu_fd, VIDIOC_DQBUF, &vpu_enc->buf_v4l2[0]);
	if (ret) {
		GST_ERROR("VIDIOC_DQBUF failed: %s\n", strerror(errno));
		return GST_FLOW_ERROR;
	}

	if (vpu_enc->memory == V4L2_MEMORY_USERPTR) {
		gst_buffer_unref(buffer);
	}

	src_caps = GST_PAD_CAPS(vpu_enc->srcpad);

	retval = gst_pad_alloc_buffer_and_set_caps(vpu_enc->srcpad,
			0, 1024 * 1024, src_caps, &outbuffer);
	if (retval != GST_FLOW_OK) {
		GST_ERROR("Allocating buffer failed with %d", ret);
		return retval;
	}

	ret = read(vpu_enc->vpu_fd, GST_BUFFER_DATA(outbuffer), 1024 * 1024);
	if (ret < 0) {
		printf("read failed: %s\n", strerror(errno));
		return GST_FLOW_ERROR;
	}
	GST_BUFFER_SIZE(outbuffer) = ret;
	GST_BUFFER_TIMESTAMP(outbuffer) = gst_util_uint64_scale(vpu_enc->encoded_frames,
		1 * GST_SECOND,
		vpu_enc->framerate);

	vpu_enc->encoded_frames++;

	GST_DEBUG_OBJECT(vpu_enc, "frame encoded : %lld ts = %" GST_TIME_FORMAT,
			vpu_enc->encoded_frames,
			GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(outbuffer)));

	retval = gst_pad_push(vpu_enc->srcpad, outbuffer);
	if (retval != GST_FLOW_OK) {
		GST_ERROR("Pushing Output onto the source pad failed with %d \n",
			  retval);
	}

	return retval;
}
示例#29
0
static GstFlowReturn
gst_icydemux_chain (GstPad * pad, GstBuffer * buf)
{
  GstICYDemux *icydemux;
  guint size, chunk, offset;
  GstBuffer *sub;
  GstFlowReturn ret = GST_FLOW_OK;

  icydemux = GST_ICYDEMUX (GST_PAD_PARENT (pad));

  if (G_UNLIKELY (icydemux->meta_interval < 0))
    goto not_negotiated;

  if (icydemux->meta_interval == 0) {
    ret = gst_icydemux_typefind_or_forward (icydemux, buf);
    goto done;
  }

  /* Go through the buffer, chopping it into appropriate chunks. Forward as
   * tags or buffers, as appropriate
   */
  size = GST_BUFFER_SIZE (buf);
  offset = 0;
  while (size) {
    if (icydemux->remaining) {
      chunk = (size <= icydemux->remaining) ? size : icydemux->remaining;
      sub = gst_buffer_create_sub (buf, offset, chunk);
      offset += chunk;
      icydemux->remaining -= chunk;
      size -= chunk;

      /* This buffer goes onto typefinding, and/or directly pushed out */
      ret = gst_icydemux_typefind_or_forward (icydemux, sub);
      if (ret != GST_FLOW_OK)
        goto done;
    } else if (icydemux->meta_remaining) {
      chunk = (size <= icydemux->meta_remaining) ?
          size : icydemux->meta_remaining;
      sub = gst_buffer_create_sub (buf, offset, chunk);
      gst_icydemux_add_meta (icydemux, sub);

      offset += chunk;
      icydemux->meta_remaining -= chunk;
      size -= chunk;

      if (icydemux->meta_remaining == 0) {
        /* Parse tags from meta_adapter, send off as tag messages */
        GST_DEBUG_OBJECT (icydemux, "No remaining metadata, parsing for tags");
        gst_icydemux_parse_and_send_tags (icydemux);

        icydemux->remaining = icydemux->meta_interval;
      }
    } else {
      /* We need to read a single byte (always safe at this point in the loop)
       * to figure out how many bytes of metadata exist. 
       * The 'spec' tells us to read 16 * (byte_value) bytes of metadata after
       * this (zero is common, and means the metadata hasn't changed).
       */
      icydemux->meta_remaining = 16 * GST_BUFFER_DATA (buf)[offset];
      if (icydemux->meta_remaining == 0)
        icydemux->remaining = icydemux->meta_interval;

      offset += 1;
      size -= 1;
    }
  }

done:
  gst_buffer_unref (buf);

  return ret;

  /* ERRORS */
not_negotiated:
  {
    GST_WARNING_OBJECT (icydemux, "meta_interval not set, buffer probably had "
        "no caps set. Try enabling iradio-mode on the http source element");
    gst_buffer_unref (buf);
    return GST_FLOW_NOT_NEGOTIATED;
  }
}
示例#30
0
static GstFlowReturn
gst_file_src_create_read (GstFileSrc * src, guint64 offset, guint length,
    GstBuffer ** buffer)
{
  int ret;
  GstBuffer *buf;

  if (G_UNLIKELY (src->read_position != offset)) {
    off_t res;

    res = lseek (src->fd, offset, SEEK_SET);
    if (G_UNLIKELY (res < 0 || res != offset))
      goto seek_failed;

    src->read_position = offset;
  }

  buf = gst_buffer_try_new_and_alloc (length);
  if (G_UNLIKELY (buf == NULL && length > 0)) {
    GST_ERROR_OBJECT (src, "Failed to allocate %u bytes", length);
    return GST_FLOW_ERROR;
  }

  /* No need to read anything if length is 0 */
  if (length > 0) {
    GST_LOG_OBJECT (src, "Reading %d bytes at offset 0x%" G_GINT64_MODIFIER "x",
        length, offset);
    ret = read (src->fd, GST_BUFFER_DATA (buf), length);
    if (G_UNLIKELY (ret < 0))
      goto could_not_read;

    /* seekable regular files should have given us what we expected */
    if (G_UNLIKELY ((guint) ret < length && src->seekable))
      goto unexpected_eos;

    /* other files should eos if they read 0 and more was requested */
    if (G_UNLIKELY (ret == 0 && length > 0))
      goto eos;

    length = ret;
    GST_BUFFER_SIZE (buf) = length;
    GST_BUFFER_OFFSET (buf) = offset;
    GST_BUFFER_OFFSET_END (buf) = offset + length;

    src->read_position += length;
  }

  *buffer = buf;

  return GST_FLOW_OK;

  /* ERROR */
seek_failed:
  {
    GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), GST_ERROR_SYSTEM);
    return GST_FLOW_ERROR;
  }
could_not_read:
  {
    GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), GST_ERROR_SYSTEM);
    gst_buffer_unref (buf);
    return GST_FLOW_ERROR;
  }
unexpected_eos:
  {
    GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL),
        ("unexpected end of file."));
    gst_buffer_unref (buf);
    return GST_FLOW_ERROR;
  }
eos:
  {
    GST_DEBUG ("non-regular file hits EOS");
    gst_buffer_unref (buf);
    return GST_FLOW_UNEXPECTED;
  }
}