Exemplo n.º 1
0
static GstFlowReturn
gst_kate_enc_flush_waiting (GstKateEnc * ke, GstClockTime now)
{
  GstFlowReturn rflow = GST_FLOW_OK;
  if (ke->delayed_spu) {
    int ret;
    kate_packet kp;
    GstClockTime keepalive_time;

    kate_float t0 = ke->delayed_start / (double) GST_SECOND;
    kate_float t1 = now / (double) GST_SECOND;

    GST_INFO_OBJECT (ke,
        "We had a delayed SPU packet starting at %f, flushing at %f (assumed duration %f)",
        t0, t1, t1 - t0);

    ret = kate_encode_text (&ke->k, t0, t1, "", 0, &kp);
    if (G_UNLIKELY (ret < 0)) {
      GST_ELEMENT_ERROR (ke, STREAM, ENCODE, (NULL),
          ("kate_encode_text: %d", ret));
      rflow = GST_FLOW_ERROR;
    } else {
      rflow =
          gst_kate_enc_chain_push_packet (ke, &kp, ke->delayed_start,
          now - ke->delayed_start + 1);
    }

    if (rflow == GST_FLOW_OK) {
      GST_DEBUG_OBJECT (ke, "delayed SPU packet flushed");
    } else {
      GST_WARNING_OBJECT (ke, "Failed to flush delayed SPU packet: %d", rflow);
    }

    /* forget it even if we couldn't flush it */
    ke->delayed_spu = FALSE;

    /* free the delayed data */
    g_free (ke->delayed_bitmap->pixels);
    g_free (ke->delayed_bitmap);
    ke->delayed_bitmap = NULL;
    g_free (ke->delayed_palette->colors);
    g_free (ke->delayed_palette);
    ke->delayed_palette = NULL;
    g_free (ke->delayed_region);
    ke->delayed_region = NULL;

    /* now that we've flushed the packet, we want to insert keepalives as requested */
    if (ke->keepalive_min_time > 0.0f && t1 > t0) {
      GST_INFO_OBJECT (ke, "generating keepalives at %f from %f to %f",
          ke->keepalive_min_time, t0, t1);
      for (keepalive_time = ke->delayed_start;
          (keepalive_time += ke->keepalive_min_time * GST_SECOND) < now;) {
        GST_INFO_OBJECT (ke, "generating keepalive at %f",
            keepalive_time / (double) GST_SECOND);
        gst_kate_enc_generate_keepalive (ke, keepalive_time);
      }
    }
  }
  return rflow;
}
Exemplo n.º 2
0
static GstFlowReturn
gst_kate_enc_chain_text (GstKateEnc * ke, GstBuffer * buf)
{
  kate_packet kp = { 0 };
  int ret = 0;
  GstFlowReturn rflow;
  GstClockTime start = GST_BUFFER_TIMESTAMP (buf);
  GstClockTime stop = GST_BUFFER_TIMESTAMP (buf) + GST_BUFFER_DURATION (buf);

  if (ke->format == GST_KATE_FORMAT_TEXT_PANGO_MARKUP) {
    ret = kate_encode_set_markup_type (&ke->k, kate_markup_simple);
  } else if (ke->format == GST_KATE_FORMAT_TEXT_UTF8) {
    ret = kate_encode_set_markup_type (&ke->k, kate_markup_none);
  } else {
    return GST_FLOW_ERROR;
  }

  if (G_UNLIKELY (ret < 0)) {
    GST_ELEMENT_ERROR (ke, STREAM, ENCODE, (NULL),
        ("Failed to set markup type: %s",
            gst_kate_util_get_error_message (ret)));
    rflow = GST_FLOW_ERROR;
  } else {
    GstMapInfo info;
    gboolean need_unmap = TRUE;
    kate_float t0 = start / (double) GST_SECOND;
    kate_float t1 = stop / (double) GST_SECOND;

    if (!gst_buffer_map (buf, &info, GST_MAP_READ)) {
      info.data = NULL;
      info.size = 0;
      need_unmap = FALSE;
      GST_WARNING_OBJECT (buf, "Failed to map buffer");
    }

    GST_LOG_OBJECT (ke, "Encoding text: %*.*s (%u bytes) from %f to %f",
        (int) info.size, (int) info.size, info.data, (int) info.size, t0, t1);
    ret = kate_encode_text (&ke->k, t0, t1, (const char *) info.data, info.size,
        &kp);
    if (G_UNLIKELY (ret < 0)) {
      GST_ELEMENT_ERROR (ke, STREAM, ENCODE, (NULL),
          ("Failed to encode text: %s", gst_kate_util_get_error_message (ret)));
      rflow = GST_FLOW_ERROR;
    } else {
      rflow = gst_kate_enc_chain_push_packet (ke, &kp, start, stop - start + 1);
    }
    if (need_unmap)
      gst_buffer_unmap (buf, &info);
  }

  return rflow;
}
Exemplo n.º 3
0
static GstFlowReturn
gst_kate_enc_chain_text (GstKateEnc * ke, GstBuffer * buf,
    const char *mime_type)
{
  kate_packet kp;
  int ret = 0;
  GstFlowReturn rflow;
  GstClockTime start = GST_BUFFER_TIMESTAMP (buf);
  GstClockTime stop = GST_BUFFER_TIMESTAMP (buf) + GST_BUFFER_DURATION (buf);

  if (!strcmp (mime_type, "text/x-pango-markup")) {
    ret = kate_encode_set_markup_type (&ke->k, kate_markup_simple);
  } else {
    ret = kate_encode_set_markup_type (&ke->k, kate_markup_none);
  }

  if (G_UNLIKELY (ret < 0)) {
    GST_ELEMENT_ERROR (ke, STREAM, ENCODE, (NULL),
        ("kate_encode_set_markup_type: %d", ret));
    rflow = GST_FLOW_ERROR;
  } else {
    const char *text = (const char *) GST_BUFFER_DATA (buf);
    if (text) {
      size_t text_len = GST_BUFFER_SIZE (buf);
      kate_float t0 = start / (double) GST_SECOND;
      kate_float t1 = stop / (double) GST_SECOND;
      GST_LOG_OBJECT (ke, "Encoding text: %*.*s (%u bytes) from %f to %f",
          (int) text_len, (int) text_len, GST_BUFFER_DATA (buf),
          GST_BUFFER_SIZE (buf), t0, t1);
      ret = kate_encode_text (&ke->k, t0, t1, text, text_len, &kp);
      if (G_UNLIKELY (ret < 0)) {
        GST_ELEMENT_ERROR (ke, STREAM, ENCODE, (NULL),
            ("Failed to encode text: %d", ret));
        rflow = GST_FLOW_ERROR;
      } else {
        rflow =
            gst_kate_enc_chain_push_packet (ke, &kp, start, stop - start + 1);
      }
    } else {
      /* FIXME: this should not be an error, we should ignore it and move on */
      GST_ELEMENT_ERROR (ke, STREAM, ENCODE, (NULL),
          ("no text in text packet"));
      rflow = GST_FLOW_ERROR;
    }
  }

  return rflow;
}
Exemplo n.º 4
0
static GstFlowReturn
gst_kate_enc_chain_spu (GstKateEnc * ke, GstBuffer * buf)
{
  kate_packet kp;
  kate_region *kregion;
  kate_bitmap *kbitmap;
  kate_palette *kpalette;
  GstFlowReturn rflow;
  int ret = 0;
  GstClockTime start, stop;
  kate_float t0, t1;

  /* allocate region, bitmap, and palette, in case we have to delay encoding them */
  kregion = (kate_region *) g_malloc (sizeof (kate_region));
  kbitmap = (kate_bitmap *) g_malloc (sizeof (kate_bitmap));
  kpalette = (kate_palette *) g_malloc (sizeof (kate_palette));
  if (!kregion || !kpalette || !kbitmap) {
    g_free (kregion);
    g_free (kbitmap);
    g_free (kpalette);
    GST_ELEMENT_ERROR (ke, STREAM, ENCODE, (NULL), ("Out of memory"));
    return GST_FLOW_ERROR;
  }

  rflow = gst_kate_spu_decode_spu (ke, buf, kregion, kbitmap, kpalette);
  if (G_UNLIKELY (rflow != GST_FLOW_OK)) {
    GST_ERROR_OBJECT (ke, "Failed to decode incoming SPU");
#if 0
    {
      static int spu_count = 0;
      FILE *f;
      char name[32];
      snprintf (name, sizeof (name), "/tmp/bad_spu_%04d", spu_count++);
      name[sizeof (name) - 1] = 0;
      f = fopen (name, "w");
      if (f) {
        fwrite (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf), 1, f);
        fclose (f);
      }
    }
#endif
    goto beach;
  }

  if (G_UNLIKELY (kbitmap->width == 0 || kbitmap->height == 0)) {
    /* there are some DVDs (well, at least one) where some dimwits put in a wholly transparent full screen 720x576 SPU !!!!?! */
    GST_WARNING_OBJECT (ke, "SPU is totally invisible - dimwits");
    rflow = GST_FLOW_OK;
    goto beach;
  }

  /* timestamp offsets are hidden in the SPU packets */
  start = GST_BUFFER_TIMESTAMP (buf) + GST_KATE_STM_TO_GST (ke->show_time);
  stop = GST_BUFFER_TIMESTAMP (buf) + GST_KATE_STM_TO_GST (ke->hide_time);
  t0 = start / (double) GST_SECOND;
  t1 = stop / (double) GST_SECOND;
  GST_DEBUG_OBJECT (ke, "buf ts %f, start/show %hu/%hu",
      GST_BUFFER_TIMESTAMP (buf) / (double) GST_SECOND, ke->show_time,
      ke->hide_time);

#if 0
  {
    static int spu_count = 0;
    FILE *f;
    char name[32];
    snprintf (name, sizeof (name), "/tmp/spu_%04d", spu_count++);
    name[sizeof (name) - 1] = 0;
    f = fopen (name, "w");
    if (f) {
      fwrite (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf), 1, f);
      fclose (f);
    }
  }
#endif
  GST_DEBUG_OBJECT (ke, "Encoding %" G_GSIZE_FORMAT "x%" G_GSIZE_FORMAT
      " SPU: (%" G_GSIZE_FORMAT " bytes) from %f to %f",
      kbitmap->width, kbitmap->height, gst_buffer_get_size (buf), t0, t1);

  ret = kate_encode_set_region (&ke->k, kregion);
  if (G_UNLIKELY (ret < 0)) {
    GST_ELEMENT_ERROR (ke, STREAM, ENCODE, (NULL),
        ("Failed to set region: %s", gst_kate_util_get_error_message (ret)));
    goto error_return;
  }

  ret = kate_encode_set_palette (&ke->k, kpalette);
  if (G_UNLIKELY (ret < 0)) {
    GST_ELEMENT_ERROR (ke, STREAM, ENCODE, (NULL),
        ("Failed to set palette: %s", gst_kate_util_get_error_message (ret)));
    goto error_return;
  }

  ret = kate_encode_set_bitmap (&ke->k, kbitmap);
  if (G_UNLIKELY (ret < 0)) {
    GST_ELEMENT_ERROR (ke, STREAM, ENCODE, (NULL),
        ("Failed to set bitmap: %s", gst_kate_util_get_error_message (ret)));
    goto error_return;
  }

  /* Some SPUs have no hide time - so I'm going to delay the encoding of the packet
     till either a suitable event happens, and the time of this event will be used
     as the end time of this SPU, which will then be encoded and sent off. Suitable
     events are the arrival of a subsequent SPU (eg, this SPU will replace the one
     with no end), EOS, a new segment event, or a time threshold being reached */
  if (ke->hide_time <= ke->show_time) {
    GST_INFO_OBJECT (ke,
        "Cannot encode SPU packet now, hide time is now known (starting at %f) - delaying",
        t0);
    ke->delayed_spu = TRUE;
    ke->delayed_start = start;
    ke->delayed_bitmap = kbitmap;
    ke->delayed_palette = kpalette;
    ke->delayed_region = kregion;
    rflow = GST_FLOW_OK;
    goto beach;
  }

  ret = kate_encode_text (&ke->k, t0, t1, "", 0, &kp);
  if (G_UNLIKELY (ret < 0)) {
    GST_ELEMENT_ERROR (ke, STREAM, ENCODE, (NULL),
        ("Failed to encode empty text for SPU buffer: %s",
            gst_kate_util_get_error_message (ret)));
    goto error_return;
  }

  rflow = gst_kate_enc_chain_push_packet (ke, &kp, start, stop - start + 1);

beach:
  /* Cleanup data if we're not keeping it around */
  if (!ke->delayed_spu) {
    g_free (kpalette->colors);
    g_free (kpalette);
    g_free (kbitmap->pixels);
    g_free (kbitmap);
    g_free (kregion);
  }

  return rflow;

error_return:
  {
    rflow = GST_FLOW_ERROR;
    goto beach;
  }
}