前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >基于ffmpeg的wince版本网络收音机开发

基于ffmpeg的wince版本网络收音机开发

作者头像
雪影
发布2018-08-02 11:59:54
7720
发布2018-08-02 11:59:54
举报
文章被收录于专栏:流媒体人生

基于FFMPEG的Wince版本网络收音机设计与开发

软件架构设计

模块依赖关系图

FFMPEG的编译移植

代码语言:javascript
复制
./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

Msdl模块的移植

Ffmpeg IO模块的实现,URLProtocol接口的实现

代码语言:javascript
复制
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;
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2012年11月02日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 基于FFMPEG的Wince版本网络收音机设计与开发
    • 软件架构设计
      • 模块依赖关系图
        • FFMPEG的编译移植
          • Msdl模块的移植
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档