./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; }