예제 #1
0
파일: bdremux.c 프로젝트: OpenDMM/bdremux
static gboolean
do_seek (App * app)
{
    gint64 in_pos, out_pos;
    gfloat rate = 1.0;
    GstFormat fmt = GST_FORMAT_TIME;
    GstSeekFlags flags = 0;
    int ret;

    if (app->current_segment >= app->segment_count) {
        GST_WARNING ("seek segment not found!");
        return FALSE;
    }

    GST_INFO ("do_seek...");
    flags |= GST_SEEK_FLAG_FLUSH;
//      flags |= GST_SEEK_FLAG_ACCURATE;
    flags |= GST_SEEK_FLAG_KEY_UNIT;
    flags |= GST_SEEK_FLAG_SEGMENT;

    gst_element_query_position ((app->pipeline), &fmt, &in_pos);
    GST_DEBUG ("do_seek::initial gst_element_query_position = %lld ms",
               in_pos / 1000000);

    in_pos =
        MPEGTIME_TO_GSTTIME (app->seek_segments[app->current_segment].in_pts);
    GST_DEBUG ("do_seek::in_time for segment %i = %lld ms", app->current_segment,
               in_pos / 1000000);

    out_pos = -1;
//       MPEGTIME_TO_GSTTIME (app->seek_segments[app->current_segment].out_pts);
    GST_DEBUG ("do_seek::out_time for segment %i = %lld ms", app->current_segment,
               out_pos / 1000000);

    ret = gst_element_seek ((app->pipeline), rate, GST_FORMAT_TIME, flags,
                            GST_SEEK_TYPE_SET, in_pos, GST_SEEK_TYPE_SET, out_pos);

    gst_element_query_position ((app->pipeline), &fmt, &in_pos);
    GST_DEBUG
    ("do_seek::seek command returned %i. new gst_element_query_position = %lld ms",
     ret, in_pos / 1000000);

    if (ret)
        app->current_segment++;

    return ret;
}
예제 #2
0
static GstFlowReturn
gst_mpeg_demux_parse_pes (GstMPEGParse * mpeg_parse, GstBuffer * buffer)
{
  GstMPEGDemux *mpeg_demux = GST_MPEG_DEMUX (mpeg_parse);
  guint8 id;

  guint16 packet_length;
  guint8 header_data_length = 0;

  guint16 datalen;
  guint16 headerlen;
  GstClockTime timestamp;

  GstFlowReturn ret = GST_FLOW_OK;

  GstMPEGStream *outstream = NULL;
  guint8 *buf;

  buf = GST_BUFFER_DATA (buffer);
  id = *(buf + 3);
  buf += 4;

  /* start parsing */
  packet_length = GST_READ_UINT16_BE (buf);

  GST_DEBUG_OBJECT (mpeg_demux, "packet_length %d", packet_length);
  buf += 2;

  /* we don't operate on: program_stream_map, padding_stream, */
  /* private_stream_2, ECM, EMM, or program_stream_directory  */
  if ((id != 0xBC) && (id != 0xBE) && (id != 0xBF) && (id != 0xF0) &&
      (id != 0xF1) && (id != 0xFF)) {
    guchar flags1 = *buf++;
    guchar flags2 = *buf++;

    if ((flags1 & 0xC0) != 0x80) {
      return FALSE;
    }

    header_data_length = *buf++;

    GST_DEBUG_OBJECT (mpeg_demux, "header_data_length: %d", header_data_length);

    /* check for PTS */
    if ((flags2 & 0x80)) {
      gint64 pts;

      pts = ((guint64) (*buf++ & 0x0E)) << 29;
      pts |= ((guint64) * buf++) << 22;
      pts |= ((guint64) (*buf++ & 0xFE)) << 14;
      pts |= ((guint64) * buf++) << 7;
      pts |= ((guint64) (*buf++ & 0xFE)) >> 1;

      /* Check for pts overflow */
      if (mpeg_demux->last_pts != -1) {
        gint32 diff = pts - mpeg_demux->last_pts;

        if (diff > -4 * CLOCK_FREQ && diff < 4 * CLOCK_FREQ)
          pts = mpeg_demux->last_pts + diff;
      }
      mpeg_demux->last_pts = pts;

      timestamp = PARSE_CLASS (mpeg_parse)->adjust_ts (mpeg_parse,
          MPEGTIME_TO_GSTTIME (pts));

      GST_DEBUG_OBJECT (mpeg_demux,
          "0x%02x (% " G_GINT64_FORMAT ") PTS = %" G_GUINT64_FORMAT, id, pts,
          MPEGTIME_TO_GSTTIME (pts));
    } else {
예제 #3
0
static GstFlowReturn
gst_mpeg_demux_parse_packet (GstMPEGParse * mpeg_parse, GstBuffer * buffer)
{
  GstMPEGDemux *mpeg_demux = GST_MPEG_DEMUX (mpeg_parse);
  guint8 id;
  guint16 headerlen;

  guint16 packet_length;
  gboolean STD_buffer_bound_scale;
  guint16 STD_buffer_size_bound;
  guint64 dts;
  gint64 pts = -1;

  guint16 datalen;

  GstMPEGStream *outstream = NULL;
  guint8 *buf, *basebuf;
  gint64 timestamp;

  GstFlowReturn ret = GST_FLOW_OK;

  basebuf = buf = GST_BUFFER_DATA (buffer);
  id = *(buf + 3);
  buf += 4;

  /* start parsing */
  packet_length = GST_READ_UINT16_BE (buf);

  GST_DEBUG_OBJECT (mpeg_demux, "got packet_length %d", packet_length);
  headerlen = 2;
  buf += 2;

  /* loop through looping for stuffing bits, STD, PTS, DTS, etc */
  do {
    guint8 bits = *buf++;

    /* stuffing bytes */
    switch (bits & 0xC0) {
      case 0xC0:
        if (bits == 0xff) {
          GST_DEBUG_OBJECT (mpeg_demux, "have stuffing byte");
        } else {
          GST_DEBUG_OBJECT (mpeg_demux, "expected stuffing byte");
        }
        headerlen++;
        break;
      case 0x40:
        GST_DEBUG_OBJECT (mpeg_demux, "have STD");

        STD_buffer_bound_scale = bits & 0x20;
        STD_buffer_size_bound = ((guint16) (bits & 0x1F)) << 8;
        STD_buffer_size_bound |= *buf++;

        headerlen += 2;
        break;
      case 0x00:
        switch (bits & 0x30) {
          case 0x20:
            /* pts:3 ! 1 ! pts:15 ! 1 | pts:15 ! 1 */
            pts = ((guint64) (bits & 0x0E)) << 29;
            pts |= ((guint64) (*buf++)) << 22;
            pts |= ((guint64) (*buf++ & 0xFE)) << 14;
            pts |= ((guint64) (*buf++)) << 7;
            pts |= ((guint64) (*buf++ & 0xFE)) >> 1;

            GST_DEBUG_OBJECT (mpeg_demux, "PTS = %" G_GUINT64_FORMAT, pts);
            headerlen += 5;
            goto done;
          case 0x30:
            /* pts:3 ! 1 ! pts:15 ! 1 | pts:15 ! 1 */
            pts = ((guint64) (bits & 0x0E)) << 29;
            pts |= ((guint64) (*buf++)) << 22;
            pts |= ((guint64) (*buf++ & 0xFE)) << 14;
            pts |= ((guint64) (*buf++)) << 7;
            pts |= ((guint64) (*buf++ & 0xFE)) >> 1;

            /* sync:4 ! pts:3 ! 1 ! pts:15 ! 1 | pts:15 ! 1 */
            dts = ((guint64) (*buf++ & 0x0E)) << 29;
            dts |= ((guint64) * buf++) << 22;
            dts |= ((guint64) (*buf++ & 0xFE)) << 14;
            dts |= ((guint64) * buf++) << 7;
            dts |= ((guint64) (*buf++ & 0xFE)) >> 1;

            GST_DEBUG_OBJECT (mpeg_demux, "PTS = %" G_GUINT64_FORMAT
                ", DTS = %" G_GUINT64_FORMAT, pts, dts);
            headerlen += 10;
            goto done;
          case 0x00:
            GST_DEBUG_OBJECT (mpeg_demux, "have no pts/dts");
            GST_DEBUG_OBJECT (mpeg_demux, "got trailer bits %x", (bits & 0x0f));
            if ((bits & 0x0f) != 0xf) {
              GST_DEBUG_OBJECT (mpeg_demux, "not a valid packet time sequence");
              return FALSE;
            }
            headerlen++;
          default:
            goto done;
        }
      default:
        goto done;
    }
  } while (1);
  GST_DEBUG_OBJECT (mpeg_demux, "done with header loop");

done:

  /* calculate the amount of real data in this packet */
  datalen = packet_length - headerlen + 2;

  GST_DEBUG_OBJECT (mpeg_demux, "headerlen is %d, datalen is %d",
      headerlen, datalen);

  if (pts != -1) {
    /* Check for pts overflow */
    if (mpeg_demux->last_pts != -1) {
      gint32 diff = pts - mpeg_demux->last_pts;

      if (diff > -4 * CLOCK_FREQ && diff < 4 * CLOCK_FREQ)
        pts = mpeg_demux->last_pts + diff;
    }
    mpeg_demux->last_pts = pts;

    timestamp = PARSE_CLASS (mpeg_parse)->adjust_ts (mpeg_parse,
        MPEGTIME_TO_GSTTIME (pts));

    /* this apparently happens for some input were headers are
     * rewritten to make time start at zero... */
    if ((gint64) timestamp < 0)
      timestamp = 0;
  } else {
    timestamp = GST_CLOCK_TIME_NONE;
  }

  if (id == 0xBD) {
    /* Private stream 1. */
    GST_DEBUG_OBJECT (mpeg_demux, "we have a private 1 packet");
    ret = CLASS (mpeg_demux)->process_private (mpeg_demux, buffer, 0, timestamp,
        headerlen, datalen);
  } else if (id == 0xBF) {
    /* Private stream 2. */
    GST_DEBUG_OBJECT (mpeg_demux, "we have a private 2 packet");
    ret = CLASS (mpeg_demux)->process_private (mpeg_demux, buffer, 1, timestamp,
        headerlen, datalen);
  } else if (id >= 0xC0 && id <= 0xDF) {
    /* Audio. */
    GST_DEBUG_OBJECT (mpeg_demux, "we have an audio packet");
    outstream = CLASS (mpeg_demux)->get_audio_stream (mpeg_demux,
        id - 0xC0, GST_MPEG_DEMUX_AUDIO_MPEG, NULL);
    ret = CLASS (mpeg_demux)->send_subbuffer (mpeg_demux, outstream, buffer,
        timestamp, headerlen + 4, datalen);
  } else if (id >= 0xE0 && id <= 0xEF) {
    /* Video. */
    gint mpeg_version = !GST_MPEG_PARSE_IS_MPEG2 (mpeg_demux) ? 1 : 2;

    GST_DEBUG_OBJECT (mpeg_demux, "we have a video packet");

    outstream = CLASS (mpeg_demux)->get_video_stream (mpeg_demux,
        id - 0xE0, GST_MPEG_DEMUX_VIDEO_MPEG, &mpeg_version);
    ret = CLASS (mpeg_demux)->send_subbuffer (mpeg_demux, outstream, buffer,
        timestamp, headerlen + 4, datalen);
  } else if (id == 0xBE) {
    /* padding stream */
    GST_DEBUG_OBJECT (mpeg_demux, "we have a padding packet");
  } else {
    GST_WARNING_OBJECT (mpeg_demux, "unknown stream id 0x%02x", id);
  }

  return ret;
}