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