Esempio n. 1
0
int
main(int argc, char *argv[])
{
  PwIntRect screen, picture;
  PwTileMap *tilemap;
  GOptionContext *context;
  GError *error = NULL;

  tilemap = pwtilemap_create();

  context = g_option_context_new("SCREEN PICTURE - check tile mapping");
  pwtilemap_add_options(tilemap, context);
  g_option_context_parse(context, &argc, &argv, &error);
  if (! error) {
    if (argc != 3) {
      g_set_error(&error, G_OPTION_ERROR, 0, "Wrong number of arguments %d",
		  argc);
    } else {
      pwintrect_from_string(&screen, argv[1], &error);
      if (! error) {
	pwintrect_from_string(&picture, argv[2], &error);
      }
    }
  }
  if (! error) {
    pwtilemap_set_screen(tilemap, &screen);
  }
  if (! error) {
    pwtilemap_define(tilemap, &error);
  }
  if (! error) {
    PwIntRect src, dest;
    PwVcTransform xform;
    pwtilemap_map_picture(tilemap, &picture,
			  &src, &dest, &xform,
			  &error);
    if (! error) {
      printf("src: %dx%d+%d+%d\n",
	     PWRECT_WIDTH(src), PWRECT_HEIGHT(src), src.x0, src.y0);
      printf("dest: %dx%d+%d+%d\n",
	     PWRECT_WIDTH(dest), PWRECT_HEIGHT(dest), dest.x0, dest.y0);
      printf("transform: %d\n", (int)xform);
    }
  }

  if (error) {
    fprintf(stderr, "%s\n", error->message);
    return 1;
  }
  return 0;
}
Esempio n. 2
0
int SyncVideo::play()
{
// signal(SIGINT, sig_handler);
bool m_first = true;
#if WANT_KEYS
  if (isatty(STDIN_FILENO))
  {
    struct termios new_termios;

    tcgetattr(STDIN_FILENO, &orig_termios);

    new_termios             = orig_termios;
    new_termios.c_lflag     &= ~(ICANON | ECHO | ECHOCTL | ECHONL);
    new_termios.c_cflag     |= HUPCL;
    new_termios.c_cc[VMIN]  = 0;


    tcsetattr(STDIN_FILENO, TCSANOW, &new_termios);
    atexit(restore_termios);
  }
  else
  {
    orig_fl = fcntl(STDIN_FILENO, F_GETFL);
    fcntl(STDIN_FILENO, F_SETFL, orig_fl | O_NONBLOCK);
    atexit(restore_fl);
  }
#endif /* WANT_KEYS */

  
  double                m_incr                = 0;
  CRBP                  g_RBP;
  COMXCore              g_OMX;
  bool                  m_quiet               = false;
  bool                  m_stats               = false;
  bool                  m_dump_format         = false;
  FORMAT_3D_T           m_3d                  = CONF_FLAGS_FORMAT_NONE;
  bool                  m_refresh             = false;
  double                startpts              = 0;
  CRect                 DestRect              = {0,0,0,0};
  TV_DISPLAY_STATE_T   tv_state;
  GError                *error = NULL;

  const int font_opt      = 0x100;
  const int font_size_opt = 0x101;
  const int align_opt     = 0x102;
  const int subtitles_opt = 0x103;
  const int lines_opt     = 0x104;
  const int pos_opt       = 0x105;
  const int vol_opt       = 0x106;
  const int boost_on_downmix_opt = 0x200;
  const int tile_code_opt = 0x300;
  const int frame_size_opt = 0x301;

  //LOOP
  double loop_offset     = 0.0;
  double last_packet_pts = 0.0;
  double last_packet_dts = 0.0;
  double last_packet_duration = 0.0;

  
 //  int c;
 //  std::string mode;
 //  while ((c = getopt_long(argc, argv, "wihn:l:o:cqslpd3:yzt:rW:T:O:F:AR:C:", longopts, NULL)) != -1)
 //  {
 //    switch (c) 
 //    {
 //      case 'q':
 //        m_quiet = true;
 //        break;
    
 //      case 'l':
 //        m_seek_pos = atoi(optarg) ;
 //        if (m_seek_pos < 0)
 //            m_seek_pos = 0;
 //        break;
 
 //      case pos_opt:
	// sscanf(optarg, "%f %f %f %f", &DestRect.x1, &DestRect.y1, &DestRect.x2, &DestRect.y2);
 //        break;
 
 //      case tile_code_opt:
	// if (! m_tilemap) m_tilemap = pwtilemap_create();
	// pwtilemap_set_tilecode(m_tilemap, atoi(optarg));
	// break;
 //      case frame_size_opt:
	// {
	//   float fx, fy;
	//   char c;
	//   if (! m_tilemap) m_tilemap = pwtilemap_create();
	//   if (sscanf(optarg, "%gx%g%c", &fx, &fy, &c) != 2) {
	//     fprintf(stderr, "pwomxplayer --frame-size: invalid FXxFY\n");
	//     return 2;
	//   }
	//   pwtilemap_set_framesize(m_tilemap, fx, fy);
	// }
	// break;
 //      case 'W':
	// {
	//   PwRect wall;
	//   if (! m_tilemap) m_tilemap = pwtilemap_create();
	//   if (! pwrect_from_string(&wall, optarg, &error)) {
	//     fprintf(stderr, "pwomxplayer --wall: %s\n", error->message);
	//     return 2;
	//   } else {
	//     pwtilemap_set_wall(m_tilemap, &wall);
	//   }
	// }
	// break;
 //      case 'T':
	// {
	//   PwRect tile;
	//   if (! m_tilemap) m_tilemap = pwtilemap_create();
	//   if (! pwrect_from_string(&tile, optarg, &error)) {
	//     fprintf(stderr, "pwomxplayer --tile: %s\n", error->message);
	//     return 2;
	//   } else {
	//     pwtilemap_set_tile(m_tilemap, &tile);
	//   }
	// }
	// break;
 //      case 'O':
	// {
	//   PwOrient orient;
	//   if (! m_tilemap) m_tilemap = pwtilemap_create();
	//   if (! pworient_from_string(&orient, optarg, &error)) {
	//     fprintf(stderr, "pwomxplayer --orient: %s\n", error->message);
	//     return 2;
	//   } else {
	//     pwtilemap_set_orient(m_tilemap, orient);
	//   }
	// }
	// break;
 //      case 'F':
	// {
	//   PwFit fit;
	//   if (! m_tilemap) m_tilemap = pwtilemap_create();
	//   if (! pwfit_from_string(&fit, optarg, &error)) {
	//     fprintf(stderr, "pwomxplayer --fit: %s\n", error->message);
	//     return 2;
	//   } else {
	//     pwtilemap_set_fit(m_tilemap, fit);
	//   }
	// }
	// break;
 //      case 'A':
	// if (! m_tilemap) m_tilemap = pwtilemap_create();
	// pwtilemap_set_auto(m_tilemap);
	// break;
 //      case 'R':
	// if (! m_tilemap) m_tilemap = pwtilemap_create();
	// pwtilemap_set_role(m_tilemap, optarg);
	// break;
 //      case 'C':
	// if (! m_tilemap) m_tilemap = pwtilemap_create();
	// pwtilemap_set_config(m_tilemap, optarg);
	// break;
 //      case 0:
 //        break;
 //      case 'h':
 //        print_usage();
 //        return 0;
 //        break;
 //      case ':':
 //        return 0;
 //        break;
 //      default:
 //        return 0;
 //        break;
 //    }
 //  }

  

  


//changement de taille ICI
  if(m_wallWidth > 0 && m_wallHeight > 0)
  {
    ostringstream  wallStr;
    wallStr << m_wallWidth << "x" << m_wallHeight << "+0+0";
    cout << "WALL " << wallStr.str() << endl;
    PwRect wall;
    if (! m_tilemap) m_tilemap = pwtilemap_create();
    if (! pwrect_from_string(&wall, wallStr.str().c_str(), &error)) {
      fprintf(stderr, "pwomxplayer --wall: %s\n", error->message);
      return 2;
    } else {
      pwtilemap_set_wall(m_tilemap, &wall);
    }
  }

  if(m_tileWidth > 0 && m_tileHeight > 0 && m_tileX >= 0 && m_tileY >= 0)
  {
    ostringstream tileStr;
    tileStr << m_tileWidth << "x" << m_tileHeight << "+" << m_tileX  << "+" << m_tileY;
    cout << "TILE " << tileStr.str() << endl;
    PwRect tile;  
    if (! m_tilemap) m_tilemap = pwtilemap_create();
    if (! pwrect_from_string(&tile, tileStr.str().c_str(), &error)) {
      fprintf(stderr, "pwomxplayer --tile: %s\n", error->message);
      return 2;
    } else {
      pwtilemap_set_tile(m_tilemap, &tile);
    }
  }


  auto PrintFileNotFound = [](const std::string& path)
  {
    printf("File \"%s\" not found.\n", path.c_str());
  };

  bool filename_is_URL = IsURL(m_filename);

  if(!filename_is_URL && !Exists(m_filename))
  {
    PrintFileNotFound(m_filename);
    return 0;
  }

  if(m_has_font && !Exists(m_font_path))
  {
    PrintFileNotFound(m_font_path);
    return 0;
  }

  if(m_has_external_subtitles && !Exists(m_external_subtitles_path))
  {
    PrintFileNotFound(m_external_subtitles_path);
    return 0;
  }

  if(!m_has_external_subtitles && !filename_is_URL)
  {
    auto subtitles_path = m_filename.substr(0, m_filename.find_last_of(".")) +
                          ".srt";

    if(Exists(subtitles_path))
    {
      m_external_subtitles_path = subtitles_path;
      m_has_external_subtitles = true;
    }
  }

  if (m_tilemap != NULL) {
    if (! pwtilemap_define(m_tilemap, &error)) {
      fprintf(stderr, "pwomxplayer: %s\n", error->message);
      return 1;
    }
  }


  g_RBP.Initialize();
  g_OMX.Initialize();

  m_av_clock = new OMXClock();

  m_thread_player = true;

  if(!m_omx_reader.Open(m_filename.c_str(), m_dump_format, ! m_quiet))
    goto do_exit;

  if(m_dump_format)
    goto do_exit;

  //LOOP
  if(m_loop && !m_omx_reader.CanSeek()) {
    printf("Looping requested on an input that doesn't support seeking\n");
    goto do_exit;
  }

  struct timeval now;
  gettimeofday(&now, NULL);

  //start date is over and we can navigate through the stream
  if(m_dateStart < now.tv_sec && m_omx_reader.CanSeek())
  {

    if(m_omx_reader.GetStreamLength() < 15000)
    {
      
      struct tm * timeinfo;
      char buffer [80];

      timeinfo = localtime (&(m_dateStart));
      strftime (buffer,80," %I:%M:%S%p.",timeinfo);
      printf("previous time %s\n", buffer);

      m_seek_pos = 0;
      m_dateStart = now.tv_sec + 15 + m_omx_reader.GetStreamLength()/1000 - ((now.tv_sec+15)%(m_omx_reader.GetStreamLength()/1000));
      

      timeinfo = localtime (&(m_dateStart));
      strftime (buffer,80," %I:%M:%S%p.",timeinfo);
      printf("after time %s\n", buffer);


    }else
    {
      //but there is still some video to play (with a safety)
      if(m_dateEnd > now.tv_sec + 15)
      {
        printf("Start on the go\n");
        m_seek_pos = now.tv_sec - m_dateStart + 15;

        if(m_seek_pos > m_omx_reader.GetStreamLength()/1000 && m_loop)
        {
          printf("seekpos %i\n", m_seek_pos);
          printf("duration %i\n", m_omx_reader.GetStreamLength());
          m_seek_pos = m_seek_pos % (m_omx_reader.GetStreamLength()/1000);
          printf("new seekpos %i\n", m_seek_pos);
        }

        m_dateStart = now.tv_sec + 15;
      }
    }
  }


  m_bMpeg         = m_omx_reader.IsMpegVideo();
  m_has_video     = m_omx_reader.VideoStreamCount();
  m_has_audio     = m_omx_reader.AudioStreamCount();
  m_has_subtitle  = m_has_external_subtitles ||
                    m_omx_reader.SubtitleStreamCount();

  if(m_filename.find("3DSBS") != string::npos || m_filename.find("HSBS") != string::npos)
    m_3d = CONF_FLAGS_FORMAT_SBS;
  else if(m_filename.find("3DTAB") != string::npos || m_filename.find("HTAB") != string::npos)
    m_3d = CONF_FLAGS_FORMAT_TB;

  // 3d modes don't work without switch hdmi mode
  if (m_3d != CONF_FLAGS_FORMAT_NONE)
    m_refresh = true;

  // you really don't want want to match refresh rate without hdmi clock sync
  if (m_refresh && !m_no_hdmi_clock_sync)
    m_hdmi_clock_sync = true;

  if(!m_av_clock->OMXInitialize(m_has_video, m_has_audio))
    goto do_exit;

  if(m_hdmi_clock_sync && !m_av_clock->HDMIClockSync())
      goto do_exit;

  m_omx_reader.GetHints(OMXSTREAM_AUDIO, m_hints_audio);
  m_omx_reader.GetHints(OMXSTREAM_VIDEO, m_hints_video);

  if(m_audio_index_use != -1)
    m_omx_reader.SetActiveStream(OMXSTREAM_AUDIO, m_audio_index_use);
          
  if(m_has_video && m_refresh)
  {
    memset(&tv_state, 0, sizeof(TV_DISPLAY_STATE_T));
    m_BcmHost.vc_tv_get_display_state(&tv_state);

    SetVideoMode(m_hints_video.width, m_hints_video.height, m_hints_video.fpsrate, m_hints_video.fpsscale, m_3d, ! m_quiet);
  }
  // get display aspect
  TV_DISPLAY_STATE_T current_tv_state;
  memset(&current_tv_state, 0, sizeof(TV_DISPLAY_STATE_T));
  m_BcmHost.vc_tv_get_display_state(&current_tv_state);
  if(current_tv_state.state & ( VC_HDMI_HDMI | VC_HDMI_DVI )) {
    //HDMI or DVI on
    m_display_aspect = get_display_aspect_ratio((HDMI_ASPECT_T)current_tv_state.display.hdmi.aspect_ratio);
  } else {
    //composite on
    m_display_aspect = get_display_aspect_ratio((SDTV_ASPECT_T)current_tv_state.display.sdtv.display_options.aspect);
  }
  m_display_aspect *= (float)current_tv_state.display.hdmi.height/(float)current_tv_state.display.hdmi.width;

  if (m_tilemap != NULL) {
    PwIntRect screen;
    PWRECT_SET0(screen,
		current_tv_state.display.hdmi.width,
		current_tv_state.display.hdmi.height);
    pwtilemap_set_screen(m_tilemap, &screen);
  }

  // seek on start
  if (m_seek_pos !=0 && m_omx_reader.CanSeek()) {
    if (! m_quiet)
      printf("Seeking start of video to %i seconds\n", m_seek_pos);
    m_omx_reader.SeekTime(m_seek_pos * 1000.0f, 0, &startpts);  // from seconds to DVD_TIME_BASE
  }
  
  if(m_has_video && !m_player_video.Open(m_hints_video, m_av_clock, m_tilemap, DestRect, ! m_quiet, m_Deinterlace,  m_bMpeg,
                                         m_hdmi_clock_sync, m_thread_player, m_display_aspect))
    goto do_exit;

  {
    std::vector<Subtitle> external_subtitles;
    if(m_has_external_subtitles &&
       !ReadSrt(m_external_subtitles_path, external_subtitles))
    {
       puts("Unable to read the subtitle file.");
       goto do_exit;
    }

    if(m_has_subtitle &&
       !m_player_subtitles.Open(m_omx_reader.SubtitleStreamCount(),
                                std::move(external_subtitles),
                                m_font_path,
                                m_font_size,
                                m_centered,
                                m_subtitle_lines,
                                m_av_clock))
      goto do_exit;
  }

  if(m_has_subtitle)
  {
    if(!m_has_external_subtitles)
    {
      if(m_subtitle_index != -1)
      {
        m_player_subtitles.SetActiveStream(
          std::min(m_subtitle_index, m_omx_reader.SubtitleStreamCount()-1));
      }
      m_player_subtitles.SetUseExternalSubtitles(false);
    }

    if(m_subtitle_index == -1 && !m_has_external_subtitles)
      m_player_subtitles.SetVisible(false);
  }

  m_omx_reader.GetHints(OMXSTREAM_AUDIO, m_hints_audio);

  if (deviceString == "")
  {
    if (m_BcmHost.vc_tv_hdmi_audio_supported(EDID_AudioFormat_ePCM, 2, EDID_AudioSampleRate_e44KHz, EDID_AudioSampleSize_16bit ) == 0)
      deviceString = "omx:hdmi";
    else
      deviceString = "omx:local";
  }

  if(m_has_audio && !m_player_audio.Open(m_hints_audio, m_av_clock, &m_omx_reader, deviceString, 
                                         m_passthrough, m_initialVolume, m_use_hw_audio,
                                         m_boost_on_downmix, m_thread_player))
    goto do_exit;

   


  m_av_clock->SetSpeed(DVD_PLAYSPEED_NORMAL);
  m_av_clock->OMXStateExecute();
  m_av_clock->OMXStart(0.0);

  struct timespec starttime, endtime;

  if (! m_quiet)
    PrintSubtitleInfo();



  while(!m_stop)
  {
    //verifie le temps de fin
    struct timeval now;
    gettimeofday(&now, NULL);
    if(now.tv_sec > m_dateEnd)
    {
      Stop();
      goto do_exit;
    }



    if(SyncVideo::g_abort)
      goto do_exit;

// #if WANT_KEYS
//     int ch[8];
//     int chnum = 0;
// #endif

    
// #if WANT_KEYS
//     while((ch[chnum] = getchar()) != EOF) chnum++;
//     if (chnum > 1) ch[0] = ch[chnum - 1] | (ch[chnum - 2] << 8);

//     switch(ch[0])
//     {
//       case 'z':
//         m_tv_show_info = !m_tv_show_info;
//         vc_tv_show_info(m_tv_show_info);
//         break;
//       case '1':
//         SetSpeed(m_av_clock->OMXPlaySpeed() - 1);
//         break;
//       case '2':
//         SetSpeed(m_av_clock->OMXPlaySpeed() + 1);
//         break;
//       case 'j':
//         if(m_has_audio)
//         {
//           int new_index = m_omx_reader.GetAudioIndex() - 1;
//           if (new_index >= 0)
//             m_omx_reader.SetActiveStream(OMXSTREAM_AUDIO, new_index);
//         }
//         break;
//       case 'k':
//         if(m_has_audio)
//           m_omx_reader.SetActiveStream(OMXSTREAM_AUDIO, m_omx_reader.GetAudioIndex() + 1);
//         break;
//       case 'i':
//         if(m_omx_reader.GetChapterCount() > 0)
//         {
//           m_omx_reader.SeekChapter(m_omx_reader.GetChapter() - 1, &startpts);
//           FlushStreams(startpts);
//         }
//         else
//         {
//           m_incr = -600.0;
//         }
//         break;
//       case 'o':
//         if(m_omx_reader.GetChapterCount() > 0)
//         {
//           m_omx_reader.SeekChapter(m_omx_reader.GetChapter() + 1, &startpts);
//           FlushStreams(startpts);
//         }
//         else
//         {
//           m_incr = 600.0;
//         }
//         break;
//       case 'n':
//         if(m_has_subtitle)
//         {
//           if(!m_player_subtitles.GetUseExternalSubtitles())
//           {
//             if (m_player_subtitles.GetActiveStream() == 0)
//             {
//               if(m_has_external_subtitles)
//                 m_player_subtitles.SetUseExternalSubtitles(true);
//             }
//             else
//             {
//               m_player_subtitles.SetActiveStream(
//                 m_player_subtitles.GetActiveStream()-1);
//             }
//           }

//           m_player_subtitles.SetVisible(true);
//           PrintSubtitleInfo();
//         }
//         break;
//       case 'm':
//         if(m_has_subtitle)
//         {
//           if(m_player_subtitles.GetUseExternalSubtitles())
//           {
//             if(m_omx_reader.SubtitleStreamCount())
//             {
//               assert(m_player_subtitles.GetActiveStream() == 0);
//               m_player_subtitles.SetUseExternalSubtitles(false);
//             }
//           }
//           else
//           {
//             auto new_index = m_player_subtitles.GetActiveStream()+1;
//             if(new_index < (size_t) m_omx_reader.SubtitleStreamCount())
//               m_player_subtitles.SetActiveStream(new_index);
//           }

//           m_player_subtitles.SetVisible(true);
//           PrintSubtitleInfo();
//         }
//         break;
//       case 's':
//         if(m_has_subtitle)
//         {
//           m_player_subtitles.SetVisible(!m_player_subtitles.GetVisible());
//           PrintSubtitleInfo();
//         }
//         break;
//       case 'd':
//         if(m_has_subtitle && m_player_subtitles.GetVisible())
//         {
//           m_player_subtitles.SetDelay(m_player_subtitles.GetDelay() - 250);
//           PrintSubtitleInfo();
//         }
//         break;
//       case 'f':
//         if(m_has_subtitle && m_player_subtitles.GetVisible())
//         {
//           m_player_subtitles.SetDelay(m_player_subtitles.GetDelay() + 250);
//           PrintSubtitleInfo();
//         }
//         break;
//       case 'q': case 27:
//         m_stop = true;
//         goto do_exit;
//         break;
//       case 0x5b44: // key left
//         if(m_omx_reader.CanSeek()) m_incr = -30.0;
//         break;
//       case 0x5b43: // key right
//         if(m_omx_reader.CanSeek()) m_incr = 30.0;
//         break;
//       case 0x5b41: // key up
//         if(m_omx_reader.CanSeek()) m_incr = 600.0;
//         break;
//       case 0x5b42: // key down
//         if(m_omx_reader.CanSeek()) m_incr = -600.0;
//         break;
//       case ' ':
//       case 'p':
//         m_Pause = !m_Pause;
//         if(m_Pause)
//         {
//           SetSpeed(OMX_PLAYSPEED_PAUSE);
//           m_av_clock->OMXPause();
//           if(m_has_subtitle)
//             m_player_subtitles.Pause();
//         }
//         else
//         {
//           if(m_has_subtitle)
//             m_player_subtitles.Resume();
//           SetSpeed(OMX_PLAYSPEED_NORMAL);
//           m_av_clock->OMXResume();
//         }
//         break;
//       case '-':
//         m_player_audio.SetCurrentVolume(m_player_audio.GetCurrentVolume() - 300);
//         if (! m_quiet)
// 	  printf("Current Volume: %.2fdB\n", m_player_audio.GetCurrentVolume() / 100.0f);
//         break;
//       case '+': case '=':
//         m_player_audio.SetCurrentVolume(m_player_audio.GetCurrentVolume() + 300);
//         if (! m_quiet)
// 	  printf("Current Volume: %.2fdB\n", m_player_audio.GetCurrentVolume() / 100.0f);
//         break;
//       default:
//         break;
//     }
// #endif /* WANT_KEYS */

    if(m_Pause)
    {
      OMXClock::OMXSleep(2);
      continue;
    }

    if(m_incr != 0 && !m_bMpeg)
    {
      int    seek_flags   = 0;
      double seek_pos     = 0;
      double pts          = 0;

      if(m_has_subtitle)
        m_player_subtitles.Pause();

      m_av_clock->OMXStop();

      pts = m_av_clock->GetPTS();

      seek_pos = (pts / DVD_TIME_BASE) + m_incr;
      seek_flags = m_incr < 0.0f ? AVSEEK_FLAG_BACKWARD : 0;

      seek_pos *= 1000.0f;

      m_incr = 0;

      if(m_omx_reader.SeekTime(seek_pos, seek_flags, &startpts))
        FlushStreams(startpts);

      m_player_video.Close();
      if(m_has_video && !m_player_video.Open(m_hints_video, m_av_clock, m_tilemap, DestRect, ! m_quiet, m_Deinterlace, m_bMpeg,
                                         m_hdmi_clock_sync, m_thread_player, m_display_aspect))
        goto do_exit;

      m_av_clock->OMXStart(startpts);
      
      if(m_has_subtitle)
        m_player_subtitles.Resume();
    }

    /* player got in an error state */
    if(m_player_audio.Error())
    {
      fprintf(stderr, "audio player error. emergency exit!!!\n");
      goto do_exit;
    }

    if(m_stats)
    {
      printf("V : %8.02f %8d %8d A : %8.02f %8.02f Cv : %8d Ca : %8d                            \r",
             m_av_clock->OMXMediaTime(), m_player_video.GetDecoderBufferSize(),
             m_player_video.GetDecoderFreeSpace(), m_player_audio.GetCurrentPTS() / DVD_TIME_BASE, 
             m_player_audio.GetDelay(), m_player_video.GetCached(), m_player_audio.GetCached());
    }



    //DEBUT LOOP
    if(m_loop && m_omx_reader.IsEof() && !m_omx_pkt && m_isOver) {
      m_isOver = false;
      CLog::Log(LOGINFO, "EOF detected; looping requested");
      printf("RESTART !!\n");
      m_incr = -DBL_MAX;
      m_first= true;
      
      struct timeval now;
      gettimeofday(&now, NULL); 
      m_dateStart += (m_omx_reader.GetStreamLength()/1000) + 2 - m_seek_pos;
      printf("length of stream %i\n", m_omx_reader.GetStreamLength()/1000);
      printf("seek %i\n", m_seek_pos);
      m_seek_pos = 0;
    }







    if(m_omx_reader.IsEof() && !m_omx_pkt)
    {
      if (!m_player_audio.GetCached() && !m_player_video.GetCached())
      {
        if(m_loop)
        {
          cout << "abort ABORT !!" << endl;
          m_isOver = true;
          if(m_has_audio)
            m_player_audio.WaitCompletion();
          else if(m_has_video)
            m_player_video.WaitCompletion();


        }else
        {
          break;
        }
      }

      // Abort audio buffering, now we're on our own
      if (m_buffer_empty && m_first)
      {
        printf("en attente (empty buffer)\n");
        m_timer.SleepUntilTime(m_dateStart);
        printf("GO\n");
        m_av_clock->OMXResume();
        m_first = false;
      }

      OMXClock::OMXSleep(10);
      continue;
    }

    /* when the audio buffer runs under 0.1 seconds we buffer up */
    if(m_has_audio)
    {
      if(m_player_audio.GetDelay() < 0.1f && !m_buffer_empty)
      {
        if(!m_av_clock->OMXIsPaused())
        {
          m_av_clock->OMXPause();
          //printf("buffering start\n");
          m_buffer_empty = true;
          clock_gettime(CLOCK_REALTIME, &starttime);
        }
      }
      // printf("A\n");
      if(m_player_audio.GetDelay() > (AUDIO_BUFFER_SECONDS * 0.75f) && m_buffer_empty)
      {
        if(m_av_clock->OMXIsPaused())
        {
          printf("en attente\n");
          m_timer.SleepUntilTime(m_dateStart);
          m_av_clock->OMXResume();
          printf("GO\n");
          m_buffer_empty = false;
        }
      }
      if(m_buffer_empty)
      {
        clock_gettime(CLOCK_REALTIME, &endtime);
        if((endtime.tv_sec - starttime.tv_sec) > 1)
        {
          m_buffer_empty = false;
          m_av_clock->OMXResume();
          //printf("buffering timed out\n");
        }
      }
    }

    if(!m_omx_pkt)
      m_omx_pkt = m_omx_reader.Read();

    if(m_has_video && m_omx_pkt && m_omx_reader.IsActive(OMXSTREAM_VIDEO, m_omx_pkt->stream_index))
    {
      if(m_player_video.AddPacket(m_omx_pkt))
        m_omx_pkt = NULL;
      else
        OMXClock::OMXSleep(10);

      if(m_tv_show_info)
      {
        char response[80];
        vc_gencmd(response, sizeof response, "render_bar 4 video_fifo %d %d %d %d", 
                m_player_video.GetDecoderBufferSize()-m_player_video.GetDecoderFreeSpace(),
                0 , 0, m_player_video.GetDecoderBufferSize());
        vc_gencmd(response, sizeof response, "render_bar 5 audio_fifo %d %d %d %d", 
                (int)(100.0*m_player_audio.GetDelay()), 0, 0, 100*AUDIO_BUFFER_SECONDS);
      }
    }
    else if(m_has_audio && m_omx_pkt && m_omx_pkt->codec_type == AVMEDIA_TYPE_AUDIO)
    {
      if(m_player_audio.AddPacket(m_omx_pkt))
        m_omx_pkt = NULL;
      else
        OMXClock::OMXSleep(10);
    }
    else if(m_has_subtitle && m_omx_pkt &&
            m_omx_pkt->codec_type == AVMEDIA_TYPE_SUBTITLE)
    {
      auto result = m_player_subtitles.AddPacket(m_omx_pkt,
                      m_omx_reader.GetRelativeIndex(m_omx_pkt->stream_index));
      if (result)
        m_omx_pkt = NULL;
      else
        OMXClock::OMXSleep(10);
    }
    else
    {
      if(m_omx_pkt)
      {
        m_omx_reader.FreePacket(m_omx_pkt);
        m_omx_pkt = NULL;
      }
    }
  }

do_exit:
  if (m_stats)
    printf("\n");

  if(!m_stop && !SyncVideo::g_abort)
  {
    cout << "WAIT" << endl;
    if(m_has_audio)
      m_player_audio.WaitCompletion();
    else if(m_has_video)
      m_player_video.WaitCompletion();

    cout << "WAIT OVER" << endl;
  }

  if(m_has_video && m_refresh && tv_state.display.hdmi.group && tv_state.display.hdmi.mode)
  {
    m_BcmHost.vc_tv_hdmi_power_on_explicit_new(HDMI_MODE_HDMI, (HDMI_RES_GROUP_T)tv_state.display.hdmi.group, tv_state.display.hdmi.mode);
  }

  m_av_clock->OMXStop();
  m_av_clock->OMXStateIdle();

  m_player_subtitles.Close();
  m_player_video.Close();
  m_player_audio.Close();

  if(m_omx_pkt)
  {
    m_omx_reader.FreePacket(m_omx_pkt);
    m_omx_pkt = NULL;
  }

  m_omx_reader.Close();

  vc_tv_show_info(0);

  g_OMX.Deinitialize();
  g_RBP.Deinitialize();

  if (! m_quiet)
    printf("have a nice day ;)\n");
  return 1;
}