使用FFMPEG在Android上进行HLS播放问题

时间:2014-02-03 10:55:44

标签: android ffmpeg http-live-streaming

我正在使用由AppUnite构建的FFMPEG和最新的stagefright支持补丁来播放http直播流:https://review.appunite.com/#/c/1779/

由于流未从0开始,我添加了以下代码以避免出现黑屏:

struct Player {
   + int64_t video_start_time;
}

void player_get_video_duration(struct Player *player) {
+ player->video_start_time = 0;

+ for (i = 0; i < player->capture_streams_no; ++i) {
+    AVStream *stream = player->input_streams[i];
+       if (stream->start_time > 0) {
+          player->video_start_time = av_rescale_q(
+             stream->start_time, stream->time_base, AV_TIME_BASE_Q);
+
+          LOGI(3, "player_set_data_source stream[%d] start_time: %ld",
+             i, player->video_start_time);
+
+           break;
+       }
+   }
}

enum WaitFuncRet player_wait_for_frame(
   struct Player *player, double time, int stream_no) {
- int64_t current_time = av_gettime();
+ int64_t current_time = av_gettime() + player->video_start_time; 
}

但是,只要player_wait_for_frame中的sleep_time低于0,播放就会冻结,然后挂起等待永不到来的帧。由player_alloc_queues函数分配的队列似乎不够大,无法容纳在player_open_input和player_start_decoding_threads之间推送的实时流。但是,增加队列中的节点数并不能解决问题。问题似乎在player_wait_for_frame方法中很明显,但我无法找到解决方案。

我花了很多时间试图解决这个令人讨厌的问题,但到目前为止还没有成功。任何帮助真的很感激!!!

1 个答案:

答案 0 :(得分:0)

我使用该库时遇到了同样的问题。在我的情况下,我试图播放通过网络转发的DVB流。流是有效的,有时(由于网络问题或其他原因)某些数据包可能会丢失或损坏,并且库停止播放。

为了让它正常工作,除了&#34;视频开始时间修复&#34;之外,我还做了其他2个修复。 (帖子中的补丁)。

第一个是在解码失败时禁用&#34;停止流&#34;:

@@ -1112,7 +1127,7 @@
            av_free_packet(packet_data->packet);
        }
        queue_pop_finish(queue, &player->mutex_queue, &player->cond_queue);
-       if (err < 0) {
+       if (!player->is_live_stream && err < 0) {
            pthread_mutex_lock(&player->mutex_queue);
            goto stop;
        }

第二个是对太晚到达的帧禁用PTS调整(在直播中我们必须删除它们):

@@ -738,7 +741,19 @@
                "player_wait_for_frame[%d] Waiting for frame: sleeping: %" SCNd64,
                stream_no, sleep_time);

-       if (sleep_time < -300000ll) {
+       if (player->is_live_stream && sleep_time < -1000000ll) {
+           // 1000 ms late
+           int64_t new_value = player->start_time - sleep_time;
+
+           LOGI(4,
+                   "player_wait_for_frame[%d] skipping frame because too late",
+                   stream_no);
+
+           ret = WAIT_FUNC_RET_SKIP;
+           break;
+       }
+
+        if (sleep_time < -300000ll) {
            // 300 ms late
            int64_t new_value = player->start_time - sleep_time;

&#34;播放器 - &gt; is_live_stream&#34;是一个int 0/1,当我正在播放实时流时我设置为1,所以对于其他类型的源,该库仍然像以前一样工作。

希望这可以帮助你:)