Beispiel #1
0
bool OMXReader::SeekTime(int time, bool backwords, double *startpts)
{
  if(time < 0)
    time = 0;

  if(!m_pFormatContext)
    return false;

  if(m_pFile && !m_pFile->IoControl(IOCTRL_SEEK_POSSIBLE, NULL))
  {
    CLog::Log(LOGDEBUG, "%s - input stream reports it is not seekable", __FUNCTION__);
    return false;
  }

  Lock();

  //FlushRead();

  if(m_ioContext)
    m_ioContext->buf_ptr = m_ioContext->buf_end;

  int64_t seek_pts = (int64_t)time * (AV_TIME_BASE / 1000);
  if (m_pFormatContext->start_time != (int64_t)AV_NOPTS_VALUE)
    seek_pts += m_pFormatContext->start_time;


  int ret = m_dllAvFormat.av_seek_frame(m_pFormatContext, -1, seek_pts, backwords ? AVSEEK_FLAG_BACKWARD : 0);

  if(ret >= 0)
  {
    UpdateCurrentPTS();
  }
  else {
    //m_pFile->rewindFile();
    m_pFile->Seek(0);
    UpdateCurrentPTS();
    wasFileRewound = true;
  }

  // in this case the start time is requested time
  if(startpts)
    *startpts = DVD_MSEC_TO_TIME(time);

  // demuxer will return failure, if you seek to eof
  m_eof = false;
  if (m_pFile && m_pFile->IsEOF() && ret <= 0)
  {
    m_eof = true;
    ret = 0;
  }

  CLog::Log(LOGDEBUG, "OMXReader::SeekTime(%d) - seek ended up on time %d",time,(int)(m_iCurrentPts / DVD_TIME_BASE * 1000));

  UnLock();

  return (ret >= 0);
}
Beispiel #2
0
bool OMXReader::SeekTime(int64_t seek_ms, int seek_flags, double *startpts)
{
  if(seek_ms < 0)
    seek_ms = 0;

  if(!m_pFile || !m_pFormatContext)
    return false;

  if(!m_pFile->IoControl(IOCTRL_SEEK_POSSIBLE, NULL))
    return false;

  Lock();

  //FlushRead();

  if(m_ioContext)
    m_ioContext->buf_ptr = m_ioContext->buf_end;

  int64_t seek_pts = (int64_t)seek_ms * (AV_TIME_BASE / 1000);
  if (m_pFormatContext->start_time != (int64_t)AV_NOPTS_VALUE)
    seek_pts += m_pFormatContext->start_time;

  /* seek behind eof */
  if((seek_pts / AV_TIME_BASE) > (GetStreamLength()  / 1000))
  {
    m_eof = true;
    UnLock();
    return true;
  }

  int ret = m_dllAvFormat.av_seek_frame(m_pFormatContext, -1, seek_pts, seek_flags ? AVSEEK_FLAG_BACKWARD : 0);

  if(ret >= 0)
  {
    UpdateCurrentPTS();
    m_eof = false;
  }

  if(m_iCurrentPts == DVD_NOPTS_VALUE)
  {
    CLog::Log(LOGDEBUG, "OMXReader::SeekTime - unknown position after seek");
  }
  else
  {
    CLog::Log(LOGDEBUG, "OMXReader::SeekTime - seek ended up on time %d",(int)(m_iCurrentPts / DVD_TIME_BASE * 1000));
  }

  if(startpts)
    *startpts = DVD_MSEC_TO_TIME(seek_ms);

  UnLock();

  return (ret >= 0);
}
Beispiel #3
0
bool CDVDDemuxFFmpeg::SeekByte(__int64 pos)
{
  Lock();
  int ret = m_dllAvFormat.av_seek_frame(m_pFormatContext, -1, pos, AVSEEK_FLAG_BYTE);

  if(ret >= 0)
    UpdateCurrentPTS();

  Unlock();
  return (ret >= 0);
}
Beispiel #4
0
bool CDVDDemuxFFmpeg::SeekTime(int time, bool backwords, double *startpts)
{
  if(time < 0)
    time = 0;

  if (m_pInput->IsStreamType(DVDSTREAM_TYPE_DVD))
  {
    CLog::Log(LOGDEBUG, "%s - seeking using navigator", __FUNCTION__);
    if (((CDVDInputStreamNavigator*)m_pInput)->SeekTime(time))
    {
      // since seek happens behind demuxers back, we have to reset it
      // this won't be a problem if we setup ffmpeg properly later
      Reset();

      // todo, calculate starting pts in this case
      return true;
    }
    return false;
  }

  if(!m_pInput->Seek(0, SEEK_POSSIBLE) 
  && !m_pInput->IsStreamType(DVDSTREAM_TYPE_FFMPEG))
  {
    CLog::Log(LOGDEBUG, "%s - input stream reports it is not seekable", __FUNCTION__);
    return false;
  }

  __int64 seek_pts = (__int64)time * (AV_TIME_BASE / 1000);
  if (m_pFormatContext->start_time != (int64_t)AV_NOPTS_VALUE)
    seek_pts += m_pFormatContext->start_time;

  Lock();
  int ret = m_dllAvFormat.av_seek_frame(m_pFormatContext, -1, seek_pts, backwords ? AVSEEK_FLAG_BACKWARD : 0);

  if(ret >= 0)
    UpdateCurrentPTS();
  Unlock();

  if(m_iCurrentPts == DVD_NOPTS_VALUE)
    CLog::Log(LOGDEBUG, "%s - unknown position after seek", __FUNCTION__);
  else
    CLog::Log(LOGDEBUG, "%s - seek ended up on time %d", __FUNCTION__, (int)(m_iCurrentPts / DVD_TIME_BASE * 1000));

  // in this case the start time is requested time
  if(startpts)
    *startpts = DVD_MSEC_TO_TIME(time);

  // demuxer will return failure, if you seek to eof
  if (m_pInput->IsEOF() && ret <= 0)
    return true;

  return (ret >= 0);
}
Beispiel #5
0
bool OMXReader::Open(std::string filename, bool dump_format)
{
  if (!m_dllAvUtil.Load() || !m_dllAvCodec.Load() || !m_dllAvFormat.Load())
    return false;
  
  m_iCurrentPts = DVD_NOPTS_VALUE;
  m_filename    = filename; 
  m_speed       = DVD_PLAYSPEED_NORMAL;
  m_program     = UINT_MAX;
  const AVIOInterruptCB int_cb = { interrupt_cb, NULL };

  ClearStreams();

  m_dllAvFormat.av_register_all();
  m_dllAvFormat.avformat_network_init();
  m_dllAvUtil.av_log_set_level(AV_LOG_QUIET);

  int           result    = -1;
  AVInputFormat *iformat  = NULL;
  unsigned char *buffer   = NULL;
  unsigned int  flags     = READ_TRUNCATED | READ_BITRATE | READ_CHUNKED;
#ifndef STANDALONE
  if( CFileItem(m_filename, false).IsInternetStream() )
    flags |= READ_CACHED;
#endif

  if(m_filename.substr(0, 8) == "shout://" )
    m_filename.replace(0, 8, "http://");

  if(m_filename.substr(0,6) == "mms://" || m_filename.substr(0,7) == "http://" || 
      m_filename.substr(0,7) == "rtmp://" || m_filename.substr(0,6) == "udp://")
  {
    // ffmpeg dislikes the useragent from AirPlay urls
    //int idx = m_filename.Find("|User-Agent=AppleCoreMedia");
    size_t idx = m_filename.find("|");
    if(idx != string::npos)
      m_filename = m_filename.substr(0, idx);

    result = m_dllAvFormat.avformat_open_input(&m_pFormatContext, m_filename.c_str(), iformat, NULL);
    if(result < 0)
    {
      CLog::Log(LOGERROR, "COMXPlayer::OpenFile - avformat_open_input %s ", m_filename.c_str());
      Close();
      return false;
    }
  }
  else
  {
    m_pFile = new CFile();

    if (!m_pFile->Open(m_filename, flags))
    {
      CLog::Log(LOGERROR, "COMXPlayer::OpenFile - %s ", m_filename.c_str());
      Close();
      return false;
    }

    buffer = (unsigned char*)m_dllAvUtil.av_malloc(FFMPEG_FILE_BUFFER_SIZE);
    m_ioContext = m_dllAvFormat.avio_alloc_context(buffer, FFMPEG_FILE_BUFFER_SIZE, 0, m_pFile, dvd_file_read, NULL, dvd_file_seek);
    m_ioContext->max_packet_size = 6144;
    if(m_ioContext->max_packet_size)
      m_ioContext->max_packet_size *= FFMPEG_FILE_BUFFER_SIZE / m_ioContext->max_packet_size;

    if(m_pFile->IoControl(IOCTRL_SEEK_POSSIBLE, NULL) == 0)
      m_ioContext->seekable = 0;

    m_dllAvFormat.av_probe_input_buffer(m_ioContext, &iformat, m_filename.c_str(), NULL, 0, 0);

    if(!iformat)
    {
      CLog::Log(LOGERROR, "COMXPlayer::OpenFile - av_probe_input_buffer %s ", m_filename.c_str());
      Close();
      return false;
    }

    m_pFormatContext     = m_dllAvFormat.avformat_alloc_context();
    m_pFormatContext->pb = m_ioContext;
    result = m_dllAvFormat.avformat_open_input(&m_pFormatContext, m_filename.c_str(), iformat, NULL);
    if(result < 0)
    {
      Close();
      return false;
    }
  }

  // set the interrupt callback, appeared in libavformat 53.15.0
  m_pFormatContext->interrupt_callback = int_cb;

  m_bMatroska = strncmp(m_pFormatContext->iformat->name, "matroska", 8) == 0; // for "matroska.webm"
  m_bAVI = strcmp(m_pFormatContext->iformat->name, "avi") == 0;
  m_bMpeg = strcmp(m_pFormatContext->iformat->name, "mpeg") == 0;

  // if format can be nonblocking, let's use that
  m_pFormatContext->flags |= AVFMT_FLAG_NONBLOCK;

  // analyse very short to speed up mjpeg playback start
  if (iformat && (strcmp(iformat->name, "mjpeg") == 0) && m_ioContext->seekable == 0)
    m_pFormatContext->max_analyze_duration = 500000;

#ifdef STANDALONE
  if(/*m_bAVI || */m_bMatroska)
    m_pFormatContext->max_analyze_duration = 0;
#endif

  result = m_dllAvFormat.avformat_find_stream_info(m_pFormatContext, NULL);
  if(result < 0)
  {
    Close();
    return false;
  }

  if(!GetStreams())
  {
    Close();
    return false;
  }

  if(m_pFile)
  {
    int64_t len = m_pFile->GetLength();
    int64_t tim = GetStreamLength();

    if(len > 0 && tim > 0)
    {
      unsigned rate = len * 1000 / tim;
      unsigned maxrate = rate + 1024 * 1024 / 8;
      if(m_pFile->IoControl(IOCTRL_CACHE_SETRATE, &maxrate) >= 0)
        CLog::Log(LOGDEBUG, "COMXPlayer::OpenFile - set cache throttle rate to %u bytes per second", maxrate);
    }
  }

  printf("file : %s reult %d format %s audio streams %d video streams %d chapters %d subtitles %d\n", 
      m_filename.c_str(), result, m_pFormatContext->iformat->name, m_audio_count, m_video_count, m_chapter_count, m_subtitle_count);


  m_speed       = DVD_PLAYSPEED_NORMAL;

  if(dump_format)
    m_dllAvFormat.av_dump_format(m_pFormatContext, 0, m_filename.c_str(), 0);

  UpdateCurrentPTS();

  m_open        = true;

  return true;
}
Beispiel #6
0
bool CDVDDemuxFFmpeg::Open(CDVDInputStream* pInput)
{
  AVInputFormat* iformat = NULL;
  std::string strFile;
  m_iCurrentPts = DVD_NOPTS_VALUE;
  m_speed = DVD_PLAYSPEED_NORMAL;

  if (!pInput) return false;

  if (!m_dllAvUtil.Load() || !m_dllAvCodec.Load() || !m_dllAvFormat.Load())  {
    CLog::Log(LOGERROR,"CDVDDemuxFFmpeg::Open - failed to load ffmpeg libraries");
    return false;
  }

  // register codecs
  m_dllAvFormat.av_register_all();
  m_dllAvFormat.url_set_interrupt_cb(interrupt_cb);

  // could be used for interupting ffmpeg while opening a file (eg internet streams)
  // url_set_interrupt_cb(NULL);

  m_pInput = pInput;
  strFile = m_pInput->GetFileName();

  bool streaminfo = true; /* set to true if we want to look for streams before playback*/

  if( m_pInput->GetContent().length() > 0 )
  {
    std::string content = m_pInput->GetContent();

    /* check if we can get a hint from content */
    if( content.compare("audio/aacp") == 0 )
      iformat = m_dllAvFormat.av_find_input_format("aac");
    else if( content.compare("audio/aac") == 0 )
      iformat = m_dllAvFormat.av_find_input_format("aac");
    else if( content.compare("audio/mpeg") == 0  )  
      iformat = m_dllAvFormat.av_find_input_format("mp3");
    else if( content.compare("video/mpeg") == 0 )
      iformat = m_dllAvFormat.av_find_input_format("mpeg");
    else if( content.compare("video/flv") == 0 )
      iformat = m_dllAvFormat.av_find_input_format("flv");
    else if( content.compare("video/x-flv") == 0 )
      iformat = m_dllAvFormat.av_find_input_format("flv");

    /* these are likely pure streams, and as such we don't */
    /* want to try to look for streaminfo before playback */
    if( iformat )
      streaminfo = false;
  }

  if( m_pInput->IsStreamType(DVDSTREAM_TYPE_FFMPEG) )
  {
    g_urltimeout = GetTickCount() + 10000;

    // special stream type that makes avformat handle file opening
    // allows internal ffmpeg protocols to be used
    if( m_dllAvFormat.av_open_input_file(&m_pFormatContext, strFile.c_str(), iformat, FFMPEG_FILE_BUFFER_SIZE, NULL) < 0 )
    {
      CLog::Log(LOGDEBUG, "Error, could not open file %s", strFile.c_str());
      Dispose();
      return false;
    }
  }
  else
  {
    g_urltimeout = 0;

    // initialize url context to be used as filedevice
    URLContext* context = (URLContext*)m_dllAvUtil.av_mallocz(sizeof(struct URLContext) + strFile.length() + 1);
    context->prot = &dvd_file_protocol;
    context->priv_data = (void*)m_pInput;
    context->max_packet_size = FFMPEG_FILE_BUFFER_SIZE;

    if (m_pInput->IsStreamType(DVDSTREAM_TYPE_DVD))
    {
      context->max_packet_size = FFMPEG_DVDNAV_BUFFER_SIZE;
      context->is_streamed = 1;
    }
    if (m_pInput->IsStreamType(DVDSTREAM_TYPE_TV))
    {
      if(m_pInput->Seek(0, SEEK_POSSIBLE) == 0)
        context->is_streamed = 1;

      // this actually speeds up channel changes by almost a second
      // however, it alsa makes player not buffer anything, this
      // leads to buffer underruns in audio renderer
      //if(context->is_streamed)
      //  streaminfo = false;
    }
    else
    {
      if(m_pInput->Seek(0, SEEK_POSSIBLE) == 0)
        context->is_streamed = 1;
    }

#if LIBAVFORMAT_VERSION_INT >= (52<<16)
    context->filename = (char *) &context[1];
#endif

    strcpy(context->filename, strFile.c_str());  

    // open our virtual file device
    if(m_dllAvFormat.url_fdopen(&m_ioContext, context) < 0)
    {
      CLog::Log(LOGERROR, "%s - Unable to init io context", __FUNCTION__);
      m_dllAvUtil.av_free(context);
      Dispose();
      return false;
    }

    if( iformat == NULL )
    {
      // let ffmpeg decide which demuxer we have to open
      AVProbeData pd;
      BYTE probe_buffer[2048];

      // init probe data
      pd.buf = probe_buffer;
      pd.filename = strFile.c_str();

      // read data using avformat's buffers
      pd.buf_size = m_dllAvFormat.get_buffer(m_ioContext, pd.buf, sizeof(probe_buffer));            
      if (pd.buf_size == 0)
      {
        CLog::Log(LOGERROR, "%s - error reading from input stream, %s", __FUNCTION__, strFile.c_str());
        return false;
      }
      // restore position again
      m_dllAvFormat.url_fseek(m_ioContext , 0, SEEK_SET);

      iformat = m_dllAvFormat.av_probe_input_format(&pd, 1);
      if (!iformat)
      {
        CLog::Log(LOGERROR, "%s - error probing input format, %s", __FUNCTION__, strFile.c_str());
        return false;
      }
    }


    // open the demuxer
    if (m_dllAvFormat.av_open_input_stream(&m_pFormatContext, m_ioContext, strFile.c_str(), iformat, NULL) < 0)
    {
      CLog::Log(LOGERROR, "Error, could not open file %s", strFile.c_str());
      Dispose();
      return false;
    }
  }
  
  // we need to know if this is matroska later
  m_bMatroska = strcmp(m_pFormatContext->iformat->name, "matroska") == 0;

  // in combination with libdvdnav seek, av_find_stream_info wont work
  // so we do this for files only
  if (streaminfo)
  {
    if (m_pInput->IsStreamType(DVDSTREAM_TYPE_TV))
    {
      /* too speed up livetv channel changes, only analyse very short */ 
      if(m_pInput->Seek(0, SEEK_POSSIBLE) == 0)
        m_pFormatContext->max_analyze_duration = 500000;
    }


    CLog::Log(LOGDEBUG, "%s - av_find_stream_info starting", __FUNCTION__);
    int iErr = m_dllAvFormat.av_find_stream_info(m_pFormatContext);
    if (iErr < 0)
    {
      CLog::Log(LOGWARNING,"could not find codec parameters for %s", strFile.c_str());
      if (m_pFormatContext->nb_streams == 1 && m_pFormatContext->streams[0]->codec->codec_id == CODEC_ID_AC3)
      {
        // special case, our codecs can still handle it.
      }
      else
      {
        Dispose();
        return false;
      }
    }
    CLog::Log(LOGDEBUG, "%s - av_find_stream_info finished", __FUNCTION__);
  }
  // reset any timeout
  g_urltimeout = 0;

  // if format can be nonblocking, let's use that
  m_pFormatContext->flags |= AVFMT_FLAG_NONBLOCK;

  // print some extra information
  m_dllAvFormat.dump_format(m_pFormatContext, 0, strFile.c_str(), 0);

  UpdateCurrentPTS();

  // add the ffmpeg streams to our own stream array
  m_program = 0;
  if (m_pFormatContext->nb_programs)
  {
    // discard nonselected programs
    for (unsigned int i = 0; i < m_pFormatContext->nb_programs; i++)
    {
      if(i != m_program)
        m_pFormatContext->programs[m_program]->discard = AVDISCARD_ALL;
    }
    // add streams from selected program
    for (unsigned int i = 0; i < m_pFormatContext->programs[m_program]->nb_stream_indexes; i++)
      AddStream(m_pFormatContext->programs[m_program]->stream_index[i]);
  }
  else
  {
    for (unsigned int i = 0; i < m_pFormatContext->nb_streams; i++)
      AddStream(i);
  }

  return true;
}
Beispiel #7
0
bool OMXReader::Open(std::string filename, bool dump_format, bool live /* =false */, float timeout /* = 0.0f */, std::string cookie /* = "" */, std::string user_agent /* = "" */)
{
  if (!m_dllAvUtil.Load() || !m_dllAvCodec.Load() || !m_dllAvFormat.Load())
    return false;

  timeout_default_duration = (int64_t) (timeout * 1e9);
  m_iCurrentPts = DVD_NOPTS_VALUE;
  m_filename    = filename; 
  m_speed       = DVD_PLAYSPEED_NORMAL;
  m_program     = UINT_MAX;
  const AVIOInterruptCB int_cb = { interrupt_cb, NULL };
  RESET_TIMEOUT(3);

  ClearStreams();

  m_dllAvFormat.av_register_all();
  m_dllAvFormat.avformat_network_init();
  m_dllAvUtil.av_log_set_level(dump_format ? AV_LOG_INFO:AV_LOG_QUIET);

  int           result    = -1;
  AVInputFormat *iformat  = NULL;
  unsigned char *buffer   = NULL;
  unsigned int  flags     = READ_TRUNCATED | READ_BITRATE | READ_CHUNKED;

  m_pFormatContext     = m_dllAvFormat.avformat_alloc_context();
  if (!m_pFormatContext) {
     log_err("Failed to create format context.");
     return false;
  }

  // set the interrupt callback, appeared in libavformat 53.15.0
  m_pFormatContext->interrupt_callback = int_cb;

  // if format can be nonblocking, let's use that
  m_pFormatContext->flags |= AVFMT_FLAG_NONBLOCK;

  if(m_filename.substr(0, 8) == "shout://" )
    m_filename.replace(0, 8, "http://");

  if(m_filename.substr(0,6) == "mms://" || m_filename.substr(0,7) == "mmsh://" || m_filename.substr(0,7) == "mmst://" || m_filename.substr(0,7) == "mmsu://" ||
      m_filename.substr(0,7) == "http://" || m_filename.substr(0,8) == "https://" ||
      m_filename.substr(0,7) == "rtmp://" || m_filename.substr(0,6) == "udp://" ||
      m_filename.substr(0,7) == "rtsp://" || m_filename.substr(0,6) == "rtp://" ||
      m_filename.substr(0,6) == "ftp://" || m_filename.substr(0,7) == "sftp://" ||
      m_filename.substr(0,6) == "smb://")
  {
    // ffmpeg dislikes the useragent from AirPlay urls
    //int idx = m_filename.Find("|User-Agent=AppleCoreMedia");
    size_t idx = m_filename.find("|");
    if(idx != string::npos)
      m_filename = m_filename.substr(0, idx);

    AVDictionary *d = NULL;
    // Enable seeking if http, ftp
    if(!live && (m_filename.substr(0,7) == "http://" || m_filename.substr(0,6) == "ftp://" ||
       m_filename.substr(0,7) == "sftp://" || m_filename.substr(0,6) == "smb://"))
    {
       av_dict_set(&d, "seekable", "1", 0);
       if(!cookie.empty())
       {
          av_dict_set(&d, "cookies", cookie.c_str(), 0);
       }
       if(!user_agent.empty())
       {
          av_dict_set(&d, "user_agent", user_agent.c_str(), 0);
       }
    }
    CLog::Log(LOGDEBUG, "COMXPlayer::OpenFile - avformat_open_input %s ", m_filename.c_str());
    result = m_dllAvFormat.avformat_open_input(&m_pFormatContext, m_filename.c_str(), iformat, &d);
    if(av_dict_count(d) == 0)
    {
       CLog::Log(LOGDEBUG, "COMXPlayer::OpenFile - avformat_open_input enabled SEEKING ");
       if(m_filename.substr(0,7) == "http://")
         m_pFormatContext->pb->seekable = AVIO_SEEKABLE_NORMAL;
    }
    av_dict_free(&d);
    if(result < 0)
    {
      CLog::Log(LOGERROR, "COMXPlayer::OpenFile - avformat_open_input %s ", m_filename.c_str());
      Close();
      return false;
    }
  }
  else
  {
    m_pFile = new CFile();

    if (!m_pFile->Open(m_filename, flags))
    {
      CLog::Log(LOGERROR, "COMXPlayer::OpenFile - %s ", m_filename.c_str());
      Close();
      return false;
    }

    buffer = (unsigned char*)m_dllAvUtil.av_malloc(FFMPEG_FILE_BUFFER_SIZE);
    m_ioContext = m_dllAvFormat.avio_alloc_context(buffer, FFMPEG_FILE_BUFFER_SIZE, 0, m_pFile, dvd_file_read, NULL, dvd_file_seek);
    if (!m_ioContext) {
       log_err("Failed to create avio context.");
       return false;
    }

    m_ioContext->max_packet_size = 6144;
    if(m_ioContext->max_packet_size)
      m_ioContext->max_packet_size *= FFMPEG_FILE_BUFFER_SIZE / m_ioContext->max_packet_size;

    if(m_pFile->IoControl(IOCTRL_SEEK_POSSIBLE, NULL) == 0)
      m_ioContext->seekable = 0;

    m_dllAvFormat.av_probe_input_buffer(m_ioContext, &iformat, m_filename.c_str(), NULL, 0, 0);

    if(!iformat)
    {
      CLog::Log(LOGERROR, "COMXPlayer::OpenFile - av_probe_input_buffer %s ", m_filename.c_str());
      Close();
      return false;
    }

    m_pFormatContext->pb = m_ioContext;
    if (!m_pFormatContext->internal) {
       log_err("AVFormat internal null.");
       abort();
    }

    result = m_dllAvFormat.avformat_open_input(&m_pFormatContext, m_filename.c_str(), iformat, NULL);
    if(result < 0)
    {
      Close();
      return false;
    }
  }

  m_bMatroska = strncmp(m_pFormatContext->iformat->name, "matroska", 8) == 0; // for "matroska.webm"
  m_bAVI = strcmp(m_pFormatContext->iformat->name, "avi") == 0;

  // analyse very short to speed up mjpeg playback start
  if (iformat && (strcmp(iformat->name, "mjpeg") == 0) && m_ioContext->seekable == 0)
    m_pFormatContext->max_analyze_duration = 500000;

  if(/*m_bAVI || */m_bMatroska)
    m_pFormatContext->max_analyze_duration = 0;

  if (live)
    m_pFormatContext->flags |= AVFMT_FLAG_NOBUFFER;

  result = m_dllAvFormat.avformat_find_stream_info(m_pFormatContext, NULL);
  if(result < 0)
  {
    Close();
    return false;
  }

  if(!GetStreams())
  {
    Close();
    return false;
  }

  if(m_pFile)
  {
    int64_t len = m_pFile->GetLength();
    int64_t tim = GetStreamLength();

    if(len > 0 && tim > 0)
    {
      unsigned rate = len * 1000 / tim;
      unsigned maxrate = rate + 1024 * 1024 / 8;
      if(m_pFile->IoControl(IOCTRL_CACHE_SETRATE, &maxrate) >= 0)
        CLog::Log(LOGDEBUG, "COMXPlayer::OpenFile - set cache throttle rate to %u bytes per second", maxrate);
    }
  }

  m_speed       = DVD_PLAYSPEED_NORMAL;

  if(dump_format)
    m_dllAvFormat.av_dump_format(m_pFormatContext, 0, m_filename.c_str(), 0);

  UpdateCurrentPTS();

  m_open        = true;

  return true;
}
Beispiel #8
0
bool OMXReader::SeekTime(int time, bool backwords, double *startpts, bool doLoopOnFail)//doLoopOnFail = true
{
	if(time < 0)
	{
		time = 0;
	}

	if(!m_pFormatContext)
	{
		return false;
	}

	if(m_pFile && !m_pFile->IoControl(IOCTRL_SEEK_POSSIBLE, NULL))
	{
		ofLog(OF_LOG_VERBOSE, "%s - input stream reports it is not seekable", __FUNCTION__);
		return false;
	}

	Lock();

	//FlushRead();

	if(m_ioContext)
	{
		m_ioContext->buf_ptr = m_ioContext->buf_end;
	}

	int64_t seek_pts = (int64_t)time * (AV_TIME_BASE / 1000);
	if (m_pFormatContext->start_time != (int64_t)AV_NOPTS_VALUE)
	{
		seek_pts += m_pFormatContext->start_time;
	}

	//  virtual int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) { return ::av_seek_frame(s, stream_index, timestamp, flags); }

	int ret = m_dllAvFormat.av_seek_frame(m_pFormatContext, -1, seek_pts, backwords ? AVSEEK_FLAG_BACKWARD : 0);
	//int ret =avformat_seek_file(m_pFormatContext, -1, 0, seek_pts, m_pFormatContext->duration*1000, AVSEEK_FLAG_ANY);
	if(ret >= 0)
	{
		ofLogVerbose(__func__) << "av_seek_frame PASS: - returned: " << ret;
		UpdateCurrentPTS();
	}
	else
	{
		ofLogVerbose(__func__) << "av_seek_frame returned >= 0, - rewinding file" << ret;
		if (doLoopOnFail)
		{
			m_pFile->rewindFile();
			wasFileRewound = true;
		}

		UpdateCurrentPTS();

	}


	// in this case the start time is requested time
	if(startpts)
	{
		*startpts = DVD_MSEC_TO_TIME(time);
	}

	// demuxer will return failure, if you seek to eof
	m_eof = false;
	if (m_pFile && m_pFile->IsEOF() && ret <= 0)
	{
		m_eof = true;
		ret = 0;
	}
	//int landedTime = (int)(m_iCurrentPts / DVD_TIME_BASE * 1000);
	//ofLogVerbose(__func__) << "Seek ended up on time: " << landedTime;

	UnLock();

	return (ret >= 0);
}