Пример #1
0
static int demux_demuxers_fill_buffer(demuxer_t *demux,demux_stream_t *ds) {
  dd_priv_t* priv;

  priv=demux->priv;

  if(ds->demuxer == priv->vd)
    return demux_fill_buffer(priv->vd,ds);
  else if(ds->demuxer == priv->ad)
    return demux_fill_buffer(priv->ad,ds);
  else if(ds->demuxer == priv->sd)
    return demux_fill_buffer(priv->sd,ds);
 
  mp_msg(MSGT_DEMUX,MSGL_WARN,MSGTR_MPDEMUX_DEMUXERS_FillBufferError);
  return 0;
}
Пример #2
0
static void demux_demuxers_seek(demuxer_t *demuxer,float rel_seek_secs,float audio_delay,int flags) {
  dd_priv_t* priv;
  float pos;
  priv=demuxer->priv;

  priv->ad->stream->eof = 0;
  priv->sd->stream->eof = 0;

  // Seek video
  demux_seek(priv->vd,rel_seek_secs,audio_delay,flags);
  // Get the new pos
  pos = demuxer->video->pts;
  if (!pos) {
    demux_fill_buffer(priv->vd, demuxer->video);
    if (demuxer->video->first)
      pos = demuxer->video->first->pts;
  }

  if(priv->ad != priv->vd && demuxer->audio->sh) {
    sh_audio_t* sh = demuxer->audio->sh;
    demux_seek(priv->ad,pos,audio_delay,1);
    // In case the demuxer don't set pts
    if(!demuxer->audio->pts)
      demuxer->audio->pts = pos-((ds_tell_pts(demuxer->audio)-sh->a_in_buffer_len)/(float)sh->i_bps);
  }

  if(priv->sd != priv->vd)
      demux_seek(priv->sd,pos,audio_delay,1);

}
Пример #3
0
double ds_get_next_pts(demux_stream_t *ds)
{
    demuxer_t *demux = ds->demuxer;
    // if we have not read from the "current" packet, consider it
    // as the next, otherwise we never get the pts for the first packet.
    while (!ds->first && (!ds->current || ds->buffer_pos)) {
        if (demux->audio->packs >= MAX_PACKS
            || demux->audio->bytes >= MAX_PACK_BYTES) {
            mp_tmsg(MSGT_DEMUXER, MSGL_ERR, "\nToo many audio packets in the buffer: (%d in %d bytes).\n",
                   demux->audio->packs, demux->audio->bytes);
            mp_tmsg(MSGT_DEMUXER, MSGL_HINT, MaybeNI);
            return MP_NOPTS_VALUE;
        }
        if (demux->video->packs >= MAX_PACKS
            || demux->video->bytes >= MAX_PACK_BYTES) {
            mp_tmsg(MSGT_DEMUXER, MSGL_ERR, "\nToo many video packets in the buffer: (%d in %d bytes).\n",
                   demux->video->packs, demux->video->bytes);
            mp_tmsg(MSGT_DEMUXER, MSGL_HINT, MaybeNI);
            return MP_NOPTS_VALUE;
        }
        if (!demux_fill_buffer(demux, ds))
            return MP_NOPTS_VALUE;
    }
    // take pts from "current" if we never read from it.
    if (ds->current && !ds->buffer_pos)
        return ds->current->pts;
    return ds->first->pts;
}
Пример #4
0
/// Open an mpg physical stream
static demuxer_t* demux_mpg_open(demuxer_t* demuxer) {
  stream_t *s = demuxer->stream;
  mpg_demuxer_t* mpg_d = calloc(1,sizeof(*mpg_d));
  if (!mpg_d)
    return NULL;
  demuxer->priv = mpg_d;

  while (demuxer->video->packs + demuxer->audio->packs < 2)
    if (!demux_fill_buffer(demuxer, demuxer->video)) return 0;
    mpg_d->last_pts = -1.0;
    mpg_d->first_pts = -1.0;

    //if seeking is allowed set has_valid_timestamps if appropriate
    if(demuxer->seekable
       && (demuxer->stream->type == STREAMTYPE_FILE
           || demuxer->stream->type == STREAMTYPE_VCD)
       && demuxer->movi_start != demuxer-> movi_end
    )
    {
      //We seek to the beginning of the stream, to somewhere in the
      //middle, and to the end of the stream, while remembering the pts
      //at each of the three positions. With these pts, we check whether
      //or not the pts are "linear enough" to justify seeking by the pts
      //of the stream

      //The position where the stream is now
      off_t pos = stream_tell(s);
      float first_pts = read_first_mpeg_pts_at_position(demuxer, demuxer->movi_start);
      if(first_pts != -1.0)
      {
        float middle_pts = read_first_mpeg_pts_at_position(demuxer, (demuxer->movi_end + demuxer->movi_start)/2);
        if(middle_pts != -1.0)
        {
          float final_pts = read_first_mpeg_pts_at_position(demuxer, demuxer->movi_end - TIMESTAMP_PROBE_LEN);
          if(final_pts != -1.0)
          {
            // found proper first, middle, and final pts.
            float proportion = (middle_pts-first_pts==0) ? -1 : (final_pts-middle_pts)/(middle_pts-first_pts);
            // if they are linear enough set has_valid_timestamps
            if((0.5 < proportion) && (proportion < 2))
            {
              mpg_d->first_pts = first_pts;
              mpg_d->first_to_final_pts_len = final_pts - first_pts;
              mpg_d->has_valid_timestamps = 1;
            }
          }
        }
      }

      //Cleaning up from seeking in stream
      reset_eof(demuxer);

      stream_seek(s,pos);
      ds_fill_buffer(demuxer->video);
    } // if ( demuxer->seekable )
  return demuxer;
}
Пример #5
0
static int demux_demuxers_fill_buffer(demuxer_t *demux,demux_stream_t *ds) {
  dd_priv_t* priv;

  priv=demux->priv;

  // HACK: make sure the subtitles get properly interleaved if with -subfile
  if (priv->sd && priv->sd->sub != ds &&
      priv->sd != priv->vd && priv->sd != priv->ad)
    ds_get_next_pts(priv->sd->sub);
  if(priv->vd && priv->vd->video == ds)
    return demux_fill_buffer(priv->vd,ds);
  else if(priv->ad && priv->ad->audio == ds)
    return demux_fill_buffer(priv->ad,ds);
  else if(priv->sd && priv->sd->sub == ds)
    return demux_fill_buffer(priv->sd,ds);

  mp_msg(MSGT_DEMUX,MSGL_WARN,MSGTR_MPDEMUX_DEMUXERS_FillBufferError);
  return 0;
}
static void demux_demuxers_seek(demuxer_t *demuxer,float rel_seek_secs,float audio_delay,int flags) {
  dd_priv_t* priv;
  float pos;
  priv=demuxer->priv;

  priv->ad->stream->eof = 0;
  priv->sd->stream->eof = 0;

  // Seek video
  demux_seek(priv->vd,rel_seek_secs,audio_delay,flags);
  // Get the new pos
  pos = demuxer->video->pts;
  if (!pos) {
    // since the video demuxer might provide multiple
    // streams (e.g. subs) we might have to call
    // demux_fill_buffer multiple times.
    int limit = 10;
    do {
      demux_fill_buffer(priv->vd, demuxer->video);
    } while (--limit && !demuxer->video->first);
    if (demuxer->video->first)
      pos = demuxer->video->first->pts;
  }

  if(priv->ad != priv->vd && demuxer->audio->sh) {
    sh_audio_t* sh = demuxer->audio->sh;
    demux_seek(priv->ad,pos,audio_delay,1);
    // In case the demuxer don't set pts
    if(!demuxer->audio->pts)
      demuxer->audio->pts = pos-((ds_tell_pts(demuxer->audio)-sh->a_in_buffer_len)/(float)sh->i_bps);
  }

  if(priv->sd != priv->vd)
      demux_seek(priv->sd,pos,audio_delay,1);

}
Пример #7
0
// return value:
//     0 = EOF
//     1 = successful
int ds_fill_buffer(demux_stream_t *ds)
{
    demuxer_t *demux = ds->demuxer;
    if (ds->current)
        free_demux_packet(ds->current);
    ds->current = NULL;
    mp_dbg(MSGT_DEMUXER, MSGL_DBG3, "ds_fill_buffer (%s) called\n",
           ds == demux->audio ? "d_audio" : ds == demux->video ? "d_video" :
           ds == demux->sub   ? "d_sub"   : "unknown");
    while (1) {
        if (ds->packs) {
            demux_packet_t *p = ds->first;
            // copy useful data:
            ds->buffer = p->buffer;
            ds->buffer_pos = 0;
            ds->buffer_size = p->len;
            ds->pos = p->pos;
            ds->dpos += p->len; // !!!
            ++ds->pack_no;
            if (p->pts != MP_NOPTS_VALUE) {
                ds->pts = p->pts;
                ds->pts_bytes = 0;
            }
            ds->pts_bytes += p->len;    // !!!
            if (p->stream_pts != MP_NOPTS_VALUE)
                demux->stream_pts = p->stream_pts;
            ds->keyframe = p->keyframe;
            // unlink packet:
            ds->bytes -= p->len;
            ds->current = p;
            ds->first = p->next;
            if (!ds->first)
                ds->last = NULL;
            --ds->packs;
            /* The code below can set ds->eof to 1 when another stream runs
             * out of buffer space. That makes sense because in that situation
             * the calling code should not count on being able to demux more
             * packets from this stream.
             * If however the situation improves and we're called again
             * despite the eof flag then it's better to clear it to avoid
             * weird behavior. */
            ds->eof = 0;
            return 1;
        }

#define MaybeNI _("Maybe you are playing a non-interleaved stream/file or the codec failed?\n" \
                "For AVI files, try to force non-interleaved mode with the -ni option.\n")

        if (demux->audio->packs >= MAX_PACKS
            || demux->audio->bytes >= MAX_PACK_BYTES) {
            mp_tmsg(MSGT_DEMUXER, MSGL_ERR, "\nToo many audio packets in the buffer: (%d in %d bytes).\n",
                   demux->audio->packs, demux->audio->bytes);
            mp_tmsg(MSGT_DEMUXER, MSGL_HINT, MaybeNI);
            break;
        }
        if (demux->video->packs >= MAX_PACKS
            || demux->video->bytes >= MAX_PACK_BYTES) {
            mp_tmsg(MSGT_DEMUXER, MSGL_ERR, "\nToo many video packets in the buffer: (%d in %d bytes).\n",
                   demux->video->packs, demux->video->bytes);
            mp_tmsg(MSGT_DEMUXER, MSGL_HINT, MaybeNI);
            break;
        }
        if (!demux_fill_buffer(demux, ds)) {
            mp_dbg(MSGT_DEMUXER, MSGL_DBG2,
                   "ds_fill_buffer()->demux_fill_buffer() failed\n");
            break; // EOF
        }
    }
    ds->buffer_pos = ds->buffer_size = 0;
    ds->buffer = NULL;
    mp_msg(MSGT_DEMUXER, MSGL_V,
           "ds_fill_buffer: EOF reached (stream: %s)  \n",
           ds == demux->audio ? "audio" : "video");
    ds->eof = 1;
    return 0;
}