forked from Jackarain/avplayer
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathyouku_demux.cpp
196 lines (148 loc) · 3.86 KB
/
youku_demux.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
#include "internal.h"
#include "globals.h"
#include "youku_demux.h"
#include "avplay.h"
#include "source.h"
#define IO_BUFFER_SIZE 32768
// 具体实现.
int youku_demux::read_data(void *opaque, uint8_t *buf, int buf_size)
{
youku_demux *demux = (youku_demux*)opaque;
// 已经中止播放.
// if (demux->is_abort())
// return 0;
int ret = demux->m_source_ctx->read_data(demux->m_source_ctx, (char*)buf, buf_size);
// 读取失败, 跳过, 这样就可以继续缓冲数据或者跳回前面播放.
if (ret == -1)
return 0;
return ret;
}
int youku_demux::write_data(void *opaque, uint8_t *buf, int buf_size)
{
youku_demux *demux = (youku_demux*)opaque;
return 0;
}
int64_t youku_demux::seek_data(void *opaque, int64_t offset, int whence)
{
youku_demux *demux = (youku_demux*)opaque;
// 已经中止播放.
// if (demux->is_abort())
// return -1;
offset = demux->m_source_ctx->read_seek(demux->m_source_ctx, offset, whence);
if (demux->m_source_ctx->dl_info.not_enough)
{
// TODO: 判断是否数据足够, 如果不足以播放, 则暂停播放.
}
return offset;
}
youku_demux::youku_demux(void)
: m_source_ctx(NULL)
, m_format_ctx(NULL)
, m_io_buffer(NULL)
, m_avio_ctx(NULL)
, m_abort(false)
{}
youku_demux::~youku_demux(void)
{}
int youku_demux::decode_interrupt_cb(void *ctx)
{
youku_demux *demux = (youku_demux*)ctx;
return (int)demux->m_abort;
}
bool youku_demux::open(boost::any ctx)
{
av_register_all();
avformat_network_init();
// 得到传入的参数.
m_youku_demux_data = boost::any_cast<youku_demux_data>(ctx);
BOOST_ASSERT(m_youku_demux_data.type == MEDIA_TYPE_YK);
// 初始化youku的source.
m_source_ctx = alloc_media_source(MEDIA_TYPE_YK,
m_youku_demux_data.youku_url.c_str(), m_youku_demux_data.youku_url.size(), 0);
// 创建m_format_ctx.
m_format_ctx = avformat_alloc_context();
if (!m_format_ctx)
goto FAILED_FLG;
// 设置参数.
m_format_ctx->flags = AVFMT_FLAG_GENPTS;
m_format_ctx->interrupt_callback.callback = decode_interrupt_cb;
m_format_ctx->interrupt_callback.opaque = (void*)this;
m_source_ctx->init_source = yk_init_source;
m_source_ctx->read_data = yk_read_data;
m_source_ctx->read_seek = yk_read_seek;
m_source_ctx->close = yk_close;
m_source_ctx->destory = yk_destory;
// 如果初始化失败.
if (m_source_ctx->init_source(m_source_ctx) < 0)
goto FAILED_FLG;
int ret = 0;
AVInputFormat *iformat = NULL;
m_io_buffer = (unsigned char*)av_malloc(IO_BUFFER_SIZE);
if (!m_io_buffer)
{
std::cerr << "Create buffer failed!\n";
goto FAILED_FLG;
}
// 分配io上下文.
m_avio_ctx = avio_alloc_context(m_io_buffer,
IO_BUFFER_SIZE, 0, (void*)this, read_data, NULL, seek_data);
if (!m_avio_ctx)
{
std::cerr << "Create io context failed!\n";
goto FAILED_FLG;
}
m_avio_ctx->write_flag = 0;
ret = av_probe_input_buffer(m_avio_ctx, &iformat, "", NULL, 0, 0);
if (ret < 0)
{
std::cerr << "av_probe_input_buffer call failed!\n";
goto FAILED_FLG;
}
// 打开输入媒体流.
m_format_ctx->pb = m_avio_ctx;
ret = avformat_open_input(&m_format_ctx, "", iformat, NULL);
if (ret < 0)
{
std::cerr << "av_open_input_stream call failed!\n";
goto FAILED_FLG;
}
ret = avformat_find_stream_info(m_format_ctx, NULL);
if (ret < 0)
goto FAILED_FLG;
FAILED_FLG:
// 遇到出错, 释放各种资源.
if (m_source_ctx)
{
free_media_source(m_source_ctx);
m_source_ctx = NULL;
}
if (m_format_ctx)
{
avformat_close_input(&m_format_ctx);
m_format_ctx = NULL;
}
return false;
}
bool youku_demux::read_packet(AVPacket *pkt)
{
return false;
}
bool youku_demux::seek_packet(int64_t timestamp)
{
return false;
}
bool youku_demux::stream_index(enum AVMediaType type, int &index)
{
return false;
}
bool youku_demux::query_avcodec_id(int index, enum AVCodecID &codec_id)
{
return false;
}
void youku_demux::close()
{
}
media_base_info youku_demux::base_info()
{
return media_base_info();
}