diff --git a/android/ijkplayer/ijkplayer-example/src/main/java/tv/danmaku/ijk/media/example/widget/media/IjkVideoView.java b/android/ijkplayer/ijkplayer-example/src/main/java/tv/danmaku/ijk/media/example/widget/media/IjkVideoView.java index da787c682e43967cf74521179e7b2367c2269970..d4200045a8aaac865529c0dad4f2cf77464aa8a2 100755 --- a/android/ijkplayer/ijkplayer-example/src/main/java/tv/danmaku/ijk/media/example/widget/media/IjkVideoView.java +++ b/android/ijkplayer/ijkplayer-example/src/main/java/tv/danmaku/ijk/media/example/widget/media/IjkVideoView.java @@ -256,7 +256,7 @@ public class IjkVideoView extends FrameLayout implements MediaController.MediaPl public void setVideoPath(String path) { if (path.contains("adaptationSet")){ mManifestString = path; - setVideoURI(Uri.EMPTY); + setVideoURI(Uri.parse("ijklas:")); } else { setVideoURI(Uri.parse(path)); } @@ -1044,7 +1044,8 @@ public class IjkVideoView extends FrameLayout implements MediaController.MediaPl ijkMediaPlayer.native_setLogLevel(IjkMediaPlayer.IJK_LOG_DEBUG); 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); } if (mSettings.getUsingMediaCodec()) { diff --git a/ijkmedia/ijkplayer/ff_ffplay.c b/ijkmedia/ijkplayer/ff_ffplay.c index eae2dae484c8bd376a9a96552065275d12135422..714a8c9d6186682e8fee119bd8355b06217f438e 100755 --- a/ijkmedia/ijkplayer/ff_ffplay.c +++ b/ijkmedia/ijkplayer/ff_ffplay.c @@ -48,7 +48,6 @@ #include "libavutil/avassert.h" #include "libavutil/time.h" #include "libavformat/avformat.h" -#include "ijkavformat/ijklas.h" #if CONFIG_AVDEVICE #include "libavdevice/avdevice.h" #endif @@ -3117,13 +3116,9 @@ static int read_thread(void *arg) if (ffp->iformat_name) is->iformat = av_find_input_format(ffp->iformat_name); - - if (ffp->is_manifest) { - extern AVInputFormat ijkff_las_demuxer; - 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; - } + + av_dict_set_intptr(&ffp->format_opts, "video_cache_ptr", (intptr_t)&ffp->stat.video_cache, 0); + av_dict_set_intptr(&ffp->format_opts, "audio_cache_ptr", (intptr_t)&ffp->stat.audio_cache, 0); err = avformat_open_input(&ic, is->filename, is->iformat, &ffp->format_opts); if (err < 0) { print_error(is->filename, err); @@ -4001,8 +3996,6 @@ FFPlayer *ffp_create() ffp->meta = ijkmeta_create(); av_opt_set_defaults(ffp); - - las_stat_init(&ffp->las_player_statistic); return ffp; } @@ -4022,7 +4015,6 @@ void ffp_destroy(FFPlayer *ffp) ffpipenode_free_p(&ffp->node_vdec); ffpipeline_free_p(&ffp->pipeline); ijkmeta_destroy_p(&ffp->meta); - las_stat_destroy(&ffp->las_player_statistic); ffp_reset_internal(ffp); SDL_DestroyMutexP(&ffp->af_mutex); @@ -4637,18 +4629,12 @@ void ffp_audio_statistic_l(FFPlayer *ffp) { VideoState *is = ffp->is; 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) { VideoState *is = ffp->is; 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) diff --git a/ijkmedia/ijkplayer/ff_ffplay_def.h b/ijkmedia/ijkplayer/ff_ffplay_def.h index 7ca73f527984479dd4945bc995e00c44e91c594e..00f19f3c4d36c3df4c485b3edd8380d187d8564b 100755 --- a/ijkmedia/ijkplayer/ff_ffplay_def.h +++ b/ijkmedia/ijkplayer/ff_ffplay_def.h @@ -65,7 +65,6 @@ #include "ff_ffmsg_queue.h" #include "ff_ffpipenode.h" #include "ijkmeta.h" -#include "ijkavformat/ijklas.h" #define DEFAULT_HIGH_WATER_MARK_IN_BYTES (256 * 1024) @@ -721,8 +720,6 @@ typedef struct FFPlayer { char *mediacodec_default_name; int ijkmeta_delay_init; int render_wait_start; - int is_manifest; - LasPlayerStatistic las_player_statistic; } FFPlayer; #define fftime_to_milliseconds(ts) (av_rescale(ts, 1000, AV_TIME_BASE)) @@ -833,7 +830,6 @@ inline static void ffp_reset_internal(FFPlayer *ffp) ffp->mediacodec_default_name = NULL; // option ffp->ijkmeta_delay_init = 0; // option ffp->render_wait_start = 0; - ffp->is_manifest = 0; ijkmeta_reset(ffp->meta); diff --git a/ijkmedia/ijkplayer/ff_ffplay_options.h b/ijkmedia/ijkplayer/ff_ffplay_options.h index 5384d945d919ca6ecc963b8dd0c1d1b552d772e8..b021c26e55d1dca03ce73086dc92b080ca0e0ffa 100644 --- a/ijkmedia/ijkplayer/ff_ffplay_options.h +++ b/ijkmedia/ijkplayer/ff_ffplay_options.h @@ -206,9 +206,6 @@ static const AVOption ffp_context_options[] = { OPTION_OFFSET(ijkmeta_delay_init), OPTION_INT(0, 0, 1) }, { "render-wait-start", "render wait start", 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 } }; diff --git a/ijkmedia/ijkplayer/ijkavformat/allformats.c b/ijkmedia/ijkplayer/ijkavformat/allformats.c index c220949f9db67a1257884e21ab4bc6dbc3638927..49dd3b61bc3e5f740b2682a9b76ba5be0c5093e0 100644 --- a/ijkmedia/ijkplayer/ijkavformat/allformats.c +++ b/ijkmedia/ijkplayer/ijkavformat/allformats.c @@ -87,5 +87,6 @@ void ijkav_register_all(void) IJK_REGISTER_PROTOCOL(ijksegment); /* demuxers */ IJK_REGISTER_DEMUXER(ijklivehook); + IJK_REGISTER_DEMUXER(ijklas); av_log(NULL, AV_LOG_INFO, "===== custom modules end =====\n"); } diff --git a/ijkmedia/ijkplayer/ijkavformat/ijklas.c b/ijkmedia/ijkplayer/ijkavformat/ijklas.c index fea1981989b7a19e8528e8cafca1c49468700454..642a50006fdf4e483680b583f34989b1e42a5b26 100644 --- a/ijkmedia/ijkplayer/ijkavformat/ijklas.c +++ b/ijkmedia/ijkplayer/ijkavformat/ijklas.c @@ -28,6 +28,7 @@ #include "ijksdl/ijksdl_thread.h" #include "ijksdl/ijksdl_mutex.h" #include "cJSON.h" +#include "ff_ffplay_def.h" #include "ijklas.h" @@ -184,10 +185,11 @@ typedef struct PlayList { // cur playlist Qos LasStatistic* las_statistic; - LasPlayerStatistic* las_player_statistic; bool is_stream_ever_opened; int64_t bytes_read; unsigned session_id; + FFTrackCacheStatistic* video_cache; + FFTrackCacheStatistic* audio_cache; } PlayList; typedef struct LasContext { @@ -204,13 +206,21 @@ typedef struct LasContext { char* manifest_string; int64_t network; char* abr_history_data; - int64_t las_player_statistic; char* live_adapt_config; AVDictionary* avio_opts; // all info of las is in it PlayList playlist; + LasStatistic las_statistic; 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; #pragma mark common util @@ -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__) #pragma mark PlayerControl -int las_stat_init(LasPlayerStatistic* stat) { - memset(stat, 0, sizeof(LasPlayerStatistic)); - stat->las_switch_mode = LAS_AUTO_MODE; - return pthread_mutex_init(&stat->control_mutex, NULL); +int get_switch_mode(AVFormatContext* format) { + LasContext* c = format->priv_data; + return c->las_switch_mode; } -void las_stat_destroy(LasPlayerStatistic* stat) { - pthread_mutex_destroy(&stat->control_mutex); +int64_t get_first_audio_packet_pts(AVFormatContext* format) { + LasContext* c = format->priv_data; + return c->first_audio_packet_pts; } -int las_get_switch_mode(LasPlayerStatistic* stat) { - pthread_mutex_lock(&stat->control_mutex); - int switch_mode = stat->las_switch_mode; - pthread_mutex_unlock(&stat->control_mutex); - return switch_mode; +int get_audio_only_request(AVFormatContext* format) { + LasContext* c = format->priv_data; + return c->audio_only_request; } -void las_set_switch_mode(LasPlayerStatistic* stat, int switch_mode) { - pthread_mutex_lock(&stat->control_mutex); - stat->las_switch_mode = switch_mode; - pthread_mutex_unlock(&stat->control_mutex); +void set_audio_only_response(AVFormatContext* format, int audio_only) { + LasContext* c = format->priv_data; + c->audio_only_response = audio_only; } -int64_t las_get_first_audio_packet_pts(LasPlayerStatistic* stat) { - pthread_mutex_lock(&stat->control_mutex); - int64_t ret = stat->first_audio_packet_pts; - 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); +void set_stream_reopened(AVFormatContext* format, bool stream_reopened) { + LasContext* c = format->priv_data; + c->stream_reopened = stream_reopened; } -#pragma mark PlayerStat -int32_t LasPlayerStatistic_get_downloading_bitrate(LasPlayerStatistic* stat) { - if (stat->las_stat.bitrate_downloading > 0) { - return stat->las_stat.bitrate_downloading; +int64_t get_cache_duration_ms(FFTrackCacheStatistic* cache) { + if (cache) { + return cache->duration; } 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 static int64_t get_bytes_read(PlayList* p) { SDL_LockMutex(p->las_mutex); @@ -692,8 +612,8 @@ void LasStatistic_on_read_packet(LasStatistic* stat, PlayList* playlist) { void LasStatistic_on_buffer_time(LasStatistic* stat, PlayList* playlist) { if (stat && playlist) { - stat->cached_a_dur_ms = las_get_audio_cached_duration_ms(playlist->las_player_statistic); - stat->cached_v_dur_ms = las_get_video_cached_duration_ms(playlist->las_player_statistic); + stat->cached_a_dur_ms = get_cache_duration_ms(playlist->audio_cache); + stat->cached_v_dur_ms = get_cache_duration_ms(playlist->video_cache);; 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", 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 void LasStatistic_on_rep_switch_count(LasStatistic* stat, PlayList* playlist) { if (stat) { stat->rep_switch_cnt++; - stat->switch_point_a_buffer_ms = las_get_audio_cached_duration_ms(playlist->las_player_statistic); - stat->switch_point_v_buffer_ms = las_get_video_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 = get_cache_duration_ms(playlist->video_cache); } } @@ -819,7 +739,7 @@ void MultiRateAdaption_init(MultiRateAdaption* thiz, AdaptiveConfig config, 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) { thiz->current = rep_index_2_local_index(thiz, switch_mode); } @@ -858,7 +778,7 @@ bool update_stable_buffer(MultiRateAdaption* thiz, double buffered) { * check buffer periodically */ 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); if (is_buffer_stable && thiz->current + 1 < thiz->n_bitrates) { thiz->generated_speed = thiz->levels[thiz->current + 1]; @@ -919,12 +839,16 @@ bool is_speed_enough(MultiRateAdaption* thiz, double speed) { } 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 smoothed_speed = get_smoothed_speed(thiz, speed); algo_info("gop_speed: %.0f, smoothed_speed: %.0f", speed, smoothed_speed); 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; if (predicted_buffered < thiz->conf.buffer_lower_limit_second @@ -1189,10 +1113,10 @@ int64_t GopReader_download_gop(GopReader* reader, MultiRateAdaption* adaption, P 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) { 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); int64_t request_ts = current_playing_audio_ts - playlist->adaptation_set.duration / 2; 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 adaption->next_expected_rep_index = next_representation_id( adaption, - las_get_switch_mode(playlist->las_player_statistic), + get_switch_mode(playlist->outermost_ctx), 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) { LasStatistic_on_adaption_adapted(playlist, adaption); LasStatistic_on_rep_switch_count(playlist->las_statistic, playlist); @@ -1505,7 +1429,7 @@ int PlayList_open_rep(PlayList* playlist, FlvTag* tag, AVFormatContext* s) { } playlist->is_stream_ever_opened = true; } 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++) { @@ -1520,7 +1444,7 @@ int PlayList_open_rep(PlayList* playlist, FlvTag* tag, AVFormatContext* s) { } 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); return 0; @@ -1763,7 +1687,6 @@ int parse_root(char* file_name, PlayList* c) { } int parse_adapt_config(char* config_string, AdaptiveConfig* config, PlayList* playlist) { - LasPlayerStatistic* player_stat = playlist->las_player_statistic; cJSON* root = cJSON_Parse(config_string); if (!root) return LAS_ERROR_ADAPT_CONFIG_JSON; @@ -1835,7 +1758,7 @@ static int las_close(AVFormatContext* s) { } 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 0; @@ -1861,20 +1784,19 @@ static int las_read_header(AVFormatContext* s) { playlist->session_id = c->session_id; av_dict_set(&c->avio_opts, "timeout", "10000000", 0); - if ((ret = parse_root(c->manifest_string, playlist)) < 0) { log_error("Illegal manifest Json String"); goto fail; } - log_info("Finish parsing las manifest (player)"); - playlist->las_player_statistic = (LasPlayerStatistic*)c->las_player_statistic; - if (playlist->las_player_statistic) { - playlist->las_statistic = &playlist->las_player_statistic->las_stat; - log_info("playlist->stat: %p, las_statistic: %p", playlist->las_player_statistic, playlist->las_statistic); + log_info("Finish parsing las manifest, switch_mode:%d", c->las_switch_mode); + if (c->audio_cache_ptr && c->video_cache_ptr) { + playlist->video_cache = (FFTrackCacheStatistic*)c->video_cache_ptr; + playlist->audio_cache = (FFTrackCacheStatistic*)c->audio_cache_ptr; } else { - log_error("las_player_statistic is null"); + log_error("FFTrackCacheStatistic is null"); goto fail; } + playlist->las_statistic = &c->las_statistic; LasStatistic_init(playlist->las_statistic, playlist); RateAdaptConfig_default_init(&config, playlist); @@ -2089,10 +2011,6 @@ static const AVOption las_options[] = { "device-network-type", "device-network-type", 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", OFFSET(live_adapt_config), AV_OPT_TYPE_STRING, { .str = NULL }, CHAR_MIN, CHAR_MAX, FLAGS @@ -2101,20 +2019,52 @@ static const AVOption las_options[] = { "session_id", "session_id", 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} }; -static const AVClass las_class = { - .class_name = "las", +static const AVClass ijklas_class = { + .class_name = "las demuxer", .item_name = av_default_item_name, .option = las_options, .version = LIBAVUTIL_VERSION_INT, }; -AVInputFormat ijkff_las_demuxer = { - .name = "las", +AVInputFormat ijkff_ijklas_demuxer = { + .name = "ijklas", .long_name = "Live Adaptive Streaming", - .priv_class = &las_class, + .priv_class = &ijklas_class, .priv_data_size = sizeof(LasContext), .read_probe = las_probe, .read_header = las_read_header, diff --git a/ijkmedia/ijkplayer/ijkavformat/ijklas.h b/ijkmedia/ijkplayer/ijkavformat/ijklas.h index 2515598073c007fc6a14a79a3a09eb25bf2c3911..7730a1b56d82f47e8d07ea2cd4345ec41ca16e58 100644 --- a/ijkmedia/ijkplayer/ijkavformat/ijklas.h +++ b/ijkmedia/ijkplayer/ijkavformat/ijklas.h @@ -7,7 +7,7 @@ #define MAX_URL_SIZE 4096 #define MAX_STREAM_NUM 10 -#define LAS_AUTO_MODE -1 +#define LAS_AUTO_MODE (-1) typedef struct FlvInfo { int total_bandwidth_kbps; @@ -46,47 +46,4 @@ typedef struct LasStatistic { int64_t total_bytes_read; } 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 diff --git a/ios/IJKMediaDemo/IJKMediaDemo/IJKDemoSampleViewController.m b/ios/IJKMediaDemo/IJKMediaDemo/IJKDemoSampleViewController.m index 240338da6093d716587d266a6fa9c0a223a033fb..4f0f72cfb353eefb00cb6d884a8b4742bcf802d4 100644 --- a/ios/IJKMediaDemo/IJKMediaDemo/IJKDemoSampleViewController.m +++ b/ios/IJKMediaDemo/IJKMediaDemo/IJKDemoSampleViewController.m @@ -37,7 +37,7 @@ NSMutableArray *sampleList = [[NSMutableArray alloc] init]; [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", @"http://devimages.apple.com.edgekey.net/streaming/examples/bipbop_4x3/bipbop_4x3_variant.m3u8"]]; [sampleList addObject:@[@"bipbop basic 400x300 @ 232 kbps", diff --git a/ios/IJKMediaDemo/IJKMediaDemo/IJKMoviePlayerViewController.m b/ios/IJKMediaDemo/IJKMediaDemo/IJKMoviePlayerViewController.m index 6859d63d891fb21c16b470049b2d4cecb3bfb2f9..5178c7470a3ce4b93a00a4d1b0e69685185e9363 100644 --- a/ios/IJKMediaDemo/IJKMediaDemo/IJKMoviePlayerViewController.m +++ b/ios/IJKMediaDemo/IJKMediaDemo/IJKMoviePlayerViewController.m @@ -39,11 +39,9 @@ - (instancetype)initWithManifest: (NSString*)manifest_string { self = [self initWithNibName:@"IJKMoviePlayerViewController" bundle:nil]; if (self) { - NSString *fake_url = @"http://fakeurl_for_manifest"; - NSURL *url = [NSURL URLWithString:fake_url]; - self.url = url; + self.url = [NSURL URLWithString:@"ijklas:"]; + self.manifest = manifest_string; } - self.manifest = manifest_string; return self; } @@ -87,8 +85,9 @@ IJKFFOptions *options = [IJKFFOptions optionsByDefault]; if (self.manifest != nil){ - [options setFormatOptionValue:self.manifest forKey:@"manifest_string"]; - [options setPlayerOptionIntValue:1 forKey:@"is-manifest"]; + [options setPlayerOptionValue:@"ijklas" forKey:@"iformat"]; + [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.view.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;