Exemple #1
0
static void
gst_my_typefind_function (GstTypeFind * tf, gpointer d)
{
  GstPnmInfoMngrResult r = GST_PNM_INFO_MNGR_RESULT_READING;
  GstPnmInfoMngr mngr = { 0, };
  guint i;
  guint8 *data = NULL;

  for (i = 0; r == GST_PNM_INFO_MNGR_RESULT_READING; i++) {
    data = gst_type_find_peek (tf, i, 1);
    if (!data)
      break;
    r = gst_pnm_info_mngr_scan (&mngr, data, 1);
  }
  switch (r) {
    case GST_PNM_INFO_MNGR_RESULT_READING:
    case GST_PNM_INFO_MNGR_RESULT_FAILED:
      return;
    case GST_PNM_INFO_MNGR_RESULT_FINISHED:
      switch (mngr.info.type) {
        case GST_PNM_TYPE_BITMAP_ASCII:
        case GST_PNM_TYPE_BITMAP_RAW:
          gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, BITMAP_CAPS);
          return;
        case GST_PNM_TYPE_GRAYMAP_ASCII:
        case GST_PNM_TYPE_GRAYMAP_RAW:
          gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, GRAYMAP_CAPS);
          return;
        case GST_PNM_TYPE_PIXMAP_ASCII:
        case GST_PNM_TYPE_PIXMAP_RAW:
          gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, PIXMAP_CAPS);
          return;
      }
  }
}
Exemple #2
0
GstPnmInfoMngrResult
gst_pnm_info_mngr_scan (GstPnmInfoMngr * mngr, const guint8 * buf,
    guint buf_len)
{
  guint i = 0;

  g_return_val_if_fail (mngr != NULL, GST_PNM_INFO_MNGR_RESULT_FAILED);
  g_return_val_if_fail (buf || !buf_len, GST_PNM_INFO_MNGR_RESULT_FAILED);

  if (!buf_len)
    return (mngr->info.fields ==
        GST_PNM_INFO_FIELDS_ALL) ? GST_PNM_INFO_MNGR_RESULT_FINISHED :
        GST_PNM_INFO_MNGR_RESULT_READING;

  switch (mngr->state) {
    case GST_PNM_INFO_MNGR_STATE_COMMENT:
      for (i = 0; (i < buf_len) && (buf[i] != '\n'); i++);
      if (i == buf_len)
        return GST_PNM_INFO_MNGR_RESULT_READING;
      mngr->state = GST_PNM_INFO_MNGR_STATE_NONE;
      mngr->data_offset += i;
      return gst_pnm_info_mngr_scan (mngr, buf + i, buf_len - i);
    case GST_PNM_INFO_MNGR_STATE_WHITE_SPACE:
      for (i = 0; (i < buf_len) && ((buf[i] == ' ') || (buf[i] == '\t')
              || (buf[i] == '\n')); i++);
      if (i == buf_len)
        return GST_PNM_INFO_MNGR_RESULT_READING;
      mngr->state = GST_PNM_INFO_MNGR_STATE_NONE;
      mngr->data_offset += i;
      return gst_pnm_info_mngr_scan (mngr, buf + i, buf_len - i);
    case GST_PNM_INFO_MNGR_STATE_NONE:
      switch (buf[i++]) {
        case '#':
          mngr->state = GST_PNM_INFO_MNGR_STATE_COMMENT;
          mngr->data_offset += i;
          return gst_pnm_info_mngr_scan (mngr, buf + i, buf_len - i);
        case ' ':
        case '\t':
        case '\n':
          mngr->state = GST_PNM_INFO_MNGR_STATE_WHITE_SPACE;
          mngr->data_offset += i;
          return gst_pnm_info_mngr_scan (mngr, buf + i, buf_len - i);
        case 'P':
          if (mngr->info.fields & GST_PNM_INFO_FIELDS_TYPE)
            return GST_PNM_INFO_MNGR_RESULT_FAILED;
          mngr->state = GST_PNM_INFO_MNGR_STATE_DATA_TYPE;
          mngr->data_offset += i;
          return gst_pnm_info_mngr_scan (mngr, buf + i, buf_len - i);
        case '0':
        case '1':
        case '2':
        case '3':
        case '4':
        case '5':
        case '6':
        case '7':
        case '8':
        case '9':
          if (mngr->info.fields & GST_PNM_INFO_FIELDS_MAX)
            return GST_PNM_INFO_MNGR_RESULT_FINISHED;
          if (mngr->info.fields & GST_PNM_INFO_FIELDS_HEIGHT) {
            mngr->state = GST_PNM_INFO_MNGR_STATE_DATA_MAX;
            return gst_pnm_info_mngr_scan (mngr, buf, buf_len);
          }
          if (mngr->info.fields & GST_PNM_INFO_FIELDS_WIDTH) {
            mngr->state = GST_PNM_INFO_MNGR_STATE_DATA_HEIGHT;
            return gst_pnm_info_mngr_scan (mngr, buf, buf_len);
          }
          mngr->state = GST_PNM_INFO_MNGR_STATE_DATA_WIDTH;
          return gst_pnm_info_mngr_scan (mngr, buf, buf_len);
        default:
          return GST_PNM_INFO_MNGR_RESULT_FAILED;
      }
    case GST_PNM_INFO_MNGR_STATE_DATA_TYPE:
      switch (buf[i++]) {
        case '1':
          mngr->info.type = GST_PNM_TYPE_BITMAP;
          mngr->info.encoding = GST_PNM_ENCODING_ASCII;
          break;
        case '2':
          mngr->info.type = GST_PNM_TYPE_GRAYMAP;
          mngr->info.encoding = GST_PNM_ENCODING_ASCII;
          break;
        case '3':
          mngr->info.type = GST_PNM_TYPE_PIXMAP;
          mngr->info.encoding = GST_PNM_ENCODING_ASCII;
          break;
        case '4':
          mngr->info.type = GST_PNM_TYPE_BITMAP;
          mngr->info.encoding = GST_PNM_ENCODING_RAW;
          break;
        case '5':
          mngr->info.type = GST_PNM_TYPE_GRAYMAP;
          mngr->info.encoding = GST_PNM_ENCODING_RAW;
          break;
        case '6':
          mngr->info.type = GST_PNM_TYPE_PIXMAP;
          mngr->info.encoding = GST_PNM_ENCODING_RAW;
          break;
        default:
          return GST_PNM_INFO_MNGR_RESULT_FAILED;
      }
      mngr->info.fields |=
          GST_PNM_INFO_FIELDS_TYPE | GST_PNM_INFO_FIELDS_ENCODING;
      mngr->state = GST_PNM_INFO_MNGR_STATE_WHITE_SPACE;
      if (i == buf_len)
        return GST_PNM_INFO_MNGR_RESULT_READING;
      mngr->info.width = mngr->info.height = mngr->info.max = 0;
      mngr->data_offset += i;
      return gst_pnm_info_mngr_scan (mngr, buf + i, buf_len - i);
    case GST_PNM_INFO_MNGR_STATE_DATA_WIDTH:
      if ((buf[i] < '0') || (buf[i] > '9')) {
        switch (buf[i]) {
          case '\n':
          case '\t':
          case ' ':
            mngr->info.fields |= GST_PNM_INFO_FIELDS_WIDTH;
            mngr->state = GST_PNM_INFO_MNGR_STATE_WHITE_SPACE;
            mngr->data_offset += i;
            return gst_pnm_info_mngr_scan (mngr, buf + i, buf_len - i);
          default:
            return GST_PNM_INFO_MNGR_RESULT_FAILED;
        }
      }
      mngr->info.width *= 10;
      mngr->info.width += buf[i++] - 0x030;
      mngr->data_offset += i;
      return gst_pnm_info_mngr_scan (mngr, buf + i, buf_len - i);
    case GST_PNM_INFO_MNGR_STATE_DATA_HEIGHT:
      if ((buf[i] < '0') || (buf[i] > '9')) {
        switch (buf[i]) {
          case '\n':
          case '\t':
          case ' ':
            mngr->info.fields |= GST_PNM_INFO_FIELDS_HEIGHT;
            mngr->state = GST_PNM_INFO_MNGR_STATE_WHITE_SPACE;
            mngr->data_offset += i;
            if (mngr->info.type == GST_PNM_TYPE_BITMAP) {
              mngr->data_offset += 1;
              mngr->info.fields |= GST_PNM_INFO_FIELDS_MAX;
              return GST_PNM_INFO_MNGR_RESULT_FINISHED;
            }
            return gst_pnm_info_mngr_scan (mngr, buf + i, buf_len - i);
          default:
            return GST_PNM_INFO_MNGR_RESULT_FAILED;
        }
      }
      mngr->info.height *= 10;
      mngr->info.height += buf[i++] - 0x030;
      mngr->data_offset += i;
      return gst_pnm_info_mngr_scan (mngr, buf + i, buf_len - i);
    case GST_PNM_INFO_MNGR_STATE_DATA_MAX:
      if ((buf[i] < '0') || (buf[i] > '9')) {
        switch (buf[i]) {
          case '\n':
          case '\t':
          case ' ':
            /* Check for maximum and minimum supported bit depth and
               return error if its out of range */
            if (mngr->info.type == GST_PNM_TYPE_GRAYMAP) {
              if ((mngr->info.max > 65535) || (mngr->info.max < 1)) {
                return GST_PNM_INFO_MNGR_RESULT_FAILED;
              }
            } else if ((mngr->info.max > 255) || (mngr->info.max < 1)) {
              return GST_PNM_INFO_MNGR_RESULT_FAILED;
            }
            mngr->info.fields |= GST_PNM_INFO_FIELDS_MAX;
            mngr->data_offset += i + 1;
            return GST_PNM_INFO_MNGR_RESULT_FINISHED;
          default:
            return GST_PNM_INFO_MNGR_RESULT_FAILED;
        }
      }
      mngr->info.max *= 10;
      mngr->info.max += buf[i++] - 0x030;
      mngr->data_offset += i;
      return gst_pnm_info_mngr_scan (mngr, buf + i, buf_len - i);
  }
  return GST_PNM_INFO_MNGR_RESULT_FAILED;
}
Exemple #3
0
static GstFlowReturn
gst_pnmdec_chain (GstPad * pad, GstBuffer * data)
{
  GstPnmdec *s = GST_PNMDEC (gst_pad_get_parent (pad));
  GstPad *src = gst_element_get_static_pad (GST_ELEMENT (s), "src");
  GstBuffer *buf;
  GstCaps *caps = NULL;
  GstFlowReturn r = GST_FLOW_OK;
  guint8 offset = 0;

  if (!(s->mngr.info.fields & GST_PNM_INFO_FIELDS_ALL)) {
    switch (gst_pnm_info_mngr_scan (&s->mngr, GST_BUFFER_DATA (data),
            GST_BUFFER_SIZE (data))) {
      case GST_PNM_INFO_MNGR_RESULT_FAILED:
        gst_buffer_unref (data);
        r = GST_FLOW_ERROR;
        goto out;
      case GST_PNM_INFO_MNGR_RESULT_READING:
        gst_buffer_unref (data);
        r = GST_FLOW_OK;
        goto out;
      case GST_PNM_INFO_MNGR_RESULT_FINISHED:
        offset = s->mngr.data_offset;
        caps = gst_caps_copy (gst_pad_get_pad_template_caps (src));
        switch (s->mngr.info.type) {
          case GST_PNM_TYPE_BITMAP_RAW:
          case GST_PNM_TYPE_BITMAP_ASCII:
          case GST_PNM_TYPE_GRAYMAP_RAW:
          case GST_PNM_TYPE_GRAYMAP_ASCII:
            gst_caps_remove_structure (caps, 0);
            s->size = s->mngr.info.width * s->mngr.info.height * 1;
            break;
          case GST_PNM_TYPE_PIXMAP_RAW:
          case GST_PNM_TYPE_PIXMAP_ASCII:
            gst_caps_remove_structure (caps, 1);
            s->size = s->mngr.info.width * s->mngr.info.height * 3;
            break;
        }
        gst_caps_set_simple (caps,
            "width", G_TYPE_INT, s->mngr.info.width,
            "height", G_TYPE_INT, s->mngr.info.height, "framerate",
            GST_TYPE_FRACTION, 0, 1, NULL);
        if (!gst_pad_set_caps (src, caps)) {
          gst_caps_unref (caps);
          r = GST_FLOW_ERROR;
          goto out;
        }
        gst_caps_unref (caps);
    }
  }

  if (offset == GST_BUFFER_SIZE (data)) {
    r = GST_FLOW_OK;
    goto out;
  }

  /* If we got the whole image, just push the buffer. */
  if (GST_BUFFER_SIZE (data) - offset == s->size) {
    buf = gst_buffer_create_sub (data, offset, s->size);
    gst_buffer_unref (data);
    memset (&s->mngr, 0, sizeof (GstPnmInfoMngr));
    s->size = 0;
    gst_buffer_set_caps (buf, GST_PAD_CAPS (src));
    r = gst_pnmdec_push (s, src, buf);
    goto out;
  }

  /* We didn't get the whole image. */
  if (!s->buf) {
    s->buf = gst_buffer_create_sub (data, offset,
        GST_BUFFER_SIZE (data) - offset);
  } else {
    buf = gst_buffer_span (s->buf, 0, data,
        GST_BUFFER_SIZE (s->buf) + GST_BUFFER_SIZE (data) - offset);
    gst_buffer_unref (s->buf);
    s->buf = buf;
  }
  if (!s->buf) {
    r = GST_FLOW_ERROR;
    goto out;
  }

  /* Do we now have the full image? If yes, push. */
  if (GST_BUFFER_SIZE (s->buf) == s->size) {
    gst_buffer_set_caps (s->buf, GST_PAD_CAPS (src));
    r = gst_pnmdec_push (s, src, s->buf);
    s->buf = NULL;
    memset (&s->mngr, 0, sizeof (GstPnmInfoMngr));
    s->size = 0;
  }

out:
  gst_object_unref (src);
  gst_object_unref (s);

  return r;
}
Exemple #4
0
static GstFlowReturn
gst_pnmdec_parse (GstVideoDecoder * decoder, GstVideoCodecFrame * frame,
    GstAdapter * adapter, gboolean at_eos)
{
  gsize size;
  GstPnmdec *s = GST_PNMDEC (decoder);
  GstFlowReturn r = GST_FLOW_OK;
  guint offset = 0;
  GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
  const guint8 *raw_data;
  GstVideoCodecState *output_state;

  GST_VIDEO_CODEC_FRAME_SET_SYNC_POINT (frame);

  size = gst_adapter_available (adapter);
  if (size < 8) {
    goto need_more_data;
  }
  raw_data = gst_adapter_map (adapter, size);

  if (s->mngr.info.fields != GST_PNM_INFO_FIELDS_ALL) {
    GstPnmInfoMngrResult res;

    res = gst_pnm_info_mngr_scan (&s->mngr, raw_data, size);

    switch (res) {
      case GST_PNM_INFO_MNGR_RESULT_FAILED:
        r = GST_FLOW_ERROR;
        goto out;
      case GST_PNM_INFO_MNGR_RESULT_READING:
        r = GST_FLOW_OK;
        goto out;
      case GST_PNM_INFO_MNGR_RESULT_FINISHED:
        switch (s->mngr.info.type) {
          case GST_PNM_TYPE_BITMAP:
            if (s->mngr.info.encoding == GST_PNM_ENCODING_ASCII) {
              r = GST_FLOW_ERROR;
              goto out;
            }
            s->size = s->mngr.info.width * s->mngr.info.height * 1;
            format = GST_VIDEO_FORMAT_GRAY8;
            break;
          case GST_PNM_TYPE_GRAYMAP:
            s->size = s->mngr.info.width * s->mngr.info.height * 1;
            format = GST_VIDEO_FORMAT_GRAY8;
            break;
          case GST_PNM_TYPE_PIXMAP:
            s->size = s->mngr.info.width * s->mngr.info.height * 3;
            format = GST_VIDEO_FORMAT_RGB;
            break;
        }
        output_state =
            gst_video_decoder_set_output_state (GST_VIDEO_DECODER (s), format,
            s->mngr.info.width, s->mngr.info.height, s->input_state);
        gst_video_codec_state_unref (output_state);
        if (gst_video_decoder_negotiate (GST_VIDEO_DECODER (s)) == FALSE) {
          r = GST_FLOW_NOT_NEGOTIATED;
          goto out;
        }

        if (s->mngr.info.encoding == GST_PNM_ENCODING_ASCII) {
          s->mngr.data_offset++;
          /* It is not possible to know the size of input ascii data to parse.
             So we have to parse and know the number of pixels parsed and
             then finally decide when we have full frame */
          s->buf = gst_buffer_new_and_alloc (s->size);
        }
        offset = s->mngr.data_offset;
        gst_adapter_flush (adapter, offset);
        size = size - offset;
    }
  }

  if (s->mngr.info.encoding == GST_PNM_ENCODING_ASCII) {
    /* Parse ASCII data dn populate s->current_size with the number of 
       bytes actually parsed from the input data */
    r = gst_pnmdec_parse_ascii (s, raw_data + offset, size);
  } else {
    /* Bitmap Contains 8 pixels in a byte */
    if (s->mngr.info.type == GST_PNM_TYPE_BITMAP)
      s->current_size += (size * 8);
    else
      s->current_size += size;
  }

  gst_video_decoder_add_to_frame (decoder, size);
  if (s->size <= s->current_size) {
    goto have_full_frame;
  }

need_more_data:
  return GST_VIDEO_DECODER_FLOW_NEED_DATA;

have_full_frame:
  return gst_video_decoder_have_frame (decoder);

out:
  return r;
}