未验证 提交 30eb9441 编写于 作者: R raymond1012 提交者: GitHub

Merge pull request #5249 from bupt-steven/wenjun/abr

add ijklas demuxer & remove las features away from ijkplayer
...@@ -256,7 +256,7 @@ public class IjkVideoView extends FrameLayout implements MediaController.MediaPl ...@@ -256,7 +256,7 @@ public class IjkVideoView extends FrameLayout implements MediaController.MediaPl
public void setVideoPath(String path) { public void setVideoPath(String path) {
if (path.contains("adaptationSet")){ if (path.contains("adaptationSet")){
mManifestString = path; mManifestString = path;
setVideoURI(Uri.EMPTY); setVideoURI(Uri.parse("ijklas:"));
} else { } else {
setVideoURI(Uri.parse(path)); setVideoURI(Uri.parse(path));
} }
...@@ -1044,7 +1044,8 @@ public class IjkVideoView extends FrameLayout implements MediaController.MediaPl ...@@ -1044,7 +1044,8 @@ public class IjkVideoView extends FrameLayout implements MediaController.MediaPl
ijkMediaPlayer.native_setLogLevel(IjkMediaPlayer.IJK_LOG_DEBUG); ijkMediaPlayer.native_setLogLevel(IjkMediaPlayer.IJK_LOG_DEBUG);
if (mManifestString != null) { if (mManifestString != null) {
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "is-manifest", 1); ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "iformat", "ijklas");
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "find_stream_info", 0);
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "manifest_string", mManifestString); ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "manifest_string", mManifestString);
} }
if (mSettings.getUsingMediaCodec()) { if (mSettings.getUsingMediaCodec()) {
......
...@@ -48,7 +48,6 @@ ...@@ -48,7 +48,6 @@
#include "libavutil/avassert.h" #include "libavutil/avassert.h"
#include "libavutil/time.h" #include "libavutil/time.h"
#include "libavformat/avformat.h" #include "libavformat/avformat.h"
#include "ijkavformat/ijklas.h"
#if CONFIG_AVDEVICE #if CONFIG_AVDEVICE
#include "libavdevice/avdevice.h" #include "libavdevice/avdevice.h"
#endif #endif
...@@ -3117,13 +3116,9 @@ static int read_thread(void *arg) ...@@ -3117,13 +3116,9 @@ static int read_thread(void *arg)
if (ffp->iformat_name) if (ffp->iformat_name)
is->iformat = av_find_input_format(ffp->iformat_name); is->iformat = av_find_input_format(ffp->iformat_name);
if (ffp->is_manifest) { av_dict_set_intptr(&ffp->format_opts, "video_cache_ptr", (intptr_t)&ffp->stat.video_cache, 0);
extern AVInputFormat ijkff_las_demuxer; av_dict_set_intptr(&ffp->format_opts, "audio_cache_ptr", (intptr_t)&ffp->stat.audio_cache, 0);
is->iformat = &ijkff_las_demuxer;
av_dict_set_int(&ffp->format_opts, "las_player_statistic", (intptr_t) (&ffp->las_player_statistic), 0);
ffp->find_stream_info = false;
}
err = avformat_open_input(&ic, is->filename, is->iformat, &ffp->format_opts); err = avformat_open_input(&ic, is->filename, is->iformat, &ffp->format_opts);
if (err < 0) { if (err < 0) {
print_error(is->filename, err); print_error(is->filename, err);
...@@ -4001,8 +3996,6 @@ FFPlayer *ffp_create() ...@@ -4001,8 +3996,6 @@ FFPlayer *ffp_create()
ffp->meta = ijkmeta_create(); ffp->meta = ijkmeta_create();
av_opt_set_defaults(ffp); av_opt_set_defaults(ffp);
las_stat_init(&ffp->las_player_statistic);
return ffp; return ffp;
} }
...@@ -4022,7 +4015,6 @@ void ffp_destroy(FFPlayer *ffp) ...@@ -4022,7 +4015,6 @@ void ffp_destroy(FFPlayer *ffp)
ffpipenode_free_p(&ffp->node_vdec); ffpipenode_free_p(&ffp->node_vdec);
ffpipeline_free_p(&ffp->pipeline); ffpipeline_free_p(&ffp->pipeline);
ijkmeta_destroy_p(&ffp->meta); ijkmeta_destroy_p(&ffp->meta);
las_stat_destroy(&ffp->las_player_statistic);
ffp_reset_internal(ffp); ffp_reset_internal(ffp);
SDL_DestroyMutexP(&ffp->af_mutex); SDL_DestroyMutexP(&ffp->af_mutex);
...@@ -4637,18 +4629,12 @@ void ffp_audio_statistic_l(FFPlayer *ffp) ...@@ -4637,18 +4629,12 @@ void ffp_audio_statistic_l(FFPlayer *ffp)
{ {
VideoState *is = ffp->is; VideoState *is = ffp->is;
ffp_track_statistic_l(ffp, is->audio_st, &is->audioq, &ffp->stat.audio_cache); ffp_track_statistic_l(ffp, is->audio_st, &is->audioq, &ffp->stat.audio_cache);
if (ffp->is_manifest) {
las_set_audio_cached_duration_ms(&ffp->las_player_statistic, ffp->stat.audio_cache.duration);
}
} }
void ffp_video_statistic_l(FFPlayer *ffp) void ffp_video_statistic_l(FFPlayer *ffp)
{ {
VideoState *is = ffp->is; VideoState *is = ffp->is;
ffp_track_statistic_l(ffp, is->video_st, &is->videoq, &ffp->stat.video_cache); ffp_track_statistic_l(ffp, is->video_st, &is->videoq, &ffp->stat.video_cache);
if (ffp->is_manifest) {
las_set_video_cached_duration_ms(&ffp->las_player_statistic, ffp->stat.video_cache.duration);
}
} }
void ffp_statistic_l(FFPlayer *ffp) void ffp_statistic_l(FFPlayer *ffp)
......
...@@ -65,7 +65,6 @@ ...@@ -65,7 +65,6 @@
#include "ff_ffmsg_queue.h" #include "ff_ffmsg_queue.h"
#include "ff_ffpipenode.h" #include "ff_ffpipenode.h"
#include "ijkmeta.h" #include "ijkmeta.h"
#include "ijkavformat/ijklas.h"
#define DEFAULT_HIGH_WATER_MARK_IN_BYTES (256 * 1024) #define DEFAULT_HIGH_WATER_MARK_IN_BYTES (256 * 1024)
...@@ -721,8 +720,6 @@ typedef struct FFPlayer { ...@@ -721,8 +720,6 @@ typedef struct FFPlayer {
char *mediacodec_default_name; char *mediacodec_default_name;
int ijkmeta_delay_init; int ijkmeta_delay_init;
int render_wait_start; int render_wait_start;
int is_manifest;
LasPlayerStatistic las_player_statistic;
} FFPlayer; } FFPlayer;
#define fftime_to_milliseconds(ts) (av_rescale(ts, 1000, AV_TIME_BASE)) #define fftime_to_milliseconds(ts) (av_rescale(ts, 1000, AV_TIME_BASE))
...@@ -833,7 +830,6 @@ inline static void ffp_reset_internal(FFPlayer *ffp) ...@@ -833,7 +830,6 @@ inline static void ffp_reset_internal(FFPlayer *ffp)
ffp->mediacodec_default_name = NULL; // option ffp->mediacodec_default_name = NULL; // option
ffp->ijkmeta_delay_init = 0; // option ffp->ijkmeta_delay_init = 0; // option
ffp->render_wait_start = 0; ffp->render_wait_start = 0;
ffp->is_manifest = 0;
ijkmeta_reset(ffp->meta); ijkmeta_reset(ffp->meta);
......
...@@ -206,9 +206,6 @@ static const AVOption ffp_context_options[] = { ...@@ -206,9 +206,6 @@ static const AVOption ffp_context_options[] = {
OPTION_OFFSET(ijkmeta_delay_init), OPTION_INT(0, 0, 1) }, OPTION_OFFSET(ijkmeta_delay_init), OPTION_INT(0, 0, 1) },
{ "render-wait-start", "render wait start", { "render-wait-start", "render wait start",
OPTION_OFFSET(render_wait_start), OPTION_INT(0, 0, 1) }, OPTION_OFFSET(render_wait_start), OPTION_INT(0, 0, 1) },
{ "is-manifest", "is manifest string",
OPTION_OFFSET(is_manifest), OPTION_INT(0, 0, 1) },
{ NULL } { NULL }
}; };
......
...@@ -87,5 +87,6 @@ void ijkav_register_all(void) ...@@ -87,5 +87,6 @@ void ijkav_register_all(void)
IJK_REGISTER_PROTOCOL(ijksegment); IJK_REGISTER_PROTOCOL(ijksegment);
/* demuxers */ /* demuxers */
IJK_REGISTER_DEMUXER(ijklivehook); IJK_REGISTER_DEMUXER(ijklivehook);
IJK_REGISTER_DEMUXER(ijklas);
av_log(NULL, AV_LOG_INFO, "===== custom modules end =====\n"); av_log(NULL, AV_LOG_INFO, "===== custom modules end =====\n");
} }
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include "ijksdl/ijksdl_thread.h" #include "ijksdl/ijksdl_thread.h"
#include "ijksdl/ijksdl_mutex.h" #include "ijksdl/ijksdl_mutex.h"
#include "cJSON.h" #include "cJSON.h"
#include "ff_ffplay_def.h"
#include "ijklas.h" #include "ijklas.h"
...@@ -184,10 +185,11 @@ typedef struct PlayList { ...@@ -184,10 +185,11 @@ typedef struct PlayList {
// cur playlist Qos // cur playlist Qos
LasStatistic* las_statistic; LasStatistic* las_statistic;
LasPlayerStatistic* las_player_statistic;
bool is_stream_ever_opened; bool is_stream_ever_opened;
int64_t bytes_read; int64_t bytes_read;
unsigned session_id; unsigned session_id;
FFTrackCacheStatistic* video_cache;
FFTrackCacheStatistic* audio_cache;
} PlayList; } PlayList;
typedef struct LasContext { typedef struct LasContext {
...@@ -204,13 +206,21 @@ typedef struct LasContext { ...@@ -204,13 +206,21 @@ typedef struct LasContext {
char* manifest_string; char* manifest_string;
int64_t network; int64_t network;
char* abr_history_data; char* abr_history_data;
int64_t las_player_statistic;
char* live_adapt_config; char* live_adapt_config;
AVDictionary* avio_opts; AVDictionary* avio_opts;
// all info of las is in it // all info of las is in it
PlayList playlist; PlayList playlist;
LasStatistic las_statistic;
unsigned session_id; unsigned session_id;
int64_t video_cache_ptr;
int64_t audio_cache_ptr;
int las_switch_mode;
int64_t first_audio_packet_pts;
int block_duration;
int audio_only_request;
int audio_only_response;
bool stream_reopened;
} LasContext; } LasContext;
#pragma mark common util #pragma mark common util
...@@ -242,128 +252,38 @@ static inline void _log(unsigned session_id, const char* func_name, int av_log_l ...@@ -242,128 +252,38 @@ static inline void _log(unsigned session_id, const char* func_name, int av_log_l
#define algo_error(...) log_debug_tag(thiz->session_id, AV_LOG_ERROR, __VA_ARGS__) #define algo_error(...) log_debug_tag(thiz->session_id, AV_LOG_ERROR, __VA_ARGS__)
#pragma mark PlayerControl #pragma mark PlayerControl
int las_stat_init(LasPlayerStatistic* stat) { int get_switch_mode(AVFormatContext* format) {
memset(stat, 0, sizeof(LasPlayerStatistic)); LasContext* c = format->priv_data;
stat->las_switch_mode = LAS_AUTO_MODE; return c->las_switch_mode;
return pthread_mutex_init(&stat->control_mutex, NULL);
} }
void las_stat_destroy(LasPlayerStatistic* stat) { int64_t get_first_audio_packet_pts(AVFormatContext* format) {
pthread_mutex_destroy(&stat->control_mutex); LasContext* c = format->priv_data;
return c->first_audio_packet_pts;
} }
int las_get_switch_mode(LasPlayerStatistic* stat) { int get_audio_only_request(AVFormatContext* format) {
pthread_mutex_lock(&stat->control_mutex); LasContext* c = format->priv_data;
int switch_mode = stat->las_switch_mode; return c->audio_only_request;
pthread_mutex_unlock(&stat->control_mutex);
return switch_mode;
} }
void las_set_switch_mode(LasPlayerStatistic* stat, int switch_mode) { void set_audio_only_response(AVFormatContext* format, int audio_only) {
pthread_mutex_lock(&stat->control_mutex); LasContext* c = format->priv_data;
stat->las_switch_mode = switch_mode; c->audio_only_response = audio_only;
pthread_mutex_unlock(&stat->control_mutex);
} }
int64_t las_get_first_audio_packet_pts(LasPlayerStatistic* stat) { void set_stream_reopened(AVFormatContext* format, bool stream_reopened) {
pthread_mutex_lock(&stat->control_mutex); LasContext* c = format->priv_data;
int64_t ret = stat->first_audio_packet_pts; c->stream_reopened = stream_reopened;
pthread_mutex_unlock(&stat->control_mutex);
return ret;
}
void las_set_first_audio_packet_pts(LasPlayerStatistic* stat, int64_t first_audio_packet_pts) {
pthread_mutex_lock(&stat->control_mutex);
stat->first_audio_packet_pts = first_audio_packet_pts;
pthread_mutex_unlock(&stat->control_mutex);
}
int las_get_audio_only_request(LasPlayerStatistic* stat) {
pthread_mutex_lock(&stat->control_mutex);
int ret = stat->audio_only_request;
pthread_mutex_unlock(&stat->control_mutex);
return ret;
}
void las_set_audio_only_request(LasPlayerStatistic* stat, int audio_only) {
pthread_mutex_lock(&stat->control_mutex);
stat->audio_only_request = audio_only;
pthread_mutex_unlock(&stat->control_mutex);
}
int las_get_audio_only_response(LasPlayerStatistic* stat) {
pthread_mutex_lock(&stat->control_mutex);
int ret = stat->audio_only_response;
pthread_mutex_unlock(&stat->control_mutex);
return ret;
}
void las_set_audio_only_response(LasPlayerStatistic* stat, int audio_only) {
pthread_mutex_lock(&stat->control_mutex);
stat->audio_only_response = audio_only;
pthread_mutex_unlock(&stat->control_mutex);
}
int64_t las_get_audio_cached_duration_ms(LasPlayerStatistic* stat) {
pthread_mutex_lock(&stat->control_mutex);
int64_t ret = stat->audio_cached_duration_ms;
pthread_mutex_unlock(&stat->control_mutex);
return ret;
}
void las_set_audio_cached_duration_ms(LasPlayerStatistic* stat, int64_t audio_cached_duration_ms) {
pthread_mutex_lock(&stat->control_mutex);
stat->audio_cached_duration_ms = audio_cached_duration_ms;
pthread_mutex_unlock(&stat->control_mutex);
}
int64_t las_get_video_cached_duration_ms(LasPlayerStatistic* stat) {
pthread_mutex_lock(&stat->control_mutex);
int64_t ret = stat->video_cached_duration_ms;
pthread_mutex_unlock(&stat->control_mutex);
return ret;
}
void las_set_video_cached_duration_ms(LasPlayerStatistic* stat, int64_t video_cached_duration_ms) {
pthread_mutex_lock(&stat->control_mutex);
stat->video_cached_duration_ms = video_cached_duration_ms;
pthread_mutex_unlock(&stat->control_mutex);
}
bool las_get_stream_reopened(LasPlayerStatistic* stat) {
pthread_mutex_lock(&stat->control_mutex);
bool ret = stat->stream_reopened;
pthread_mutex_unlock(&stat->control_mutex);
return ret;
}
void las_set_stream_reopened(LasPlayerStatistic* stat, bool stream_reopened) {
pthread_mutex_lock(&stat->control_mutex);
stat->stream_reopened = stream_reopened;
pthread_mutex_unlock(&stat->control_mutex);
} }
#pragma mark PlayerStat int64_t get_cache_duration_ms(FFTrackCacheStatistic* cache) {
int32_t LasPlayerStatistic_get_downloading_bitrate(LasPlayerStatistic* stat) { if (cache) {
if (stat->las_stat.bitrate_downloading > 0) { return cache->duration;
return stat->las_stat.bitrate_downloading;
} }
return 0; return 0;
} }
char* LasPlayerStatistic_get_downloading_url(LasPlayerStatistic* stat) {
return stat->las_stat.cur_playing_url;
}
int LasPlayerStatistic_get_http_reading_error(LasPlayerStatistic* stat) {
if (stat->las_stat.cur_rep_http_reading_error != 0) {
return stat->las_stat.cur_rep_http_reading_error;
} else {
return 0;
}
}
#pragma mark PlayListLock #pragma mark PlayListLock
static int64_t get_bytes_read(PlayList* p) { static int64_t get_bytes_read(PlayList* p) {
SDL_LockMutex(p->las_mutex); SDL_LockMutex(p->las_mutex);
...@@ -692,8 +612,8 @@ void LasStatistic_on_read_packet(LasStatistic* stat, PlayList* playlist) { ...@@ -692,8 +612,8 @@ void LasStatistic_on_read_packet(LasStatistic* stat, PlayList* playlist) {
void LasStatistic_on_buffer_time(LasStatistic* stat, PlayList* playlist) { void LasStatistic_on_buffer_time(LasStatistic* stat, PlayList* playlist) {
if (stat && playlist) { if (stat && playlist) {
stat->cached_a_dur_ms = las_get_audio_cached_duration_ms(playlist->las_player_statistic); stat->cached_a_dur_ms = get_cache_duration_ms(playlist->audio_cache);
stat->cached_v_dur_ms = las_get_video_cached_duration_ms(playlist->las_player_statistic); stat->cached_v_dur_ms = get_cache_duration_ms(playlist->video_cache);;
stat->cached_tag_dur_ms = TagQueue_get_duration_ms(&playlist->tag_queue); stat->cached_tag_dur_ms = TagQueue_get_duration_ms(&playlist->tag_queue);
log_info("a_buffer_time_ms=%lld, v_buffer_time_ms=%lld, CachedTagQueue_ms=%lld", log_info("a_buffer_time_ms=%lld, v_buffer_time_ms=%lld, CachedTagQueue_ms=%lld",
stat->cached_a_dur_ms, stat->cached_v_dur_ms, stat->cached_tag_dur_ms); stat->cached_a_dur_ms, stat->cached_v_dur_ms, stat->cached_tag_dur_ms);
...@@ -724,8 +644,8 @@ void LasStatistic_on_bandwidth_update(PlayList* playlist, MultiRateAdaption* ada ...@@ -724,8 +644,8 @@ void LasStatistic_on_bandwidth_update(PlayList* playlist, MultiRateAdaption* ada
void LasStatistic_on_rep_switch_count(LasStatistic* stat, PlayList* playlist) { void LasStatistic_on_rep_switch_count(LasStatistic* stat, PlayList* playlist) {
if (stat) { if (stat) {
stat->rep_switch_cnt++; stat->rep_switch_cnt++;
stat->switch_point_a_buffer_ms = las_get_audio_cached_duration_ms(playlist->las_player_statistic); stat->switch_point_a_buffer_ms = get_cache_duration_ms(playlist->audio_cache);
stat->switch_point_v_buffer_ms = las_get_video_cached_duration_ms(playlist->las_player_statistic); stat->switch_point_v_buffer_ms = get_cache_duration_ms(playlist->video_cache);
} }
} }
...@@ -819,7 +739,7 @@ void MultiRateAdaption_init(MultiRateAdaption* thiz, AdaptiveConfig config, ...@@ -819,7 +739,7 @@ void MultiRateAdaption_init(MultiRateAdaption* thiz, AdaptiveConfig config,
thiz->current -= 1; thiz->current -= 1;
} }
int switch_mode = las_get_switch_mode(playlist->las_player_statistic); int switch_mode = get_switch_mode(playlist->outermost_ctx);
if (switch_mode >= 0 && switch_mode < thiz->n_bitrates) { if (switch_mode >= 0 && switch_mode < thiz->n_bitrates) {
thiz->current = rep_index_2_local_index(thiz, switch_mode); thiz->current = rep_index_2_local_index(thiz, switch_mode);
} }
...@@ -858,7 +778,7 @@ bool update_stable_buffer(MultiRateAdaption* thiz, double buffered) { ...@@ -858,7 +778,7 @@ bool update_stable_buffer(MultiRateAdaption* thiz, double buffered) {
* check buffer periodically * check buffer periodically
*/ */
void check_buffer(MultiRateAdaption* thiz, PlayList* playlist) { void check_buffer(MultiRateAdaption* thiz, PlayList* playlist) {
double buffered = las_get_audio_cached_duration_ms(playlist->las_player_statistic) / 1000.0; double buffered = get_cache_duration_ms(playlist->audio_cache) / 1000.0;
bool is_buffer_stable = update_stable_buffer(thiz, buffered); bool is_buffer_stable = update_stable_buffer(thiz, buffered);
if (is_buffer_stable && thiz->current + 1 < thiz->n_bitrates) { if (is_buffer_stable && thiz->current + 1 < thiz->n_bitrates) {
thiz->generated_speed = thiz->levels[thiz->current + 1]; thiz->generated_speed = thiz->levels[thiz->current + 1];
...@@ -919,12 +839,16 @@ bool is_speed_enough(MultiRateAdaption* thiz, double speed) { ...@@ -919,12 +839,16 @@ bool is_speed_enough(MultiRateAdaption* thiz, double speed) {
} }
int32_t next_local_rate_index(MultiRateAdaption* thiz, double speed, double buffered) { int32_t next_local_rate_index(MultiRateAdaption* thiz, double speed, double buffered) {
if (thiz->buffer_index <= 1 && buffered <= 0.1) {
algo_info("empty past buffer");
return thiz->current;
}
double buffer_speed = get_buffer_speed(thiz, buffered); double buffer_speed = get_buffer_speed(thiz, buffered);
double smoothed_speed = get_smoothed_speed(thiz, speed); double smoothed_speed = get_smoothed_speed(thiz, speed);
algo_info("gop_speed: %.0f, smoothed_speed: %.0f", speed, smoothed_speed); algo_info("gop_speed: %.0f, smoothed_speed: %.0f", speed, smoothed_speed);
double predicted_buffered = get_predicted_buffer(thiz, buffered); double predicted_buffered = get_predicted_buffer(thiz, buffered);
algo_info("s: %.0f, predicted_buffered: %.1f", buffer_speed, predicted_buffered); algo_info("buffer_speed: %.0f, buffered: %.1f, predicted_buffered: %.1f", buffer_speed, buffered, predicted_buffered);
int32_t next_index = thiz->current; int32_t next_index = thiz->current;
if (predicted_buffered < thiz->conf.buffer_lower_limit_second if (predicted_buffered < thiz->conf.buffer_lower_limit_second
...@@ -1189,10 +1113,10 @@ int64_t GopReader_download_gop(GopReader* reader, MultiRateAdaption* adaption, P ...@@ -1189,10 +1113,10 @@ int64_t GopReader_download_gop(GopReader* reader, MultiRateAdaption* adaption, P
return ret; return ret;
} }
int request = las_get_audio_only_request(playlist->las_player_statistic); int request = get_audio_only_request(playlist->outermost_ctx);
if (reader->is_audio_only != request) { if (reader->is_audio_only != request) {
reader->is_audio_only = request; reader->is_audio_only = request;
int64_t current_playing_audio_ts = las_get_first_audio_packet_pts(playlist->las_player_statistic); int64_t current_playing_audio_ts = get_first_audio_packet_pts(playlist->outermost_ctx);
log_info("current_playing_audio_ts: %lld", current_playing_audio_ts); log_info("current_playing_audio_ts: %lld", current_playing_audio_ts);
int64_t request_ts = current_playing_audio_ts - playlist->adaptation_set.duration / 2; int64_t request_ts = current_playing_audio_ts - playlist->adaptation_set.duration / 2;
reader->last_gop_start_ts = request_ts > 0 ? request_ts : 0; reader->last_gop_start_ts = request_ts > 0 ? request_ts : 0;
...@@ -1225,9 +1149,9 @@ int64_t GopReader_download_gop(GopReader* reader, MultiRateAdaption* adaption, P ...@@ -1225,9 +1149,9 @@ int64_t GopReader_download_gop(GopReader* reader, MultiRateAdaption* adaption, P
adaption->next_expected_rep_index = next_representation_id( adaption->next_expected_rep_index = next_representation_id(
adaption, adaption,
las_get_switch_mode(playlist->las_player_statistic), get_switch_mode(playlist->outermost_ctx),
speed, speed,
las_get_audio_cached_duration_ms(playlist->las_player_statistic) / 1000.0); get_cache_duration_ms(playlist->audio_cache) / 1000.0);
if (reader->rep_index != adaption->next_expected_rep_index) { if (reader->rep_index != adaption->next_expected_rep_index) {
LasStatistic_on_adaption_adapted(playlist, adaption); LasStatistic_on_adaption_adapted(playlist, adaption);
LasStatistic_on_rep_switch_count(playlist->las_statistic, playlist); LasStatistic_on_rep_switch_count(playlist->las_statistic, playlist);
...@@ -1505,7 +1429,7 @@ int PlayList_open_rep(PlayList* playlist, FlvTag* tag, AVFormatContext* s) { ...@@ -1505,7 +1429,7 @@ int PlayList_open_rep(PlayList* playlist, FlvTag* tag, AVFormatContext* s) {
} }
playlist->is_stream_ever_opened = true; playlist->is_stream_ever_opened = true;
} else { } else {
las_set_stream_reopened(playlist->las_player_statistic, true); set_stream_reopened(playlist->outermost_ctx, true);
} }
for (int j = 0; j < playlist->ctx->nb_streams && j < MAX_STREAM_NUM; j++) { for (int j = 0; j < playlist->ctx->nb_streams && j < MAX_STREAM_NUM; j++) {
...@@ -1520,7 +1444,7 @@ int PlayList_open_rep(PlayList* playlist, FlvTag* tag, AVFormatContext* s) { ...@@ -1520,7 +1444,7 @@ int PlayList_open_rep(PlayList* playlist, FlvTag* tag, AVFormatContext* s) {
} }
playlist->cur_rep_index = tag->rep_index; playlist->cur_rep_index = tag->rep_index;
las_set_audio_only_response(playlist->las_player_statistic, tag->audio_only); set_audio_only_response(playlist->outermost_ctx, tag->audio_only);
log_info("open_index:%d, audio_only:%d finished", tag->rep_index, tag->audio_only); log_info("open_index:%d, audio_only:%d finished", tag->rep_index, tag->audio_only);
return 0; return 0;
...@@ -1763,7 +1687,6 @@ int parse_root(char* file_name, PlayList* c) { ...@@ -1763,7 +1687,6 @@ int parse_root(char* file_name, PlayList* c) {
} }
int parse_adapt_config(char* config_string, AdaptiveConfig* config, PlayList* playlist) { int parse_adapt_config(char* config_string, AdaptiveConfig* config, PlayList* playlist) {
LasPlayerStatistic* player_stat = playlist->las_player_statistic;
cJSON* root = cJSON_Parse(config_string); cJSON* root = cJSON_Parse(config_string);
if (!root) if (!root)
return LAS_ERROR_ADAPT_CONFIG_JSON; return LAS_ERROR_ADAPT_CONFIG_JSON;
...@@ -1835,7 +1758,7 @@ static int las_close(AVFormatContext* s) { ...@@ -1835,7 +1758,7 @@ static int las_close(AVFormatContext* s) {
} }
static int las_probe(AVProbeData* p) { static int las_probe(AVProbeData* p) {
if (p->filename && strstr(p->filename, ".las")) if (p->filename && av_strstart(p->filename, "ijklas:", NULL))
return AVPROBE_SCORE_MAX; return AVPROBE_SCORE_MAX;
return 0; return 0;
...@@ -1861,20 +1784,19 @@ static int las_read_header(AVFormatContext* s) { ...@@ -1861,20 +1784,19 @@ static int las_read_header(AVFormatContext* s) {
playlist->session_id = c->session_id; playlist->session_id = c->session_id;
av_dict_set(&c->avio_opts, "timeout", "10000000", 0); av_dict_set(&c->avio_opts, "timeout", "10000000", 0);
if ((ret = parse_root(c->manifest_string, playlist)) < 0) { if ((ret = parse_root(c->manifest_string, playlist)) < 0) {
log_error("Illegal manifest Json String"); log_error("Illegal manifest Json String");
goto fail; goto fail;
} }
log_info("Finish parsing las manifest (player)"); log_info("Finish parsing las manifest, switch_mode:%d", c->las_switch_mode);
playlist->las_player_statistic = (LasPlayerStatistic*)c->las_player_statistic; if (c->audio_cache_ptr && c->video_cache_ptr) {
if (playlist->las_player_statistic) { playlist->video_cache = (FFTrackCacheStatistic*)c->video_cache_ptr;
playlist->las_statistic = &playlist->las_player_statistic->las_stat; playlist->audio_cache = (FFTrackCacheStatistic*)c->audio_cache_ptr;
log_info("playlist->stat: %p, las_statistic: %p", playlist->las_player_statistic, playlist->las_statistic);
} else { } else {
log_error("las_player_statistic is null"); log_error("FFTrackCacheStatistic is null");
goto fail; goto fail;
} }
playlist->las_statistic = &c->las_statistic;
LasStatistic_init(playlist->las_statistic, playlist); LasStatistic_init(playlist->las_statistic, playlist);
RateAdaptConfig_default_init(&config, playlist); RateAdaptConfig_default_init(&config, playlist);
...@@ -2089,10 +2011,6 @@ static const AVOption las_options[] = { ...@@ -2089,10 +2011,6 @@ static const AVOption las_options[] = {
"device-network-type", "device-network-type", "device-network-type", "device-network-type",
OFFSET(network), AV_OPT_TYPE_INT64, {.i64 = 0}, 0, INT64_MAX, FLAGS OFFSET(network), AV_OPT_TYPE_INT64, {.i64 = 0}, 0, INT64_MAX, FLAGS
}, },
{
"las_player_statistic", "las_player_statistic",
OFFSET(las_player_statistic), AV_OPT_TYPE_INT64, {.i64 = 0}, INT64_MIN, INT64_MAX, FLAGS
},
{ {
"liveAdaptConfig", "liveAdaptConfig", "liveAdaptConfig", "liveAdaptConfig",
OFFSET(live_adapt_config), AV_OPT_TYPE_STRING, { .str = NULL }, CHAR_MIN, CHAR_MAX, FLAGS OFFSET(live_adapt_config), AV_OPT_TYPE_STRING, { .str = NULL }, CHAR_MIN, CHAR_MAX, FLAGS
...@@ -2101,20 +2019,52 @@ static const AVOption las_options[] = { ...@@ -2101,20 +2019,52 @@ static const AVOption las_options[] = {
"session_id", "session_id", "session_id", "session_id",
OFFSET(session_id), AV_OPT_TYPE_INT, {.i64 = 0}, INT32_MIN, INT32_MAX, FLAGS OFFSET(session_id), AV_OPT_TYPE_INT, {.i64 = 0}, INT32_MIN, INT32_MAX, FLAGS
}, },
{
"video_cache_ptr", "video_cache_ptr",
OFFSET(video_cache_ptr), AV_OPT_TYPE_INT64, {.i64 = 0}, INT64_MIN, INT64_MAX, FLAGS
},
{
"audio_cache_ptr", "audio_cache_ptr",
OFFSET(audio_cache_ptr), AV_OPT_TYPE_INT64, {.i64 = 0}, INT64_MIN, INT64_MAX, FLAGS
},
{
"las_switch_mode", "las_switch_mode",
OFFSET(las_switch_mode), AV_OPT_TYPE_INT, {.i64 = LAS_AUTO_MODE}, INT_MIN, INT_MAX, FLAGS
},
{
"first_audio_packet_pts", "first_audio_packet_pts",
OFFSET(first_audio_packet_pts), AV_OPT_TYPE_INT64, {.i64 = 0}, INT64_MIN, INT64_MAX, FLAGS
},
{
"block_duration", "block_duration",
OFFSET(block_duration), AV_OPT_TYPE_INT, {.i64 = 0}, INT64_MIN, INT64_MAX, FLAGS
},
{
"audio_only_request", "audio_only_request",
OFFSET(audio_only_request), AV_OPT_TYPE_INT, {.i64 = 0}, INT64_MIN, INT64_MAX, FLAGS
},
{
"audio_only_response", "audio_only_response",
OFFSET(audio_only_response), AV_OPT_TYPE_INT, {.i64 = 0}, INT64_MIN, INT64_MAX, FLAGS
},
{
"stream_reopened", "stream_reopened",
OFFSET(stream_reopened), AV_OPT_TYPE_INT, {.i64 = 0}, INT64_MIN, INT64_MAX, FLAGS
},
{NULL} {NULL}
}; };
static const AVClass las_class = { static const AVClass ijklas_class = {
.class_name = "las", .class_name = "las demuxer",
.item_name = av_default_item_name, .item_name = av_default_item_name,
.option = las_options, .option = las_options,
.version = LIBAVUTIL_VERSION_INT, .version = LIBAVUTIL_VERSION_INT,
}; };
AVInputFormat ijkff_las_demuxer = { AVInputFormat ijkff_ijklas_demuxer = {
.name = "las", .name = "ijklas",
.long_name = "Live Adaptive Streaming", .long_name = "Live Adaptive Streaming",
.priv_class = &las_class, .priv_class = &ijklas_class,
.priv_data_size = sizeof(LasContext), .priv_data_size = sizeof(LasContext),
.read_probe = las_probe, .read_probe = las_probe,
.read_header = las_read_header, .read_header = las_read_header,
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
#define MAX_URL_SIZE 4096 #define MAX_URL_SIZE 4096
#define MAX_STREAM_NUM 10 #define MAX_STREAM_NUM 10
#define LAS_AUTO_MODE -1 #define LAS_AUTO_MODE (-1)
typedef struct FlvInfo { typedef struct FlvInfo {
int total_bandwidth_kbps; int total_bandwidth_kbps;
...@@ -46,47 +46,4 @@ typedef struct LasStatistic { ...@@ -46,47 +46,4 @@ typedef struct LasStatistic {
int64_t total_bytes_read; int64_t total_bytes_read;
} LasStatistic; } LasStatistic;
typedef struct LasPlayerStatistic {
pthread_mutex_t control_mutex;
int las_switch_mode;
int64_t first_audio_packet_pts;
int block_duration;
int audio_only_request;
int audio_only_response;
int64_t audio_cached_duration_ms;
int64_t video_cached_duration_ms;
LasStatistic las_stat;
bool stream_reopened;
} LasPlayerStatistic;
int las_stat_init(LasPlayerStatistic* stat);
void las_stat_destroy(LasPlayerStatistic* stat);
int las_get_switch_mode(LasPlayerStatistic* stat);
void las_set_switch_mode(LasPlayerStatistic* stat, int switch_mode);
int64_t las_get_first_audio_packet_pts(LasPlayerStatistic* stat);
void las_set_first_audio_packet_pts(LasPlayerStatistic* stat, int64_t first_audio_packet_pts);
int las_get_audio_only_request(LasPlayerStatistic* stat);
void las_set_audio_only_request(LasPlayerStatistic* stat, int audio_only);
int las_get_audio_only_response(LasPlayerStatistic* stat);
void las_set_audio_only_response(LasPlayerStatistic* stat, int audio_only);
int64_t las_get_audio_cached_duration_ms(LasPlayerStatistic* stat);
void las_set_audio_cached_duration_ms(LasPlayerStatistic* stat, int64_t audio_cached_duration_ms);
int64_t las_get_video_cached_duration_ms(LasPlayerStatistic* stat);
void las_set_video_cached_duration_ms(LasPlayerStatistic* stat, int64_t video_cached_duration_ms);
bool las_get_stream_reopened(LasPlayerStatistic* stat);
void las_set_stream_reopened(LasPlayerStatistic* stat, bool stream_reopened);
int32_t LasPlayerStatistic_get_downloading_bitrate(LasPlayerStatistic* stat);
char* LasPlayerStatistic_get_downloading_url(LasPlayerStatistic* stat);
int LasPlayerStatistic_get_http_reading_error(LasPlayerStatistic* stat);
#endif #endif
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
NSMutableArray *sampleList = [[NSMutableArray alloc] init]; NSMutableArray *sampleList = [[NSMutableArray alloc] init];
[sampleList addObject:@[@"las url", [sampleList addObject:@[@"las url",
@"{\"version\":\"1.0.0\",\"adaptationSet\":[{\"duration\":1000,\"id\":1,\"representation\":[{\"id\":1,\"codec\":\"avc1.64001e,mp4a.40.5\",\"url\":\"http://las-tech.org.cn/kwai/las-test_ld500d.flv\",\"backupUrl\":[],\"host\":\"las-tech.org.cn\",\"maxBitrate\":700,\"width\":640,\"height\":360,\"frameRate\":25,\"qualityType\":\"SMOOTH\",\"qualityTypeName\":\"流畅\",\"hidden\":false,\"disabledFromAdaptive\":false,\"defaultSelected\":false},{\"id\":2,\"codec\":\"avc1.64001f,mp4a.40.5\",\"url\":\"http://las-tech.org.cn/kwai/las-test_sd1000d.flv\",\"backupUrl\":[],\"host\":\"las-tech.org.cn\",\"maxBitrate\":1300,\"width\":960,\"height\":540,\"frameRate\":25,\"qualityType\":\"STANDARD\",\"qualityTypeName\":\"标清\",\"hidden\":false,\"disabledFromAdaptive\":false,\"defaultSelected\":false},{\"id\":3,\"codec\":\"avc1.64001f,mp4a.40.5\",\"url\":\"http://las-tech.org.cn/kwai/las-test.flv\",\"backupUrl\":[],\"host\":\"las-tech.org.cn\",\"maxBitrate\":2300,\"width\":1280,\"height\":720,\"frameRate\":30,\"qualityType\":\"HIGH\",\"qualityTypeName\":\"高清\",\"hidden\":false,\"disabledFromAdaptive\":false,\"defaultSelected\":true}]}]}"]]; @"{\"version\":\"1.0.0\",\"adaptationSet\":[{\"duration\":1000,\"id\":1,\"representation\":[{\"id\":1,\"codec\":\"avc1.64001e,mp4a.40.5\",\"url\":\"http://las-tech.org.cn/kwai/las-test_ld500d.flv\",\"backupUrl\":[],\"host\":\"las-tech.org.cn\",\"maxBitrate\":700,\"width\":640,\"height\":360,\"frameRate\":25,\"qualityType\":\"SMOOTH\",\"qualityTypeName\":\"流畅\",\"hidden\":false,\"disabledFromAdaptive\":false,\"defaultSelected\":false},{\"id\":2,\"codec\":\"avc1.64001f,mp4a.40.5\",\"url\":\"http://las-tech.org.cn/kwai/las-test_sd1000d.flv\",\"backupUrl\":[],\"host\":\"las-tech.org.cn\",\"maxBitrate\":1300,\"width\":960,\"height\":540,\"frameRate\":25,\"qualityType\":\"STANDARD\",\"qualityTypeName\":\"标清\",\"hidden\":false,\"disabledFromAdaptive\":false,\"defaultSelected\":true},{\"id\":3,\"codec\":\"avc1.64001f,mp4a.40.5\",\"url\":\"http://las-tech.org.cn/kwai/las-test.flv\",\"backupUrl\":[],\"host\":\"las-tech.org.cn\",\"maxBitrate\":2300,\"width\":1280,\"height\":720,\"frameRate\":30,\"qualityType\":\"HIGH\",\"qualityTypeName\":\"高清\",\"hidden\":false,\"disabledFromAdaptive\":false,\"defaultSelected\":false}]}]}"]];
[sampleList addObject:@[@"bipbop basic master playlist", [sampleList addObject:@[@"bipbop basic master playlist",
@"http://devimages.apple.com.edgekey.net/streaming/examples/bipbop_4x3/bipbop_4x3_variant.m3u8"]]; @"http://devimages.apple.com.edgekey.net/streaming/examples/bipbop_4x3/bipbop_4x3_variant.m3u8"]];
[sampleList addObject:@[@"bipbop basic 400x300 @ 232 kbps", [sampleList addObject:@[@"bipbop basic 400x300 @ 232 kbps",
......
...@@ -39,11 +39,9 @@ ...@@ -39,11 +39,9 @@
- (instancetype)initWithManifest: (NSString*)manifest_string { - (instancetype)initWithManifest: (NSString*)manifest_string {
self = [self initWithNibName:@"IJKMoviePlayerViewController" bundle:nil]; self = [self initWithNibName:@"IJKMoviePlayerViewController" bundle:nil];
if (self) { if (self) {
NSString *fake_url = @"http://fakeurl_for_manifest"; self.url = [NSURL URLWithString:@"ijklas:"];
NSURL *url = [NSURL URLWithString:fake_url]; self.manifest = manifest_string;
self.url = url;
} }
self.manifest = manifest_string;
return self; return self;
} }
...@@ -87,8 +85,9 @@ ...@@ -87,8 +85,9 @@
IJKFFOptions *options = [IJKFFOptions optionsByDefault]; IJKFFOptions *options = [IJKFFOptions optionsByDefault];
if (self.manifest != nil){ if (self.manifest != nil){
[options setFormatOptionValue:self.manifest forKey:@"manifest_string"]; [options setPlayerOptionValue:@"ijklas" forKey:@"iformat"];
[options setPlayerOptionIntValue:1 forKey:@"is-manifest"]; [options setPlayerOptionIntValue:0 forKey:@"find_stream_info"];
[options setFormatOptionValue:self.manifest forKey:@"manifest_string"];
} }
self.player = [[IJKFFMoviePlayerController alloc] initWithContentURL:self.url withOptions:options]; self.player = [[IJKFFMoviePlayerController alloc] initWithContentURL:self.url withOptions:options];
self.player.view.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight; self.player.view.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册