# include  "FrameReader.hpp" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <assert.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <unistd.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  ffmpeg_lockmgr_cb ( void  * * arg ,  enum  AVLockOp  op )  { 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  pthread_mutex_t  * mutex  =  ( pthread_mutex_t  * ) * arg ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  int  err ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  switch  ( op )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  case  AV_LOCK_CREATE : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    mutex  =  ( pthread_mutex_t  * ) malloc ( sizeof ( * mutex ) ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! mutex ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  AVERROR ( ENOMEM ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ( err  =  pthread_mutex_init ( mutex ,  NULL ) ) )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        free ( mutex ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  AVERROR ( err ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    * arg  =  mutex ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  0 ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  case  AV_LOCK_OBTAIN : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ( err  =  pthread_mutex_lock ( mutex ) ) ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  AVERROR ( err ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  0 ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  case  AV_LOCK_RELEASE : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ( err  =  pthread_mutex_unlock ( mutex ) ) ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  AVERROR ( err ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  0 ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  case  AV_LOCK_DESTROY : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( mutex ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        pthread_mutex_destroy ( mutex ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    free ( mutex ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    * arg  =  NULL ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  0 ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  return  1 ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								FrameReader : : FrameReader ( const  char  * fn )  { 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  int  ret ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  ret  =  av_lockmgr_register ( ffmpeg_lockmgr_cb ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  assert ( ret  > =  0 ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  avformat_network_init ( ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  av_register_all ( ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  snprintf ( url ,  sizeof ( url ) - 1 , " %s " , fn ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  t  =  new  std : : thread ( [ & ] ( )  {  this - > loaderThread ( ) ;  } ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  FrameReader : : loaderThread ( )  { 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  int  ret ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( avformat_open_input ( & pFormatCtx ,  url ,  NULL ,  NULL )  ! =  0 )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    fprintf ( stderr ,  " error loading %s \n " ,  url ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    valid  =  false ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  av_dump_format ( pFormatCtx ,  0 ,  url ,  0 ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  auto  pCodecCtxOrig  =  pFormatCtx - > streams [ 0 ] - > codec ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  auto  pCodec  =  avcodec_find_decoder ( pCodecCtxOrig - > codec_id ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  assert ( pCodec  ! =  NULL ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  pCodecCtx  =  avcodec_alloc_context3 ( pCodec ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  ret  =  avcodec_copy_context ( pCodecCtx ,  pCodecCtxOrig ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  assert ( ret  = =  0 ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  ret  =  avcodec_open2 ( pCodecCtx ,  pCodec ,  NULL ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  assert ( ret  > =  0 ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  sws_ctx  =  sws_getContext ( width ,  height ,  AV_PIX_FMT_YUV420P , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                           width ,  height ,  AV_PIX_FMT_BGR24 , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                           SWS_BILINEAR ,  NULL ,  NULL ,  NULL ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  assert ( sws_ctx  ! =  NULL ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  AVPacket  * pkt  =  ( AVPacket  * ) malloc ( sizeof ( AVPacket ) ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  assert ( pkt  ! =  NULL ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  bool  first  =  true ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  while  ( av_read_frame ( pFormatCtx ,  pkt ) > = 0 )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //printf("%d pkt %d %d\n", pkts.size(), pkt->size, pkt->pos);
   
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( first )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      AVFrame  * pFrame  =  av_frame_alloc ( ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      int  frameFinished ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      avcodec_decode_video2 ( pCodecCtx ,  pFrame ,  & frameFinished ,  pkt ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      first  =  false ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    pkts . push_back ( pkt ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    pkt  =  ( AVPacket  * ) malloc ( sizeof ( AVPacket ) ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    assert ( pkt  ! =  NULL ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  free ( pkt ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  printf ( " framereader download done \n " ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  joined  =  true ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  // cache
   
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  while  ( 1 )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    GOPCache ( to_cache . get ( ) ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  FrameReader : : GOPCache ( int  idx )  { 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  AVFrame  * pFrame ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  int  gop  =  idx  -  idx % 15 ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  mcache . lock ( ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  bool  has_gop  =  cache . find ( gop )  ! =  cache . end ( ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  mcache . unlock ( ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( ! has_gop )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //printf("caching %d\n", gop);
   
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  ( int  i  =  gop ;  i  <  gop + 15 ;  i + + )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( i  > =  pkts . size ( ) )  break ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      //printf("decode %d\n", i);
   
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      int  frameFinished ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      pFrame  =  av_frame_alloc ( ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      avcodec_decode_video2 ( pCodecCtx ,  pFrame ,  & frameFinished ,  pkts [ i ] ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      uint8_t  * dat  =  toRGB ( pFrame ) - > data [ 0 ] ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      mcache . lock ( ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      cache . insert ( std : : make_pair ( i ,  dat ) ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      mcache . unlock ( ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								AVFrame  * FrameReader : : toRGB ( AVFrame  * pFrame )  { 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  AVFrame  * pFrameRGB  =  av_frame_alloc ( ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  int  numBytes  =  avpicture_get_size ( AV_PIX_FMT_BGR24 ,  pFrame - > width ,  pFrame - > height ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  uint8_t  * buffer  =  ( uint8_t  * ) av_malloc ( numBytes * sizeof ( uint8_t ) ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  avpicture_fill ( ( AVPicture  * ) pFrameRGB ,  buffer ,  AV_PIX_FMT_BGR24 ,  pFrame - > width ,  pFrame - > height ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									sws_scale ( sws_ctx ,  ( uint8_t  const  *  const  * ) pFrame - > data , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														pFrame - > linesize ,  0 ,  pFrame - > height , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														pFrameRGB - > data ,  pFrameRGB - > linesize ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  return  pFrameRGB ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								uint8_t  * FrameReader : : get ( int  idx )  { 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( ! valid )  return  NULL ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  waitForReady ( ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  // TODO: one line?
   
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  uint8_t  * dat  =  NULL ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  // lookahead
   
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  to_cache . put ( idx ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  to_cache . put ( idx + 15 ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  mcache . lock ( ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  auto  it  =  cache . find ( idx ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( it  ! =  cache . end ( ) )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    dat  =  it - > second ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  mcache . unlock ( ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( dat  = =  NULL )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    to_cache . put_front ( idx ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // lookahead
   
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    while  ( dat  = =  NULL )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // wait for frame
   
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      usleep ( 50 * 1000 ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // check for frame
   
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      mcache . lock ( ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      auto  it  =  cache . find ( idx ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( it  ! =  cache . end ( ) )  dat  =  it - > second ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      mcache . unlock ( ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( dat  = =  NULL )  { 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        printf ( " . " ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        fflush ( stdout ) ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  return  dat ; 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}