Esempio n. 1
0
static int list_read(URLContext *h, unsigned char *buf, int size)
{   
	struct list_mgt *mgt = h->priv_data;
    int len=AVERROR(EIO);
	struct list_item *item=mgt->current_item;
	int retries = 10;
	
retry:	
	if (url_interrupt_cb()){     
		av_log(NULL, AV_LOG_ERROR," url_interrupt_cb\n");	
            	return AVERROR(EINTR);

	}
	//av_log(NULL, AV_LOG_INFO, "list_read start buf=%x,size=%d\n",buf,size);
	if(!mgt->cur_uio )
	{
		if(item && item->file)
		{
			ByteIOContext *bio;
			av_log(NULL, AV_LOG_INFO, "list_read switch to new file=%s\n",item->file);
			len=url_fopen(&bio,item->file,AVIO_FLAG_READ | URL_MINI_BUFFER | URL_NO_LP_BUFFER);
			if(len!=0)
			{
				av_log(NULL, AV_LOG_ERROR, "list url_fopen failed =%d\n",len);
				return len;
			}			
			if(url_is_file_list(bio,item->file))
			{
				mgt->have_sub_list = 1;
				/*have 32 bytes space at the end..*/
				memmove(item->file+5,item->file,strlen(item->file)+1);
				memcpy(item->file,"list:",5);
				url_fclose(bio);
				len=url_fopen(&bio,item->file,mgt->flags | URL_MINI_BUFFER | URL_NO_LP_BUFFER);
				if(len!=0)
				{
					av_log(NULL, AV_LOG_INFO, "file list url_fopen failed =%d\n",len);
					return len;
				}
			}else{
				if(item->ktype == KEY_AES_128){	
					if(item->key_ctx&&!item->crypto){
						item->crypto = av_mallocz(sizeof(struct AESCryptoContext));
						if(!item->crypto){							
							len = AVERROR(ENOMEM);
							return len;
						}
						item->crypto->aes =  av_mallocz(av_aes_size);		
						if(!item->crypto->aes){
							len = AVERROR(ENOMEM);
							return len;
						}
						
						av_aes_init(item->crypto->aes,item->key_ctx->key, 128, 1);
						item->crypto->have_init = 1;
						
					}
					bio->is_encrypted_media =1;
				}				
			}
			mgt->cur_uio=bio;
		}
	}
	if(mgt->cur_uio){
		if(size>0&&mgt->cur_uio->is_encrypted_media>0&&mgt->current_item->key_ctx&&mgt->current_item->crypto){//codes from crypto.c			
			int blocks;
			struct AESCryptoContext* c = mgt->current_item->crypto;
readagain:			
			len = 0;
			if (c->outdata > 0) {
				size = FFMIN(size, c->outdata);
				memcpy(buf, c->outptr, size);
				c->outptr  += size;
				c->outdata -= size;
				len =size;				
			}
			// We avoid using the last block until we've found EOF,
			// since we'll remove PKCS7 padding at the end. So make
			// sure we've got at least 2 blocks, so we can decrypt
			// at least one.
			while (c->indata - c->indata_used < 2*BLOCKSIZE) {
				int n = get_buffer(mgt->cur_uio,c->inbuffer + c->indata,
				                   sizeof(c->inbuffer) - c->indata);
				if (n <= 0) {
				    c->eof = 1;
				    break;
				}
				c->indata += n;				
			}
			blocks = (c->indata - c->indata_used) / BLOCKSIZE;
			if (blocks!=0){
				if (!c->eof)
					blocks--;
				av_aes_crypt(c->aes, c->outbuffer, c->inbuffer + c->indata_used, blocks,mgt->current_item->key_ctx->iv, 1);
				c->outdata      = BLOCKSIZE * blocks;
				c->outptr       = c->outbuffer;
				c->indata_used += BLOCKSIZE * blocks;
				if (c->indata_used >= sizeof(c->inbuffer)/2) {
					memmove(c->inbuffer, c->inbuffer + c->indata_used,
						c->indata - c->indata_used);
					c->indata     -= c->indata_used;
					c->indata_used = 0;
				}
				if (c->eof) {
					// Remove PKCS7 padding at the end
					int padding = c->outbuffer[c->outdata - 1];
					c->outdata -= padding;
				}

				if(len==0){
					goto readagain;
				}
			}else{
				len  =0;
			}				
			
			
		}else{
			len=get_buffer(mgt->cur_uio,buf,size);
		}
		//av_log(NULL, AV_LOG_INFO, "list_read get_buffer=%d\n",len);
	}
	if(len==AVERROR(EAGAIN))
		 return AVERROR(EAGAIN);/*not end,bug need to*/
	else if((len<=0)&& mgt->current_item!=NULL)
	{/*end of the file*/
		av_log(NULL, AV_LOG_INFO, "try switchto_next_item buf=%x,size=%d,len=%d\n",buf,size,len);

		if(item && (item->flags & ENDLIST_FLAG)){
		    if(mgt->cur_uio)
			    url_fclose(mgt->cur_uio);
    			av_log(NULL, AV_LOG_INFO, "ENDLIST_FLAG, return 0\n");
			return 0;
		}

		
		
		item=switchto_next_item(mgt);
		if(!item){
			if(mgt->flags&REAL_STREAMING_FLAG){
				fresh_item_list(mgt);	
				if(retries>0){
					retries --;
					goto retry;
				}
			}

			av_log(NULL, AV_LOG_INFO, "Need more retry by player logic\n");
			return AVERROR(EAGAIN);/*not end,but need to refresh the list later*/
		}
		if(mgt->cur_uio)
			url_fclose(mgt->cur_uio);
		mgt->cur_uio=NULL;
		mgt->current_item=item;
		
		if(item->flags & ENDLIST_FLAG){
			av_log(NULL, AV_LOG_INFO, "reach list end now!,item=%x\n",item);
			return 0;/*endof file*/
		}
		else if(item->flags & DISCONTINUE_FLAG){
			av_log(NULL, AV_LOG_INFO, "Discontiue item \n");
			//1 TODO:need to notify uper level stream is changed
			goto retry;
		}
		else{	
			av_log(NULL, AV_LOG_INFO, "[%s]item->flags=%x \n", __FUNCTION__, item->flags);
			goto retry;
		}
		
	}
	#if 0
	if(mgt->flags&REAL_STREAMING_FLAG&&mgt->item_num<4){ //force refresh items
		fresh_item_list(mgt);	
	}
	#endif

	//av_log(NULL, AV_LOG_INFO, "list_read end buf=%x,size=%d return len=%x\n",buf,size,len);
    return len;
}
static int list_read(URLContext *h, unsigned char *buf, int size)
{   
	struct list_mgt *mgt = h->priv_data;
    int len=AVERROR(EIO);
	struct list_item *item=mgt->current_item;
	
retry:	
	if (url_interrupt_cb())       
            return AVERROR(EINTR); 
	av_log(NULL, AV_LOG_INFO, "list_read start buf=%x,size=%d\n",buf,size);
	if(!mgt->cur_uio )
	{
		if(item && item->file)
		{
			ByteIOContext *bio;
			av_log(NULL, AV_LOG_INFO, "list_read switch to new file=%s\n",item->file);
			len=url_fopen(&bio,item->file,O_RDONLY | URL_MINI_BUFFER | URL_NO_LP_BUFFER);
			if(len!=0)
			{
				return len;
			}
			if(url_is_file_list(bio,item->file))
			{
				/*have 32 bytes space at the end..*/
				memmove(item->file+5,item->file,strlen(item->file)+1);
				memcpy(item->file,"list:",5);
				url_fclose(bio);
				len=url_fopen(&bio,item->file,mgt->flags | URL_MINI_BUFFER | URL_NO_LP_BUFFER);
				if(len!=0)
				{
					return len;
				}
			}
			mgt->cur_uio=bio;
		}
	}
	if(mgt->cur_uio)
		len=get_buffer(mgt->cur_uio,buf,size);
	if(len==AVERROR(EAGAIN))
		 return AVERROR(EAGAIN);/*not end,bug need to*/
	else if((len<=0)&& mgt->current_item!=NULL)
	{/*end of the file*/
		av_log(NULL, AV_LOG_INFO, "try switchto_next_item buf=%x,size=%d,len=%d\n",buf,size,len);

		if(item && (item->flags & ENDLIST_FLAG))
			return 0;
		item=switchto_next_item(mgt);
		if(!item){
			 return AVERROR(EAGAIN);/*not end,but need to refresh the list later*/
		}
		if(mgt->cur_uio)
			url_fclose(mgt->cur_uio);
		mgt->cur_uio=NULL;
		mgt->current_item=item;
		if(item->flags & ENDLIST_FLAG){
			av_log(NULL, AV_LOG_INFO, "reach list end now!,item=%x\n",item);
			return 0;/*endof file*/
		}
		else if(item->flags & DISCONTINUE_FLAG){
			av_log(NULL, AV_LOG_INFO, "Discontiue item \n");
			//1 TODO:need to notify uper level stream is changed
			goto retry;
		}
		else{	
			goto retry;
		}
	}
	av_log(NULL, AV_LOG_INFO, "list_read end buf=%x,size=%d\n",buf,size);
    return len;
}