예제 #1
0
void
gst_scene_change_finalize (GObject * object)
{
  GstSceneChange *scenechange;

  g_return_if_fail (GST_IS_SCENE_CHANGE (object));
  scenechange = GST_SCENE_CHANGE (object);

  if (scenechange->oldbuf)
    gst_buffer_unref (scenechange->oldbuf);

  G_OBJECT_CLASS (parent_class)->finalize (object);
}
예제 #2
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;
}
예제 #3
0
static GstFlowReturn
gst_scene_change_transform_frame_ip (GstVideoFilter * filter,
    GstVideoFrame * frame)
{
  GstSceneChange *scenechange = GST_SCENE_CHANGE (filter);
  GstVideoFrame oldframe;
  double score_min;
  double score_max;
  double threshold;
  double score;
  gboolean change;
  gboolean ret;
  int i;

  GST_DEBUG_OBJECT (scenechange, "transform_frame_ip");

  if (!scenechange->oldbuf) {
    scenechange->n_diffs = 0;
    memset (scenechange->diffs, 0, sizeof (double) * SC_N_DIFFS);
    scenechange->oldbuf = gst_buffer_ref (frame->buffer);
    memcpy (&scenechange->oldinfo, &frame->info, sizeof (GstVideoInfo));
    return GST_FLOW_OK;
  }

  ret =
      gst_video_frame_map (&oldframe, &scenechange->oldinfo,
      scenechange->oldbuf, GST_MAP_READ);
  if (!ret) {
    GST_ERROR_OBJECT (scenechange, "failed to map old video frame");
    return GST_FLOW_ERROR;
  }

  score = get_frame_score (&oldframe, frame);

  gst_video_frame_unmap (&oldframe);

  gst_buffer_unref (scenechange->oldbuf);
  scenechange->oldbuf = gst_buffer_ref (frame->buffer);
  memcpy (&scenechange->oldinfo, &frame->info, sizeof (GstVideoInfo));

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

  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_INFO_OBJECT (scenechange, "%d %g %g %g %d",
        scenechange->n_diffs, score / threshold, score, threshold, change);

    event =
        gst_video_event_new_downstream_force_key_unit (GST_BUFFER_PTS
        (frame->buffer), GST_CLOCK_TIME_NONE, GST_CLOCK_TIME_NONE, FALSE,
        scenechange->count++);

    gst_pad_push_event (GST_BASE_TRANSFORM_SRC_PAD (scenechange), event);
  }

  return GST_FLOW_OK;
}