title: Trying to fix VPlayer's seeking ability, need some guidance [Android FFmpeg]
body: <p>I'm trying to fix the currently broken seeking ability of <a href="https://github.com/matthewn4444/VPlayer_lib" rel="nofollow noreferrer">VPlayer</a> which is a FFmpeg player for Android. Being a Java developer, C code looks like alien language to me so can only fix it using common logic (which could make any C veteran have a good laugh).</p>
  
  <p>The relevant file is <a href="https://github.com/matthewn4444/VPlayer_lib/blob/master/VPlayer_library/jni/application/player.c" rel="nofollow noreferrer">player.c</a> and I'll try my best to point out the relevant modification.</p>
  
  <p>So the basic idea is because FFmpeg's <code>av_seek_frame</code> is very inaccurate even with <code>AVSEEK_FLAG_ANY</code> so I'm trying to follow <a href="https://stackoverflow.com/questions/17546073/how-can-i-seek-to-frame-no-x-with-ffmpeg">this suggestion</a> to seek backward to the nearest keyframe and then decode to the frame I want. One addition note is since I want to seek based on millisecond while the said solution show the way to seek by frame which is potentially a source of problem.</p>
  
  <p>In the <a href="https://github.com/matthewn4444/VPlayer_lib/blob/master/VPlayer_library/jni/application/player.c#L161" rel="nofollow noreferrer"><code>Player</code></a> I add the following fields:</p>
  
  <pre><code>struct Player{
  ....
  AVFrame *frame;
  int64_t current_time_stamp;
  }; 
  </code></pre>
  
  <p>In the <a href="https://github.com/matthewn4444/VPlayer_lib/blob/master/VPlayer_library/jni/application/player.c#L1239" rel="nofollow noreferrer"><code>player_read_from_stream</code></a> I modify the <a href="https://github.com/matthewn4444/VPlayer_lib/blob/master/VPlayer_library/jni/application/player.c#L1393" rel="nofollow noreferrer">seeking part</a> as:</p>
  
  <pre><code>void * player_read_from_stream(void *data) {
      ...
      struct DecoderData *decoder_data = data;
      int stream_no = decoder_data-&gt;stream_no;
      AVCodecContext * ctx = player-&gt;input_codec_ctxs[stream_no];
      ...
      // seeking, start my stuff
      if(av_seek_frame(player-&gt;input_format_ctx, seek_input_stream_number, seek_target, AVSEEK_FLAG_BACKWARD) &gt;= 0){
          //seek to key frame success, now need to read every frame from the key frame to our target time stamp
  
  
          while(player-&gt;current_time_stamp &lt; seek_target){
  
              int frame_done;
  
              while (av_read_frame(player-&gt;input_format_ctx, &amp;packet) &gt;= 0) {
                  if (packet.stream_index == seek_input_stream_number) {
  
                      avcodec_decode_video2(ctx, player-&gt;frame, &amp;frame_done, &amp;packet);
                      LOGI(1,"testing_stuff ctx %d", *ctx);
                      if (frame_done) {
  
                          player-&gt;current_time_stamp = packet.dts;
                          LOGI(1,"testing_stuff current_time_stamp: %"PRId64, player-&gt;current_time_stamp);
                          av_free_packet(&amp;packet);
                          return;
                      }
                  }
                  av_free_packet(&amp;packet);
              }
          }
  
  
      }
      //end my stuff
  
      LOGI(3, "player_read_from_stream seeking success");
  
      int64_t current_time = av_gettime();
      player-&gt;start_time = current_time - player-&gt;seek_position;
      player-&gt;pause_time = current_time;        
  }
  </code></pre>
  
  <p>And in <a href="https://github.com/matthewn4444/VPlayer_lib/blob/master/VPlayer_library/jni/application/player.c#L1847" rel="nofollow noreferrer"><code>player_alloc_frames</code></a> I allocate the memory for my frame as:</p>
  
  <pre><code>int player_alloc_frames(struct Player *player) {
      int capture_streams_no = player-&gt;caputre_streams_no;
      int stream_no;
      for (stream_no = 0; stream_no &lt; capture_streams_no; ++stream_no) {
          player-&gt;input_frames[stream_no] = av_frame_alloc();
  
          //todo: test my stuff
          player-&gt;frame = av_frame_alloc();
          //end test
  
          if (player-&gt;input_frames[stream_no] == NULL) {
              return -ERROR_COULD_NOT_ALLOC_FRAME;
          }
      }
      return 0;
  }
  </code></pre>
  
  <p>Currently it just keep crashing and being a typical Android NDK's "feature", it just provide a super helpful stack trace:</p>
  
  <p><code>libc: Fatal signal 11 (SIGSEGV), code 1, fault addr 0x40 in tid 2717 (FFmpegReadFromS)</code></p>
  
  <p>I very much appreciate if anyone could help me solve this problem. Thank you for your time.</p>