Exemplo n.º 1
0
static gboolean
app_run (App * app, int argc, char *argv[])
{
  if (argc < 2) {
    g_message ("no bitstream file specified");
    return FALSE;
  }
  app->file_name = g_strdup (argv[1]);

  if (!g_file_test (app->file_name, G_FILE_TEST_IS_REGULAR)) {
    g_message ("failed to find file '%s'", app->file_name);
    return FALSE;
  }

  app->codec = identify_codec (app->file_name);
  if (!app->codec) {
    app->codec = identify_codec_from_string (g_codec_str);
    if (!app->codec) {
      g_message ("failed to identify codec for '%s'", app->file_name);
      return FALSE;
    }
  }

  g_print ("Simple decoder (%s bitstream)\n", string_from_codec (app->codec));

  app->display = video_output_create_display (NULL);
  if (!app->display) {
    g_message ("failed to create VA display");
    return FALSE;
  }

  app->window = video_output_create_window (app->display,
      app->window_width, app->window_height);
  if (!app->window) {
    g_message ("failed to create window");
    return FALSE;
  }

  gst_vaapi_window_show (app->window);

  if (!start_decoder (app)) {
    g_message ("failed to start decoder thread");
    return FALSE;
  }

  if (!start_renderer (app)) {
    g_message ("failed to start renderer thread");
    return FALSE;
  }

  app_check_events (app);

  stop_renderer (app);
  stop_decoder (app);

  g_print ("Decoded %u frames", app->num_frames);
  if (g_benchmark) {
    const gdouble elapsed = g_timer_elapsed (app->timer, NULL);
    g_print (" in %.2f sec (%.1f fps)\n",
        elapsed, (gdouble) app->num_frames / elapsed);
  }
  g_print ("\n");
  return TRUE;
}
GstStateChangeReturn
gst_sandboxed_decodebin_change_state (GstElement *element,
                                      GstStateChange state_change)
{
    GError *error = NULL;
    GstSandboxedDecodebinPrivate *priv;
    GstSandboxedDecodebin *self = GST_SANDBOXED_DECODEBIN (element);
    GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;

    priv = GST_SANDBOXED_DECODEBIN_GET_PRIVATE (self);

    switch (state_change) {
    case GST_STATE_CHANGE_NULL_TO_READY:
        /* TODO: set up file monitoring */
        /* spawn subprocess */
        priv->subprocess_stdin = start_decoder (priv->shm_audio_socket_path,
                                                priv->shm_video_socket_path,
                                                &error);
        if (priv->subprocess_stdin == -1) {
            GST_WARNING_OBJECT (element,
                                "Could not spawn subprocess: %s", error->message);
            ret = GST_STATE_CHANGE_FAILURE;
        }

        /* set the right fd to fdsink */
        g_object_set (priv->fdsink, "fd", priv->subprocess_stdin, NULL);
        GST_DEBUG_OBJECT (element, "Waiting for shm sockets to be available\n");
        while (!self->priv->subprocess_ready) {
            /* does that count as acceptable code? The alternatives are another
             * thread to monitor file creation or sleep() */
            g_main_context_iteration (NULL, TRUE);
        }
        GST_DEBUG_OBJECT (element, "Done waiting\n");

        break;
    case GST_STATE_CHANGE_READY_TO_PAUSED:
        GST_DEBUG_OBJECT (element, "Going to PAUSED");
        break;
#if 0
    case GST_STATE_CHANGE_READY_TO_PAUSED:
        /* TODO: check subprocess is ready with the help of file monitoring, if
         * not, do the change asynchronously */
    {
        GstMessage *message;
        ret = GST_STATE_CHANGE_ASYNC;

        message = gst_message_new_async_start (GST_OBJECT_CAST (element), FALSE);
        parent_class->handle_message (GST_BIN (element), message);

        /* Yeah, this is a hack */
        g_timeout_add (2000, do_async_done, self);
    }

    break;
#endif
    case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
        GST_DEBUG_OBJECT (element, "Going to PLAYING");
        break;
    default:
        break;
    }
    if (ret != GST_STATE_CHANGE_FAILURE) {
        GstStateChangeReturn bret;
        bret = GST_ELEMENT_CLASS (parent_class)->change_state (element, state_change);
        if (bret == GST_STATE_CHANGE_FAILURE) {
            GST_WARNING_OBJECT (element, "parent change_state failed!");
            ret = bret;
        }
    }

    if (ret != GST_STATE_CHANGE_FAILURE) {
        GstStateChangeReturn fdret;
        gint fd;
        switch (state_change) {
        case GST_STATE_CHANGE_READY_TO_PAUSED:
            GST_DEBUG_OBJECT (element, "Trying to set fdsink to PLAYING");
            fdret = gst_element_set_state (priv->fdsink, GST_STATE_PLAYING);
            GST_DEBUG_OBJECT (element, "Returned: %s",
                              gst_element_state_change_return_get_name (fdret));
            break;
        case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
            g_object_get (priv->audiosrc,
                          "shm-area-name", &priv->audio_shm_area_name, NULL);
            g_object_get (priv->videosrc,
                          "shm-area-name", &priv->video_shm_area_name, NULL);
            GST_DEBUG_OBJECT (element, "Name of audio/video shm areas: "
                              "\"%s\" and \"%s\"\n",
                              priv->audio_shm_area_name,
                              priv->video_shm_area_name);
            break;
        case GST_STATE_CHANGE_READY_TO_NULL:
            /* Closing the fd sounds like a polite thing to do now*/
            g_object_get (priv->fdsink, "fd", &fd, NULL);
            close (fd);

            /* Unlinking the stuff the decoder could not unlink because it doesn't
             * have the necessary privileges */
            GST_DEBUG_OBJECT (element, "Trying to unlink %s and %s",
                              priv->shm_video_socket_path,
                              priv->shm_audio_socket_path);
            if (-1 == g_unlink (priv->shm_video_socket_path))
                GST_WARNING_OBJECT (element, "Could not unlink %s: %m", priv->shm_video_socket_path);
            if (-1 == g_unlink (priv->shm_audio_socket_path))
                GST_WARNING_OBJECT (element, "Could not unlink %s: %m", priv->shm_audio_socket_path);

            GST_DEBUG_OBJECT (element,
                              "Trying to unlink audio/video shm areas: \"%s\" and \"%s\"\n",
                              priv->audio_shm_area_name,
                              priv->video_shm_area_name);
            if (-1 == shm_unlink (priv->audio_shm_area_name))
                GST_WARNING_OBJECT (element, "Could not unlink shm area %s: %m",
                                    priv->audio_shm_area_name);
            if (-1 == shm_unlink (priv->video_shm_area_name))
                GST_WARNING_OBJECT (element, "Could not unlink shm area %s: %m",
                                    priv->video_shm_area_name);
            /* FIXME: where do we free all these strings? */
            break;
        default:
            break;
        }
    }

    return ret;
}