未验证 提交 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
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()) {
......
......@@ -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)
......
......@@ -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);
......
......@@ -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 }
};
......
......@@ -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");
}
......@@ -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,
......
......@@ -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
......@@ -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",
......
......@@ -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;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册