Selaa lähdekoodia

wma拖动问题

chendeben 6 kuukautta sitten
vanhempi
sitoutus
fc2572be8e
1 muutettua tiedostoa jossa 58 lisäystä ja 19 poistoa
  1. 58 19
      ijkplayer/src/main/cpp/ijkplayer/ff_ffplay.c

+ 58 - 19
ijkplayer/src/main/cpp/ijkplayer/ff_ffplay.c

@@ -30,7 +30,8 @@
  * @file
  * simple media player based on the FFmpeg libraries
  */
-#include<stdio.h>
+#include <stdio.h>
+#include <string.h>
 #include "config.h"
 #include <inttypes.h>
 #include <math.h>
@@ -3236,10 +3237,19 @@ static int read_thread(void *arg)
         /* add the stream start time */
         if (ic->start_time != AV_NOPTS_VALUE)
             timestamp += ic->start_time;
-        ret = avformat_seek_file(ic, -1, INT64_MIN, timestamp, INT64_MAX, 0);
-        if (ret < 0) {
-            av_log(NULL, AV_LOG_WARNING, "%s: could not seek to position %0.3f\n",
-                    is->filename, (double)timestamp / AV_TIME_BASE);
+
+        // Skip initial seek for ASF format to avoid crash
+        int is_asf_init = (ic->iformat && ic->iformat->name &&
+                          (strcmp(ic->iformat->name, "asf") == 0 ||
+                           strstr(ic->iformat->name, "asf") != NULL));
+        if (is_asf_init) {
+            av_log(ffp, AV_LOG_WARNING, "heanup: ASF format detected, skipping initial seek\n");
+        } else {
+            ret = avformat_seek_file(ic, -1, INT64_MIN, timestamp, INT64_MAX, 0);
+            if (ret < 0) {
+                av_log(NULL, AV_LOG_WARNING, "%s: could not seek to position %0.3f\n",
+                        is->filename, (double)timestamp / AV_TIME_BASE);
+            }
         }
     }
 
@@ -3413,23 +3423,52 @@ static int read_thread(void *arg)
             ffp_notify_msg3(ffp, FFP_MSG_BUFFERING_UPDATE, 0, 0);
 
             // Workaround for ASF/WMA seek crash (FFmpeg ff_seek_frame_binary uninitialized variable issue)
-            // See: https://ffmpeg.org/pipermail/ffmpeg-cvslog/2024-April/142447.html
-            // For ASF format, use AVSEEK_FLAG_BACKWARD to avoid triggering binary seek with uninitialized pos_min/pos_max
+            // The FFmpeg libavformat has a bug in ff_seek_frame_binary with uninitialized pos_min/pos_max
+            // For ASF format, we completely disable seek to prevent crash
             int seek_flags = is->seek_flags;
-            int is_asf_format = (ic->iformat && ic->iformat->name && !strcmp(ic->iformat->name, "asf"));
-            if (is_asf_format) {
-                seek_flags |= AVSEEK_FLAG_BACKWARD;
-                av_log(ffp, AV_LOG_DEBUG, "ASF format detected, using AVSEEK_FLAG_BACKWARD for seek\n");
-            }
 
-            ret = avformat_seek_file(is->ic, -1, seek_min, seek_target, seek_max, seek_flags);
+            // Debug: print format name to diagnose ASF detection
+            const char *format_name = (ic->iformat && ic->iformat->name) ? ic->iformat->name : "unknown";
+            av_log(ffp, AV_LOG_WARNING, "heanup seek: format_name=%s\n", format_name);
+
+            // Check for ASF format (WMA files use ASF container)
+            // Also check for "asf_o" which is the output variant
+            int is_asf_format = (ic->iformat && ic->iformat->name &&
+                                 (strcmp(ic->iformat->name, "asf") == 0 ||
+                                  strcmp(ic->iformat->name, "asf_o") == 0 ||
+                                  strstr(ic->iformat->name, "asf") != NULL));
 
-            // Fallback for ASF format: if seek failed, try with audio stream index
-            if (ret < 0 && is_asf_format && is->audio_stream >= 0) {
-                av_log(ffp, AV_LOG_WARNING, "ASF seek failed, trying fallback with audio stream index\n");
-                // Convert seek_target from AV_TIME_BASE to audio stream time_base
-                int64_t seek_ts = av_rescale_q(seek_target, AV_TIME_BASE_Q, is->audio_st->time_base);
-                ret = av_seek_frame(is->ic, is->audio_stream, seek_ts, seek_flags | AVSEEK_FLAG_ANY);
+            if (is_asf_format) {
+                // ASF/WMA format: use alternative seek method to avoid ff_seek_frame_binary crash
+                // The crash occurs because ff_seek_frame_binary has uninitialized pos_min/pos_max
+                // Try using AVSEEK_FLAG_BYTE to force byte-based seeking instead of timestamp-based
+                av_log(ffp, AV_LOG_WARNING, "heanup: ASF format, trying byte-based seek\n");
+
+                // Calculate byte position based on duration and file size
+                int64_t file_size = avio_size(ic->pb);
+                int64_t duration = ic->duration;
+
+                if (file_size > 0 && duration > 0) {
+                    // Convert seek_target (in AV_TIME_BASE) to byte position
+                    int64_t byte_pos = av_rescale(seek_target, file_size, duration);
+                    av_log(ffp, AV_LOG_WARNING, "heanup: ASF byte seek: target=%lld, file_size=%lld, duration=%lld, byte_pos=%lld\n",
+                           (long long)seek_target, (long long)file_size, (long long)duration, (long long)byte_pos);
+
+                    // Use av_seek_frame with AVSEEK_FLAG_BYTE for byte-based seeking
+                    ret = av_seek_frame(ic, -1, byte_pos, AVSEEK_FLAG_BYTE | AVSEEK_FLAG_BACKWARD);
+
+                    if (ret < 0) {
+                        av_log(ffp, AV_LOG_WARNING, "heanup: ASF byte seek failed, ret=%d\n", ret);
+                    }
+                } else {
+                    av_log(ffp, AV_LOG_WARNING, "heanup: ASF cannot calculate byte position, file_size=%lld, duration=%lld\n",
+                           (long long)file_size, (long long)duration);
+                    ret = -1;
+                }
+                // Don't continue here - let the code below handle flush if seek succeeded
+            } else {
+                // Normal format: use avformat_seek_file
+                ret = avformat_seek_file(is->ic, -1, seek_min, seek_target, seek_max, seek_flags);
             }
 
             if (ret < 0) {