提交 e8b57052 编写于 作者: Z Zhang Rui

ijkavformat: using new ffurl_open_whitelist

上级 d542640d
......@@ -60,7 +60,7 @@
#endif
#include "ijksdl/ijksdl_log.h"
#include "ijkavformat/ijkavformat.h"
#include "libavformat/ijkavformat.h"
#include "ff_cmdutils.h"
#include "ff_fferror.h"
#include "ff_ffpipeline.h"
......
......@@ -24,39 +24,12 @@
#include "libavformat/url.h"
#include "libavformat/version.h"
#define FF_REGISTER_PROTOCOL(x) \
{ \
extern URLProtocol ff_##x##_protocol; \
ijkav_register_protocol(&ff_##x##_protocol); \
}
#define IJK_REGISTER_PROTOCOL(x) \
{ \
extern URLProtocol ijkff_##x##_protocol; \
ijkav_register_protocol(&ijkff_##x##_protocol); \
}
#define IJK_REGISTER_DEMUXER(x) \
{ \
extern AVInputFormat ijkff_##x##_demuxer; \
ijkav_register_input_format(&ijkff_##x##_demuxer); \
}
static struct URLProtocol *ijkav_find_protocol(const char *proto_name)
{
URLProtocol *up = NULL;
if (!proto_name)
return NULL;
while ((up = ffurl_protocol_next(up)) != NULL) {
if (!up->name)
continue;
if (!strcmp(proto_name, up->name))
break;
}
return up;
}
static struct AVInputFormat *ijkav_find_input_format(const char *iformat_name)
{
AVInputFormat *fmt = NULL;
......@@ -71,16 +44,6 @@ static struct AVInputFormat *ijkav_find_input_format(const char *iformat_name)
return NULL;
}
static void ijkav_register_protocol(URLProtocol *protocol)
{
if (ijkav_find_protocol(protocol->name)) {
av_log(NULL, AV_LOG_WARNING, "skip protocol: %s (duplicated)\n", protocol->name);
} else {
av_log(NULL, AV_LOG_INFO, "register protocol: %s\n", protocol->name);
ffurl_register_protocol(protocol);
}
}
static void ijkav_register_input_format(AVInputFormat *iformat)
{
if (ijkav_find_input_format(iformat->name)) {
......@@ -103,15 +66,9 @@ void ijkav_register_all(void)
/* protocols */
av_log(NULL, AV_LOG_INFO, "===== custom modules begin =====\n");
FF_REGISTER_PROTOCOL(async);
IJK_REGISTER_PROTOCOL(ijkhttphook);
IJK_REGISTER_PROTOCOL(ijkinject);
IJK_REGISTER_PROTOCOL(ijklongurl);
#ifdef __ANDROID__
IJK_REGISTER_PROTOCOL(ijkmediadatasource);
#endif
IJK_REGISTER_PROTOCOL(ijksegment);
IJK_REGISTER_PROTOCOL(ijktcphook);
/* demuxers */
IJK_REGISTER_DEMUXER(ijklivehook);
......
此差异已折叠。
/*
* ijkavformat.h
*
* Copyright (c) 2003 Fabrice Bellard
* Copyright (c) 2013 Zhang Rui <bbcallen@gmail.com>
*
* This file is part of ijkPlayer.
*
* ijkPlayer is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* ijkPlayer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with ijkPlayer; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef FFPLAY__IJKAVFORMAT_IJKAVFORMAT_H
#define FFPLAY__IJKAVFORMAT_IJKAVFORMAT_H
void ijkav_register_all(void);
#define AV_PKT_FLAG_DISCONTINUITY 0x0100
/**
* Injection
*/
typedef struct IJKAVInject_OnUrlOpenData {
size_t size;
char url[4096]; /* in, out */
int segment_index; /* in, default = 0 */
int retry_counter; /* in */
int is_handled; /* out, default = false */
int is_url_changed; /* out, default = false */
} IJKAVInject_OnUrlOpenData;
/**
* Resolve segment url from concatdec
*
* @param data IJKAVInject_OnUrlOpenData*
* @param data_size size of IJKAVInject_OnUrlOpenData;
* @return 0 if OK, AVERROR_xxx otherwise
*/
#define IJKAVINJECT_CONCAT_RESOLVE_SEGMENT 0x10000
/**
* Protocol open event
*
* @param data IJKAVInject_OnUrlOpenData*
* @param data_size size of IJKAVInject_OnUrlOpenData;
* @return 0 if OK, AVERROR_xxx otherwise
*/
#define IJKAVINJECT_ON_TCP_OPEN 0x10001
#define IJKAVINJECT_ON_HTTP_OPEN 0x10002
#define IJKAVINJECT_ON_HTTP_RETRY 0x10003
#define IJKAVINJECT_ON_LIVE_RETRY 0x10004
/**
* Statistic
*/
typedef struct IJKAVInject_AsyncStatistic {
size_t size;
int64_t buf_backwards;
int64_t buf_forwards;
int64_t buf_capacity;
} IJKAVInject_AsyncStatistic;
#define IJKAVINJECT_ASYNC_STATISTIC 0x11000
typedef struct IJKAVInject_AsyncReadSpeed {
size_t size;
int is_full_speed;
int64_t io_bytes;
int64_t elapsed_milli;
} IJKAVInject_AsyncReadSpeed;
#define IJKAVINJECT_ASYNC_READ_SPEED 0x11001
typedef struct IJKAVInject_IpAddress {
int error;
int family;
char ip[96];
int port;
} IJKAVInject_IpAddress;
#define IJKAVINJECT_DID_TCP_CONNECT 0x12002
// AVAppHttpEvent
#define IJKAVINJECT_WILL_HTTP_OPEN 0x12100
#define IJKAVINJECT_DID_HTTP_OPEN 0x12101
#define IJKAVINJECT_WILL_HTTP_SEEK 0x12102
#define IJKAVINJECT_DID_HTTP_SEEK 0x12103
// AVAppIOTraffic
#define IJKAVINJECT_ON_IO_TRAFFIC 0x12204
typedef int (*IjkAVInjectCallback)(void *opaque, int message, void *data, size_t data_size);
IjkAVInjectCallback ijkav_register_inject_callback(IjkAVInjectCallback callback);
IjkAVInjectCallback ijkav_get_inject_callback();
#endif
/*
* Copyright (c) 2015 Zhang Rui <bbcallen@gmail.com>
*
* This file is part of ijkPlayer.
*
* ijkPlayer is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* ijkPlayer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with ijkPlayer; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <assert.h>
#include "libavformat/avformat.h"
#include "libavformat/url.h"
#include "libavutil/avstring.h"
#include "libavutil/log.h"
#include "libavutil/opt.h"
#include "ijkplayer/ijkavutil/opt.h"
#include "ijkavformat.h"
typedef struct Context {
AVClass *class;
URLContext *inner;
char *inner_url;
/* options */
int64_t opaque;
int segment_index;
} Context;
static int ijkinject_open(URLContext *h, const char *arg, int flags, AVDictionary **options)
{
Context *c = h->priv_data;
int ret = -1;
av_strstart(arg, "ijkinject:", &arg);
c->inner_url = av_strdup(arg);
av_dict_set_int(options, "ijkinject-opaque", c->opaque, 0);
av_dict_set_int(options, "ijkinject-segment-index", c->segment_index, 0);
ret = ffurl_open_whitelist(&c->inner, arg, flags, &h->interrupt_callback, options, h->protocol_whitelist);
if (ret)
goto fail;
return ret;
fail:
av_freep(&c->inner_url);
return ret;
}
static int ijkinject_close(URLContext *h)
{
Context *c = h->priv_data;
av_freep(&c->inner_url);
return ffurl_close(c->inner);
}
static int ijkinject_read(URLContext *h, unsigned char *buf, int size)
{
Context *c = h->priv_data;
return ffurl_read(c->inner, buf, size);
}
static int64_t ijkinject_seek(URLContext *h, int64_t pos, int whence)
{
Context *c = h->priv_data;
return ffurl_seek(c->inner, pos, whence);
}
#define OFFSET(x) offsetof(Context, x)
#define D AV_OPT_FLAG_DECODING_PARAM
static const AVOption options[] = {
{ "ijkinject-opaque", "private data of user, passed with custom callback",
OFFSET(opaque), IJKAV_OPTION_INT64(0, INT64_MIN, INT64_MAX) },
{ NULL }
};
#undef D
#undef OFFSET
static const AVClass ijkinject_context_class = {
.class_name = "Inject",
.item_name = av_default_item_name,
.option = options,
.version = LIBAVUTIL_VERSION_INT,
};
URLProtocol ijkff_ijkinject_protocol = {
.name = "ijkinject",
.url_open2 = ijkinject_open,
.url_read = ijkinject_read,
.url_seek = ijkinject_seek,
.url_close = ijkinject_close,
.priv_data_size = sizeof(Context),
.priv_data_class = &ijkinject_context_class,
};
......@@ -24,7 +24,8 @@
#include "libavutil/opt.h"
#include "ijkplayer/ijkavutil/opt.h"
#include "ijkavformat.h"
#include "libavformat/ijkavformat.h"
typedef struct {
AVClass *class;
......
/*
* Copyright (c) 2015 Zhang Rui <bbcallen@gmail.com>
*
* This file is part of ijkPlayer.
*
* ijkPlayer is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* ijkPlayer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with ijkPlayer; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <assert.h>
#include "libavformat/avformat.h"
#include "libavformat/url.h"
#include "libavutil/avstring.h"
#include "libavutil/log.h"
#include "libavutil/opt.h"
#include "ijkplayer/ijkavutil/opt.h"
#include "ijkavformat.h"
typedef struct Context {
AVClass *class;
URLContext *inner;
/* options */
char *url;
} Context;
static int ijklongurl_open(URLContext *h, const char *arg, int flags, AVDictionary **options)
{
Context *c = h->priv_data;
if (!c->url || !*c->url)
return AVERROR_EXTERNAL;
return ffurl_open_whitelist(&c->inner, c->url, flags, &h->interrupt_callback, options, h->protocol_whitelist);
}
static int ijklongurl_close(URLContext *h)
{
Context *c = h->priv_data;
return ffurl_close(c->inner);
}
static int ijklongurl_read(URLContext *h, unsigned char *buf, int size)
{
Context *c = h->priv_data;
return ffurl_read(c->inner, buf, size);
}
static int64_t ijklongurl_seek(URLContext *h, int64_t pos, int whence)
{
Context *c = h->priv_data;
return ffurl_seek(c->inner, pos, whence);
}
#define OFFSET(x) offsetof(Context, x)
#define D AV_OPT_FLAG_DECODING_PARAM
static const AVOption options[] = {
{ "ijklongurl-url", "real url to access",
OFFSET(url), IJKAV_OPTION_STR(NULL) },
{ NULL }
};
#undef D
#undef OFFSET
static const AVClass ijklongurl_context_class = {
.class_name = "LongUrl",
.item_name = av_default_item_name,
.option = options,
.version = LIBAVUTIL_VERSION_INT,
};
URLProtocol ijkff_ijklongurl_protocol = {
.name = "ijklongurl",
.url_open2 = ijklongurl_open,
.url_read = ijklongurl_read,
.url_seek = ijklongurl_seek,
.url_close = ijklongurl_close,
.priv_data_size = sizeof(Context),
.priv_data_class = &ijklongurl_context_class,
};
/*
* Copyright (c) 2015 Zhang Rui <bbcallen@gmail.com>
*
* This file is part of ijkPlayer.
*
* ijkPlayer is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* ijkPlayer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with ijkPlayer; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <assert.h>
#include "libavformat/avformat.h"
#include "libavformat/url.h"
#include "libavutil/avstring.h"
#include "libavutil/log.h"
#include "libavutil/opt.h"
#include "ijkplayer/ijkavutil/opt.h"
#include "ijkavformat.h"
typedef struct Context {
AVClass *class;
URLContext *inner;
/* options */
int64_t opaque;
int segment_index;
char *http_hook;
} Context;
static void *ijksegment_get_opaque(URLContext *h) {
Context *c = h->priv_data;
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wint-to-pointer-cast"
#endif
return (void *)c->opaque;
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
}
static int ijksegment_open(URLContext *h, const char *arg, int flags, AVDictionary **options)
{
Context *c = h->priv_data;
IJKAVInject_OnUrlOpenData inject_data = {0};
IjkAVInjectCallback inject_callback = ijkav_get_inject_callback();
int ret = -1;
void *opaque = ijksegment_get_opaque(h);
assert(opaque);
if (!c->opaque) {
av_log(h, AV_LOG_ERROR, "null opaque\n");
return AVERROR_EXTERNAL;
}
if (!inject_callback) {
av_log(h, AV_LOG_ERROR, "null inject_callback\n");
return AVERROR_EXTERNAL;
}
av_strstart(arg, "ijksegment:", &arg);
if (!arg || !*arg)
return AVERROR_EXTERNAL;
inject_data.size = sizeof(inject_data);
inject_data.segment_index = (int)strtol(arg, NULL, 0);
strlcpy(inject_data.url, arg, sizeof(inject_data.url));
if (opaque && inject_callback &&
inject_data.segment_index < 0) {
ret = AVERROR_EXTERNAL;
goto fail;
}
ret = inject_callback(opaque, IJKAVINJECT_CONCAT_RESOLVE_SEGMENT, &inject_data, sizeof(inject_data));
if (ret || !inject_data.url[0]) {
ret = AVERROR_EXIT;
goto fail;
}
av_dict_set_int(options, "ijkinject-opaque", c->opaque, 0);
av_dict_set_int(options, "ijkinject-segment-index", c->segment_index, 0);
ret = ffurl_open_whitelist(&c->inner, inject_data.url, flags, &h->interrupt_callback, options, h->protocol_whitelist);
if (ret)
goto fail;
return 0;
fail:
return ret;
}
static int ijksegment_close(URLContext *h)
{
Context *c = h->priv_data;
return ffurl_close(c->inner);
}
static int ijksegment_read(URLContext *h, unsigned char *buf, int size)
{
Context *c = h->priv_data;
return ffurl_read(c->inner, buf, size);
}
static int64_t ijksegment_seek(URLContext *h, int64_t pos, int whence)
{
Context *c = h->priv_data;
return ffurl_seek(c->inner, pos, whence);
}
#define OFFSET(x) offsetof(Context, x)
#define D AV_OPT_FLAG_DECODING_PARAM
static const AVOption options[] = {
{ "ijkinject-opaque", "private data of user, passed with custom callback",
OFFSET(opaque), IJKAV_OPTION_INT64(0, INT64_MIN, INT64_MAX) },
{ "ijkinject-segment-index", "segment index of current url",
OFFSET(segment_index), IJKAV_OPTION_INT(0, 0, INT_MAX) },
{ NULL }
};
#undef D
#undef OFFSET
static const AVClass ijksegment_context_class = {
.class_name = "Inject",
.item_name = av_default_item_name,
.option = options,
.version = LIBAVUTIL_VERSION_INT,
};
URLProtocol ijkff_ijksegment_protocol = {
.name = "ijksegment",
.url_open2 = ijksegment_open,
.url_read = ijksegment_read,
.url_seek = ijksegment_seek,
.url_close = ijksegment_close,
.priv_data_size = sizeof(Context),
.priv_data_class = &ijksegment_context_class,
};
/*
* Copyright (c) 2015 Zhang Rui <bbcallen@gmail.com>
*
* This file is part of ijkPlayer.
*
* ijkPlayer is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* ijkPlayer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with ijkPlayer; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <assert.h>
#include "libavformat/avformat.h"
#include "libavformat/url.h"
#include "libavutil/avstring.h"
#include "libavutil/log.h"
#include "libavutil/opt.h"
#include "ijkplayer/ijkavutil/opt.h"
#include "ijkavformat.h"
typedef struct Context {
AVClass *class;
URLContext *inner;
int64_t logical_pos;
int64_t logical_size;
int io_error;
IJKAVInject_OnUrlOpenData inject_data;
const char *scheme;
const char *inner_scheme;
int open_callback_id;
/* options */
int inner_flags;
AVDictionary *inner_options;
int64_t opaque;
int segment_index;
int64_t test_fail_point;
int64_t test_fail_point_next;
} Context;
static int ijkurlhook_call_inject(URLContext *h)
{
Context *c = h->priv_data;
IjkAVInjectCallback inject_callback = ijkav_get_inject_callback();
void *opaque = (void *) (intptr_t) c->opaque;
int ret = 0;
if (ff_check_interrupt(&h->interrupt_callback)) {
ret = AVERROR_EXIT;
goto fail;
}
if (opaque && inject_callback) {
IJKAVInject_OnUrlOpenData inject_data_backup = c->inject_data;
c->inject_data.is_handled = 0;
c->inject_data.is_url_changed = 0;
ret = inject_callback(opaque, c->open_callback_id, &c->inject_data, sizeof(c->inject_data));
if (ret || !c->inject_data.url[0]) {
ret = AVERROR_EXIT;
goto fail;
}
if (!c->inject_data.is_url_changed && strcmp(inject_data_backup.url, c->inject_data.url)) {
// force a url compare
c->inject_data.is_url_changed = 1;
}
av_log(h, AV_LOG_INFO, "%s %s (%s)\n", h->prot->name, c->inject_data.url, c->inject_data.is_url_changed ? "changed" : "remain");
}
if (ff_check_interrupt(&h->interrupt_callback)) {
ret = AVERROR_EXIT;
goto fail;
}
fail:
return ret;
}
static int ijkurlhook_reconnect(URLContext *h, AVDictionary *extra)
{
Context *c = h->priv_data;
int ret = 0;
URLContext *new_url = NULL;
AVDictionary *inner_options = NULL;
c->test_fail_point_next += c->test_fail_point;
assert(c->inner_options);
av_dict_copy(&inner_options, c->inner_options, 0);
if (extra)
av_dict_copy(&inner_options, extra, 0);
ret = ffurl_open_whitelist(&new_url, c->inject_data.url, c->inner_flags, &h->interrupt_callback, &inner_options, h->protocol_whitelist);
if (ret)
goto fail;
ffurl_closep(&c->inner);
c->inner = new_url;
h->is_streamed = c->inner->is_streamed;
c->logical_pos = ffurl_seek(c->inner, 0, SEEK_CUR);
if (c->inner->is_streamed)
c->logical_size = -1;
else
c->logical_size = ffurl_seek(c->inner, 0, AVSEEK_SIZE);
c->io_error = 0;
fail:
av_dict_free(&inner_options);
return ret;
}
static int ijkurlhook_init(URLContext *h, const char *arg, int flags, AVDictionary **options)
{
Context *c = h->priv_data;
int ret = 0;
av_strstart(arg, c->scheme, &arg);
c->inner_flags = flags;
if (options)
av_dict_copy(&c->inner_options, *options, 0);
av_dict_set_int(&c->inner_options, "ijkinject-opaque", c->opaque, 0);
av_dict_set_int(&c->inner_options, "ijkinject-segment-index", c->segment_index, 0);
c->inject_data.size = sizeof(c->inject_data);
c->inject_data.segment_index = c->segment_index;
c->inject_data.retry_counter = 0;
if (av_strstart(arg, c->inner_scheme, NULL)) {
snprintf(c->inject_data.url, sizeof(c->inject_data.url), "%s", arg);
} else {
snprintf(c->inject_data.url, sizeof(c->inject_data.url), "%s%s", c->inner_scheme, arg);
}
return ret;
}
static int ijktcphook_open(URLContext *h, const char *arg, int flags, AVDictionary **options)
{
Context *c = h->priv_data;
int ret = 0;
c->scheme = "ijktcphook:";
c->inner_scheme = "tcp:";
c->open_callback_id = IJKAVINJECT_ON_TCP_OPEN;
ret = ijkurlhook_init(h, arg, flags, options);
if (ret)
goto fail;
ret = ijkurlhook_call_inject(h);
if (ret)
goto fail;
ret = ijkurlhook_reconnect(h, NULL);
if (ret)
goto fail;
fail:
return ret;
}
static int ijkurlhook_close(URLContext *h)
{
Context *c = h->priv_data;
av_dict_free(&c->inner_options);
return ffurl_closep(&c->inner);
}
static int ijkurlhook_read(URLContext *h, unsigned char *buf, int size)
{
Context *c = h->priv_data;
int ret = 0;
if (c->io_error < 0)
return c->io_error;
if (c->test_fail_point_next > 0 && c->logical_pos >= c->test_fail_point_next) {
av_log(h, AV_LOG_ERROR, "test fail point:%"PRId64"\n", c->test_fail_point_next);
c->io_error = AVERROR(EIO);
return AVERROR(EIO);
}
ret = ffurl_read(c->inner, buf, size);
if (ret > 0)
c->logical_pos += ret;
else
c->io_error = ret;
return ret;
}
static int ijkurlhook_write(URLContext *h, const unsigned char *buf, int size)
{
Context *c = h->priv_data;
return ffurl_write(c->inner, buf, size);
}
static int64_t ijkurlhook_seek(URLContext *h, int64_t pos, int whence)
{
Context *c = h->priv_data;
int64_t seek_ret = 0;
seek_ret = ffurl_seek(c->inner, pos, whence);
if (seek_ret < 0) {
c->io_error = (int)seek_ret;
return seek_ret;
}
c->logical_pos = seek_ret;
if (c->test_fail_point)
c->test_fail_point_next = c->logical_pos + c->test_fail_point;
c->io_error = 0;
return seek_ret;
}
static int ijkhttphook_reconnect_at(URLContext *h, int64_t offset)
{
AVDictionary *extra_opts = NULL;
av_dict_set_int(&extra_opts, "offset", offset, 0);
int ret = ijkurlhook_reconnect(h, extra_opts);
av_dict_free(&extra_opts);
return ret;
}
static int ijkhttphook_open(URLContext *h, const char *arg, int flags, AVDictionary **options)
{
Context *c = h->priv_data;
int ret = 0;
c->scheme = "ijkhttphook:";
c->inner_scheme = "http:";
c->open_callback_id = IJKAVINJECT_ON_HTTP_OPEN;
ret = ijkurlhook_init(h, arg, flags, options);
if (ret)
goto fail;
ret = ijkurlhook_call_inject(h);
if (ret)
goto fail;
ret = ijkurlhook_reconnect(h, NULL);
while (ret) {
int inject_ret = 0;
switch (ret) {
case AVERROR_EXIT:
goto fail;
}
c->inject_data.retry_counter++;
inject_ret = ijkurlhook_call_inject(h);
if (inject_ret) {
ret = AVERROR_EXIT;
goto fail;
}
if (!c->inject_data.is_handled)
goto fail;
av_log(h, AV_LOG_INFO, "%s: will reconnect at start\n", __func__);
ret = ijkurlhook_reconnect(h, NULL);
av_log(h, AV_LOG_INFO, "%s: did reconnect at start: %d\n", __func__, ret);
if (ret)
c->inject_data.retry_counter++;
}
fail:
return ret;
}
static int ijkhttphook_read(URLContext *h, unsigned char *buf, int size)
{
Context *c = h->priv_data;
int ret = 0;
c->inject_data.retry_counter = 0;
ret = ijkurlhook_read(h, buf, size);
while (ret < 0 && !h->is_streamed && c->logical_pos < c->logical_size) {
switch (ret) {
case AVERROR_EXIT:
goto fail;
}
c->inject_data.retry_counter++;
ret = ijkurlhook_call_inject(h);
if (ret)
goto fail;
if (!c->inject_data.is_handled)
goto fail;
av_log(h, AV_LOG_INFO, "%s: will reconnect(%d) at %"PRId64"\n", __func__, c->inject_data.retry_counter, c->logical_pos);
ret = ijkhttphook_reconnect_at(h, c->logical_pos);
av_log(h, AV_LOG_INFO, "%s: did reconnect(%d) at %"PRId64": %d\n", __func__, c->inject_data.retry_counter, c->logical_pos, ret);
if (ret < 0)
continue;
ret = ijkurlhook_read(h, buf, size);
}
fail:
if (ret <= 0) {
c->io_error = ret;
}
return ret;
}
static int64_t ijkhttphook_reseek_at(URLContext *h, int64_t pos, int whence, int force_reconnect)
{
Context *c = h->priv_data;
int ret = 0;
if (!force_reconnect)
return ijkurlhook_seek(h, pos, whence);
if (whence == SEEK_CUR)
pos += c->logical_pos;
else if (whence == SEEK_END)
pos += c->logical_size;
else if (whence != SEEK_SET)
return AVERROR(EINVAL);
if (pos < 0)
return AVERROR(EINVAL);
ret = ijkhttphook_reconnect_at(h, pos);
if (ret) {
c->io_error = ret;
return ret;
}
c->io_error = 0;
return c->logical_pos;
}
static int64_t ijkhttphook_seek(URLContext *h, int64_t pos, int whence)
{
Context *c = h->priv_data;
int ret = 0;
int64_t seek_ret = -1;
if (whence == AVSEEK_SIZE)
return c->logical_size;
else if ((whence == SEEK_CUR && pos == 0) ||
(whence == SEEK_SET && pos == c->logical_pos))
return c->logical_pos;
else if ((c->logical_size < 0 && whence == SEEK_END) || h->is_streamed)
return AVERROR(ENOSYS);
c->inject_data.retry_counter = 0;
ret = ijkurlhook_call_inject(h);
if (ret) {
ret = AVERROR_EXIT;
goto fail;
}
seek_ret = ijkhttphook_reseek_at(h, pos, whence, c->inject_data.is_url_changed);
while (seek_ret < 0) {
switch (seek_ret) {
case AVERROR_EXIT:
case AVERROR_EOF:
goto fail;
}
c->inject_data.retry_counter++;
ret = ijkurlhook_call_inject(h);
if (ret) {
ret = AVERROR_EXIT;
goto fail;
}
if (!c->inject_data.is_handled)
goto fail;
av_log(h, AV_LOG_INFO, "%s: will reseek(%d) at pos=%"PRId64", whence=%d\n", __func__, c->inject_data.retry_counter, pos, whence);
seek_ret = ijkhttphook_reseek_at(h, pos, whence, c->inject_data.is_url_changed);
av_log(h, AV_LOG_INFO, "%s: did reseek(%d) at pos=%"PRId64", whence=%d: %"PRId64"\n", __func__, c->inject_data.retry_counter, pos, whence, seek_ret);
}
if (c->test_fail_point)
c->test_fail_point_next = c->logical_pos + c->test_fail_point;
c->io_error = 0;
return c->logical_pos;
fail:
return ret;
}
#define OFFSET(x) offsetof(Context, x)
#define D AV_OPT_FLAG_DECODING_PARAM
static const AVOption ijktcphook_options[] = {
{ "ijkinject-opaque", "private data of user, passed with custom callback",
OFFSET(opaque), IJKAV_OPTION_INT64(0, INT64_MIN, INT64_MAX) },
{ "ijkinject-segment-index", "segment index of current url",
OFFSET(segment_index), IJKAV_OPTION_INT(0, 0, INT_MAX) },
{ "ijktcphook-test-fail-point", "test fail point, in bytes",
OFFSET(test_fail_point), IJKAV_OPTION_INT(0, 0, INT_MAX) },
{ NULL }
};
static const AVOption ijkhttphook_options[] = {
{ "ijkinject-opaque", "private data of user, passed with custom callback",
OFFSET(opaque), IJKAV_OPTION_INT64(0, INT64_MIN, INT64_MAX) },
{ "ijkinject-segment-index", "segment index of current url",
OFFSET(segment_index), IJKAV_OPTION_INT(0, 0, INT_MAX) },
{ "ijkhttphook-test-fail-point", "test fail point, in bytes",
OFFSET(test_fail_point), IJKAV_OPTION_INT(0, 0, INT_MAX) },
{ NULL }
};
#undef D
#undef OFFSET
static const AVClass ijktcphook_context_class = {
.class_name = "TcpHook",
.item_name = av_default_item_name,
.option = ijktcphook_options,
.version = LIBAVUTIL_VERSION_INT,
};
URLProtocol ijkff_ijktcphook_protocol = {
.name = "ijktcphook",
.url_open2 = ijktcphook_open,
.url_read = ijkurlhook_read,
.url_write = ijkurlhook_write,
.url_close = ijkurlhook_close,
.priv_data_size = sizeof(Context),
.priv_data_class = &ijktcphook_context_class,
};
static const AVClass ijkhttphook_context_class = {
.class_name = "HttpHook",
.item_name = av_default_item_name,
.option = ijkhttphook_options,
.version = LIBAVUTIL_VERSION_INT,
};
URLProtocol ijkff_ijkhttphook_protocol = {
.name = "ijkhttphook",
.url_open2 = ijkhttphook_open,
.url_read = ijkhttphook_read,
.url_write = ijkurlhook_write,
.url_seek = ijkhttphook_seek,
.url_close = ijkurlhook_close,
.priv_data_size = sizeof(Context),
.priv_data_class = &ijkhttphook_context_class,
};
/*
* utils.c
*
* Copyright (c) 2003 Fabrice Bellard
* Copyright (c) 2013 Zhang Rui <bbcallen@gmail.com>
*
* This file is part of ijkPlayer.
*
* ijkPlayer is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* ijkPlayer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with ijkPlayer; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdlib.h>
#include "ijkavformat.h"
static IjkAVInjectCallback s_av_inject_callback = NULL;
IjkAVInjectCallback ijkav_register_inject_callback(IjkAVInjectCallback callback)
{
IjkAVInjectCallback prev_callback = s_av_inject_callback;
s_av_inject_callback = callback;
return prev_callback;
}
IjkAVInjectCallback ijkav_get_inject_callback()
{
return s_av_inject_callback;
}
......@@ -75,14 +75,7 @@
E69808A01C7EB2040048A46C /* IJKNotificationManager.h in Headers */ = {isa = PBXBuildFile; fileRef = E698089E1C7EB2040048A46C /* IJKNotificationManager.h */; settings = {ATTRIBUTES = (Public, ); }; };
E69808A11C7EB2040048A46C /* IJKNotificationManager.m in Sources */ = {isa = PBXBuildFile; fileRef = E698089F1C7EB2040048A46C /* IJKNotificationManager.m */; };
E69BE5511B93FED300AFBA3F /* allformats.c in Sources */ = {isa = PBXBuildFile; fileRef = E69BE54A1B93FED300AFBA3F /* allformats.c */; };
E69BE5531B93FED300AFBA3F /* async.c in Sources */ = {isa = PBXBuildFile; fileRef = E69BE54B1B93FED300AFBA3F /* async.c */; };
E69BE5561B93FED300AFBA3F /* ijkinject.c in Sources */ = {isa = PBXBuildFile; fileRef = E69BE54D1B93FED300AFBA3F /* ijkinject.c */; };
E69BE5571B93FED300AFBA3F /* opt.h in Headers */ = {isa = PBXBuildFile; fileRef = E69BE54F1B93FED300AFBA3F /* opt.h */; };
E69BE5591B9405BD00AFBA3F /* ijkavformat.h in Headers */ = {isa = PBXBuildFile; fileRef = E69BE5581B9405BD00AFBA3F /* ijkavformat.h */; };
E69BE55F1B940D1A00AFBA3F /* utils.c in Sources */ = {isa = PBXBuildFile; fileRef = E69BE55D1B940D1A00AFBA3F /* utils.c */; };
E69BE5641B943C0800AFBA3F /* ijklongurl.c in Sources */ = {isa = PBXBuildFile; fileRef = E69BE5621B943A9A00AFBA3F /* ijklongurl.c */; };
E69BE5681B94468D00AFBA3F /* ijkurlhook.c in Sources */ = {isa = PBXBuildFile; fileRef = E69BE5651B94468D00AFBA3F /* ijkurlhook.c */; };
E69BE56F1B945B0000AFBA3F /* ijksegment.c in Sources */ = {isa = PBXBuildFile; fileRef = E69BE56D1B945B0000AFBA3F /* ijksegment.c */; };
E69BE5721B946FF600AFBA3F /* ijklivehook.c in Sources */ = {isa = PBXBuildFile; fileRef = E69BE5701B946FF600AFBA3F /* ijklivehook.c */; };
E6C2E7BE1C92BD3600E59229 /* IJKKVOController.h in Headers */ = {isa = PBXBuildFile; fileRef = E65DC3B719D93D5F004F8A08 /* IJKKVOController.h */; settings = {ATTRIBUTES = (Public, ); }; };
E6C459841C7030AA004831EC /* ijksdl_gles2.h in Headers */ = {isa = PBXBuildFile; fileRef = E6C459831C7030AA004831EC /* ijksdl_gles2.h */; };
......@@ -225,14 +218,7 @@
E698089E1C7EB2040048A46C /* IJKNotificationManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IJKNotificationManager.h; path = IJKMediaPlayer/IJKNotificationManager.h; sourceTree = "<group>"; };
E698089F1C7EB2040048A46C /* IJKNotificationManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IJKNotificationManager.m; path = IJKMediaPlayer/IJKNotificationManager.m; sourceTree = "<group>"; };
E69BE54A1B93FED300AFBA3F /* allformats.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = allformats.c; sourceTree = "<group>"; };
E69BE54B1B93FED300AFBA3F /* async.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = async.c; sourceTree = "<group>"; };
E69BE54D1B93FED300AFBA3F /* ijkinject.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ijkinject.c; sourceTree = "<group>"; };
E69BE54F1B93FED300AFBA3F /* opt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = opt.h; sourceTree = "<group>"; };
E69BE5581B9405BD00AFBA3F /* ijkavformat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ijkavformat.h; sourceTree = "<group>"; };
E69BE55D1B940D1A00AFBA3F /* utils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = utils.c; sourceTree = "<group>"; };
E69BE5621B943A9A00AFBA3F /* ijklongurl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ijklongurl.c; sourceTree = "<group>"; };
E69BE5651B94468D00AFBA3F /* ijkurlhook.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ijkurlhook.c; sourceTree = "<group>"; };
E69BE56D1B945B0000AFBA3F /* ijksegment.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ijksegment.c; sourceTree = "<group>"; };
E69BE5701B946FF600AFBA3F /* ijklivehook.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ijklivehook.c; sourceTree = "<group>"; };
E6C2FD391B300A390081D321 /* ff_ffplay_debug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ff_ffplay_debug.h; sourceTree = "<group>"; };
E6C459831C7030AA004831EC /* ijksdl_gles2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ijksdl_gles2.h; sourceTree = "<group>"; };
......@@ -603,15 +589,8 @@
isa = PBXGroup;
children = (
E69BE54A1B93FED300AFBA3F /* allformats.c */,
E69BE54B1B93FED300AFBA3F /* async.c */,
E69BE5581B9405BD00AFBA3F /* ijkavformat.h */,
E69BE54D1B93FED300AFBA3F /* ijkinject.c */,
E69BE5701B946FF600AFBA3F /* ijklivehook.c */,
E69BE5621B943A9A00AFBA3F /* ijklongurl.c */,
E69BE56D1B945B0000AFBA3F /* ijksegment.c */,
E69BE5651B94468D00AFBA3F /* ijkurlhook.c */,
E69007F11B96E2A600EB346D /* url.h */,
E69BE55D1B940D1A00AFBA3F /* utils.c */,
);
path = ijkavformat;
sourceTree = "<group>";
......@@ -736,7 +715,6 @@
E654EAE61B6B295200B0F2D0 /* IJKMediaModule.h in Headers */,
E69BE5571B93FED300AFBA3F /* opt.h in Headers */,
E654EAE71B6B295200B0F2D0 /* IJKMediaPlayback.h in Headers */,
E69BE5591B9405BD00AFBA3F /* ijkavformat.h in Headers */,
E654EAED1B6B29C100B0F2D0 /* IJKMediaPlayer.h in Headers */,
E6C459961C7030B6004831EC /* internal.h in Headers */,
E654EAE91B6B295200B0F2D0 /* IJKMPMoviePlayerController.h in Headers */,
......@@ -841,12 +819,9 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
E69BE5641B943C0800AFBA3F /* ijklongurl.c in Sources */,
E69BE56F1B945B0000AFBA3F /* ijksegment.c in Sources */,
E654EAA71B6B283700B0F2D0 /* IJKKVOController.m in Sources */,
E654EAC71B6B287E00B0F2D0 /* ijksdl_vout.c in Sources */,
E6C459951C7030B6004831EC /* yuv444p10le.fsh.c in Sources */,
E69BE55F1B940D1A00AFBA3F /* utils.c in Sources */,
E69BE5511B93FED300AFBA3F /* allformats.c in Sources */,
E654EABB1B6B286B00B0F2D0 /* ffpipenode_ffplay_vdec.c in Sources */,
E6C459981C7030B6004831EC /* renderer_yuv420p.c in Sources */,
......@@ -855,7 +830,6 @@
E654EAB91B6B286700B0F2D0 /* ijkplayer_ios.m in Sources */,
E654EAB51B6B286400B0F2D0 /* ffpipeline_ios.c in Sources */,
E654EABD1B6B287000B0F2D0 /* ijksdl_vout_dummy.c in Sources */,
E69BE5681B94468D00AFBA3F /* ijkurlhook.c in Sources */,
E6C459CC1C70967F004831EC /* renderer_yuv420sp.c in Sources */,
E6C459941C7030B6004831EC /* yuv420p.fsh.c in Sources */,
E654EAC21B6B287E00B0F2D0 /* ijksdl_error.c in Sources */,
......@@ -884,7 +858,6 @@
E654EAB21B6B285900B0F2D0 /* ff_ffplay.c in Sources */,
E654EAC01B6B287E00B0F2D0 /* ijksdl_aout.c in Sources */,
E6C459921C7030B6004831EC /* color.c in Sources */,
E69BE5561B93FED300AFBA3F /* ijkinject.c in Sources */,
E654EAC11B6B287E00B0F2D0 /* ijksdl_audio.c in Sources */,
E654EAC91B6B288A00B0F2D0 /* ijksdl_thread_ios.m in Sources */,
E654EAB31B6B285900B0F2D0 /* ijkmeta.c in Sources */,
......@@ -892,7 +865,6 @@
E654EAD31B6B288A00B0F2D0 /* IJKSDLGLView.m in Sources */,
E654EAC61B6B287E00B0F2D0 /* ijksdl_timer.c in Sources */,
E6C4599A1C7030B6004831EC /* shader.c in Sources */,
E69BE5531B93FED300AFBA3F /* async.c in Sources */,
E6C459971C7030B6004831EC /* renderer.c in Sources */,
E654EAB41B6B285900B0F2D0 /* ijkplayer.c in Sources */,
E654EAAE1B6B284C00B0F2D0 /* IJKFFOptions.m in Sources */,
......
......@@ -32,7 +32,7 @@
#include "string.h"
#include "ijkplayer/version.h"
#include "ijkplayer/ijkavformat/ijkavformat.h"
#include "libavformat/ijkavformat.h"
static const char *kIJKFFRequiredFFmpegVersion = "ff3.0--ijk0.5.0--dev0.4.5--rc11";
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册