./configure \
--enable-cross-compile \
--enable-memalign-hack \
--target-os=mingw32ce \
--arch=armv4 \
--cross-prefix=arm-wince-mingw32ce- \
--enable-small \
--disable-static \
--enable-shared \
--disable-doc \
--disable-ffplay \
--disable-ffmpeg \
--disable-ffprobe \
--disable-ffserver \
--disable-encoders \
--disable-network \
--disable-muxers \
--disable-protocols \
--enable-protocol=file \
--prefix=armv4 \
--extra-cflags="-march=armv4 -mtune=xscale" \
>armv4.txt
Ffmpeg IO模块的实现,URLProtocol接口的实现
typedef struct _RadioContext{
struct stream_t* stream;
} RadioContext;
static int stream_open(URLContext *h, const char *uri, int flags)
{
RadioContext* rc = h->priv_data;
struct url_t *url=NULL;
struct download_opts_t *dlopts=NULL;
struct stream_t* stream=NULL;
int ret = 0;
char* prawuri = NULL; //原始的uri路径
char* filepath = NULL;
//printf("%d:%s\n", __LINE__,__FUNCTION__);
netstatus_changed(CONNECTING);
prawuri = strdup(uri+strlen("radio://"));
while (1)
{
ret = prepare_open(prawuri,&url,&dlopts);
if(ret <= 0) {
goto failed;
}
ret = streaming_open(url,dlopts,&stream);
if(ret <= 0) {
goto failed;
}
if(!is_metafile(prawuri))
break;
//下载跳转文件
{
char* p = getprocessfilepath();
char* buffer = (uint8_t *)xmalloc(BUFSIZE_4_DL);
filepath = malloc(256);
strcpy(filepath,p);
free(p);
p = strrchr(filepath,'\\');
sprintf(p+1,"%s","metafile");
ret = streaming_read(stream,buffer,BUFSIZE_4_DL,filepath);
free(buffer);
if(ret < 0)
goto failed;
}
//分析跳转文件,解析出url连接
{
struct list_h *p = NULL; /* iterator */
struct list_h *target_str_list = NULL; /* string */
ret = get_url_list_from_file(filepath,&target_str_list);
if(ret < 0) { /*could not open file*/
goto failed;
}
else if(ret == 0) {
display(MSDL_ERR,"input file \"%s\" does not contain any url\n",filepath);
goto failed;
}
p = target_str_list;
if(p && p->next) //不支持多目标播放
{
display(MSDL_ERR,"\n\nDo not support multi-target objects\n\n",filepath);
//输出所有的连接地址
while(p)
{
display(MSDL_ERR,"radio url:%s\n",(char*)p->p);
p = p->next;
}
//查找第一个mms或rtsp协议的地址,非http
p = target_str_list;
while(p)
{
if(strstr(p->p,"mms://") || strstr(p->p,"rtsp://"))
break;
p = p->next;
}
}
//释放资源
free_stream(stream);
url = NULL;
dlopts = NULL;
stream = NULL;
if(filepath) free(filepath);
if(prawuri) free(prawuri);
//如果没有合适的地址,则直接返回
if(!p)
goto failed;
prawuri = strdup(p->p);
}
}
//printf("%d:%s\n", __LINE__,__FUNCTION__);
h->is_streamed = 1;
rc->stream = stream;
if(prawuri) free(prawuri);
return 0;
failed:
if(url) free_url_t(url);
if(dlopts) free_download_opts_t(dlopts);
if(filepath) free(filepath);
if(prawuri) free(prawuri);
if(stream) stream->close(stream);
netstatus_changed(CONNECT_FAILED);
return -1;
}
static int stream_close(URLContext *h)
{
RadioContext* rc = h->priv_data;
struct stream_t *stream = rc->stream;
//增加快速退出代码行
if(stream)
{
if(stream->url)
free_url_t(stream->url);
if(stream->dlopts)
free_download_opts_t(stream->dlopts);
//必须在上两句代码行之后调用,不然会出异常
stream->close(stream);
rc->stream = NULL;
}
return 0;
}
static int radio_open(URLContext *h, const char *uri, int flags)
{
bStopStream = 0;
return stream_open(h,uri,flags);
}
static int radio_close(URLContext *h)
{
stream_close(h);
netstatus_changed(STOPPED);
return 0;
}
static int radio_read(URLContext *h, uint8_t *buf, int size)
{
int ret = 0;
RadioContext* rc = h->priv_data;
struct stream_t *stream = rc->stream;
while(1)
{
if(stream)
ret = streaming_read(stream,buf,size,0);
if(stream && ret > 0)
{
netstatus_changed(DOWNLOADING);
break;
}
else //获取数据失败,掉线重连
{
notify_netstatus func = func_cb;
func_cb = NULL; //暂停网络状态回调
stream_close(h);
func_cb = func; //开启网络状态回调
if(bStopStream){
netstatus_changed(CONNECT_FAILED);
break;
}
printf("%d:%s retry open server\n",__LINE__,__FUNCTION__);
//重新打开
ret = stream_open(h,h->filename,h->flags);
if(ret < 0)
break;
rc = h->priv_data;
stream = rc->stream;
}
}
return ret;
}
URLProtocol ff_radio_protocol = {
"radio",
radio_open,
radio_read,
0,
0,
radio_close,
/*next*/ NULL,
/*url_read_pause*/ NULL,
/*url_read_seek*/ NULL,
/*url_get_file_handle*/NULL,
/*priv_data_size*/ sizeof(RadioContext),
};
MSDLAPI void StopStreamData()
{
bStopStream = 1;
}
MSDLAPI URLProtocol* RadioProtocol()
{
return &ff_radio_protocol;
}