예제 #1
0
gboolean
decoder_put_buffers (GstVaapiDecoder * decoder)
{
  const CodecDefs *codec;
  VideoDecodeInfo info;
  GstBuffer *buffer;
  gboolean success;

  g_return_val_if_fail (decoder != NULL, FALSE);

  codec = get_codec_defs (decoder);
  g_return_val_if_fail (codec != NULL, FALSE);

  codec->get_video_info (&info);
  buffer = gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY,
      (guchar *) info.data, info.data_size, 0, info.data_size, NULL, NULL);
  if (!buffer) {
    GST_ERROR ("failed to create encoded data buffer");
    return FALSE;
  }

  success = gst_vaapi_decoder_put_buffer (decoder, buffer);
  gst_buffer_unref (buffer);
  if (!success) {
    GST_ERROR ("failed to send video data to the decoder");
    return FALSE;
  }

  if (!gst_vaapi_decoder_put_buffer (decoder, NULL)) {
    GST_ERROR ("failed to submit <end-of-stream> to the decoder");
    return FALSE;
  }
  return TRUE;
}
예제 #2
0
static void
gst_vaapidecode_destroy(GstVaapiDecode *decode)
{
    if (decode->decoder) {
        gst_vaapi_decoder_put_buffer(decode->decoder, NULL);
        g_object_unref(decode->decoder);
        decode->decoder = NULL;
    }

    if (decode->decoder_caps) {
        gst_caps_unref(decode->decoder_caps);
        decode->decoder_caps = NULL;
    }

    if (decode->decoder_ready) {
        gst_vaapidecode_release(decode, NULL);
        g_cond_free(decode->decoder_ready);
        decode->decoder_ready = NULL;
    }

    if (decode->decoder_mutex) {
        g_mutex_free(decode->decoder_mutex);
        decode->decoder_mutex = NULL;
    }
}
예제 #3
0
static GstFlowReturn
gst_vaapidecode_chain(GstPad *pad, GstBuffer *buf)
{
    GstVaapiDecode * const decode = GST_VAAPIDECODE(GST_OBJECT_PARENT(pad));

    if (!gst_vaapi_decoder_put_buffer(decode->decoder, buf))
        goto error_push_buffer;

    gst_buffer_unref(buf);
    return gst_vaapidecode_step(decode);

    /* ERRORS */
error_push_buffer:
    {
        GST_DEBUG("failed to push input buffer to decoder");
        gst_buffer_unref(buf);
        return GST_FLOW_UNEXPECTED;
    }
}
예제 #4
0
static gpointer
decoder_thread (gpointer data)
{
  App *const app = data;
  GError *error = NULL;
  GstVaapiDecoderStatus status;
  GstVaapiSurfaceProxy *proxy;
  RenderFrame *rfp;
  GstBuffer *buffer;
  GstClockTime pts;
  gboolean got_surface, got_eos = FALSE;
  gint64 end_time;
  guint ofs;

  g_print ("Decoder thread started\n");

#define SEND_ERROR(...)                                                 \
    do {                                                                \
        error = g_error_new(APP_ERROR, APP_ERROR_DECODER, __VA_ARGS__); \
        goto send_error;                                                \
    } while (0)

  pts = g_get_monotonic_time ();
  ofs = 0;
  while (!app->decoder_thread_cancel) {
    if (G_UNLIKELY (ofs == app->file_size))
      buffer = NULL;
    else {
      const gsize size = MIN (4096, app->file_size - ofs);
      buffer = gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY,
          app->file_data, app->file_size, ofs, size, NULL, NULL);
      if (!buffer)
        SEND_ERROR ("failed to allocate new buffer");
      ofs += size;
    }
    if (!gst_vaapi_decoder_put_buffer (app->decoder, buffer))
      SEND_ERROR ("failed to push buffer to decoder");
    gst_buffer_replace (&buffer, NULL);

  get_surface:
    status = gst_vaapi_decoder_get_surface (app->decoder, &proxy);
    switch (status) {
      case GST_VAAPI_DECODER_STATUS_SUCCESS:
        gst_vaapi_surface_proxy_set_destroy_notify (proxy,
            (GDestroyNotify) decoder_release, app);
        rfp = render_frame_new ();
        if (!rfp)
          SEND_ERROR ("failed to allocate render frame");
        rfp->proxy = proxy;
        rfp->pts = pts;
        rfp->duration = app->frame_duration;
        pts += app->frame_duration;
        g_async_queue_push (app->decoder_queue, rfp);
        break;
      case GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA:
        /* nothing to do, just continue to the next iteration */
        break;
      case GST_VAAPI_DECODER_STATUS_END_OF_STREAM:
        gst_vaapi_decoder_flush (app->decoder);
        if (got_eos)
          goto send_eos;
        got_eos = TRUE;
        break;
      case GST_VAAPI_DECODER_STATUS_ERROR_NO_SURFACE:
        end_time = g_get_monotonic_time () + G_TIME_SPAN_SECOND;
        g_mutex_lock (&app->mutex);
        got_surface = g_cond_wait_until (&app->decoder_ready, &app->mutex,
            end_time);
        g_mutex_unlock (&app->mutex);
        if (got_surface)
          goto get_surface;
        SEND_ERROR ("failed to acquire a surface within one second");
        break;
      default:
        SEND_ERROR ("%s", get_decoder_status_string (status));
        break;
    }
  }
  return NULL;

#undef SEND_ERROR

send_eos:
  app_send_eos (app);
  return NULL;

send_error:
  app_send_error (app, error);
  return NULL;
}