static int64_t cache_seek(URLContext *h, int64_t pos, int whence) { Context *c= (Context *)h->priv_data; if (whence == AVSEEK_SIZE) { pos= ffurl_seek(c->inner, pos, whence); if(pos <= 0){ pos= ffurl_seek(c->inner, -1, SEEK_END); ffurl_seek(c->inner, c->end, SEEK_SET); if(pos <= 0) return c->end; } return pos; } pos= lseek(c->fd, pos, whence); if(pos<0){ return pos; }else if(pos <= c->end){ c->pos= pos; return pos; }else{ lseek(c->fd, c->pos, SEEK_SET); return AVERROR(EPIPE); } }
static int64_t concat_seek(URLContext *h, int64_t pos, int whence) { int64_t result; struct concat_data *data = h->priv_data; struct concat_nodes *nodes = data->nodes; size_t i; switch (whence) { case SEEK_END: for (i = data->length - 1; i && pos < -nodes[i].size; i--) pos += nodes[i].size; break; case SEEK_CUR: /* get the absolute position */ for (i = 0; i != data->current; i++) pos += nodes[i].size; pos += ffurl_seek(nodes[i].uc, 0, SEEK_CUR); whence = SEEK_SET; /* fall through with the absolute position */ case SEEK_SET: for (i = 0; i != data->length - 1 && pos >= nodes[i].size; i++) pos -= nodes[i].size; break; default: return AVERROR(EINVAL); } result = ffurl_seek(nodes[i].uc, pos, whence); if (result >= 0) { data->current = i; while (i) result += nodes[--i].size; } return result; }
int64_t ffurl_size(URLContext *h) { int64_t pos, size; size= ffurl_seek(h, 0, AVSEEK_SIZE); if(size<0){ pos = ffurl_seek(h, 0, SEEK_CUR); if ((size = ffurl_seek(h, -1, SEEK_END)) < 0) return size; size++; ffurl_seek(h, pos, SEEK_SET); } return size; }
int64_t AVFRingBuffer::AVF_Seek_Packet(void *opaque, int64_t offset, int whence) { if (!opaque) return 0; return ffurl_seek((URLContext *)opaque, offset, whence); }
static int64_t cache_seek(URLContext *h, int64_t pos, int whence) { Context *c= (Context*)h->priv_data; int64_t ret; if(AVSEEK_SIZE != whence){ av_log(h, AV_LOG_ERROR, "c->inner->filename:%s,ucache seek!!!:pos=%lld,c->pos=%lld,whence=%d\n",c->inner->filename,pos,c->pos,whence); } ret = ffurl_seek(c->inner, pos, whence); if( ret >=0 ) { if(AVSEEK_SIZE != whence){ av_log(h, AV_LOG_ERROR, "ffurl_seek = %lld\n",ret); pos= lseek(c->fd, pos, whence); if(pos != ret){ av_log(h, AV_LOG_ERROR, "lseek pos != ret pos=%lld",pos); }else{ c->pos = ret; } } } return ret; }
static int cache_read(URLContext *h, unsigned char *buf, int size) { Context *c= (Context*)h->priv_data; int r = 0; //av_log(h, AV_LOG_INFO, "cache_read enter\n",r); r = ffurl_read(c->inner, buf, size); if( r > 0 && c->fd >= 0 ){ int64_t size; //av_log(h, AV_LOG_INFO, "cache_read = %d bytes\n",r); int r2= write(c->fd, buf, r); av_assert0(r2==r); // FIXME handle cache failure c->pos += r; c->end += r; //判断是否缓存完毕 size = ffurl_seek(c->inner, 0, AVSEEK_SIZE); if( size == c->pos && c->end >= size ){ if(c->local_buffer_path)notifyCacheEnd(h,1); av_log(h, AV_LOG_INFO, "ucache: ok1\n"); close(c->fd); c->fd = -1; } }else{ if(c->fd >=0)av_log(h, AV_LOG_ERROR, "cache_read:ffurl_read failed\n",r); } return r; }
static int cache_close(URLContext *h) { int64_t size; Context *c= (Context*)h->priv_data; if(c->fd >= 0)close(c->fd); //判断是否需要保存 if(c->local_buffer_path && c->fd >= 0){ size = ffurl_seek(c->inner, 0, AVSEEK_SIZE); if( size != c->pos || c->end < size ){ //删除文件 unlink(c->local_buffer_path); av_log(h, AV_LOG_INFO, "ucache: failed size=%lld,c->pos=%lld,c->end=%lld\n",size,c->pos,c->end); //通知上层缓存失败 if(c->local_buffer_path)notifyCacheEnd(h,0); }else{ //通知上层缓存成功 if(c->local_buffer_path)notifyCacheEnd(h,1); av_log(h, AV_LOG_INFO, "ucache: ok2\n"); } } ffurl_close(c->inner); return 0; }
int ffurl_connect(URLContext *uc, AVDictionary **options) { int err; AVDictionary *tmp_opts = NULL; AVDictionaryEntry *e; if (!options) options = &tmp_opts; // Check that URLContext was initialized correctly and lists are matching if set av_assert0(!(e=av_dict_get(*options, "protocol_whitelist", NULL, 0)) || (uc->protocol_whitelist && !strcmp(uc->protocol_whitelist, e->value))); av_assert0(!(e=av_dict_get(*options, "protocol_blacklist", NULL, 0)) || (uc->protocol_blacklist && !strcmp(uc->protocol_blacklist, e->value))); if (uc->protocol_whitelist && av_match_list(uc->prot->name, uc->protocol_whitelist, ',') <= 0) { av_log(uc, AV_LOG_ERROR, "Protocol not on whitelist \'%s\'!\n", uc->protocol_whitelist); return AVERROR(EINVAL); } if (uc->protocol_blacklist && av_match_list(uc->prot->name, uc->protocol_blacklist, ',') > 0) { av_log(uc, AV_LOG_ERROR, "Protocol blacklisted \'%s\'!\n", uc->protocol_blacklist); return AVERROR(EINVAL); } if (!uc->protocol_whitelist && uc->prot->default_whitelist) { av_log(uc, AV_LOG_DEBUG, "Setting default whitelist '%s'\n", uc->prot->default_whitelist); uc->protocol_whitelist = av_strdup(uc->prot->default_whitelist); if (!uc->protocol_whitelist) { return AVERROR(ENOMEM); } } else if (!uc->protocol_whitelist) av_log(uc, AV_LOG_DEBUG, "No default whitelist set\n"); // This should be an error once all declare a default whitelist if ((err = av_dict_set(options, "protocol_whitelist", uc->protocol_whitelist, 0)) < 0) return err; if ((err = av_dict_set(options, "protocol_blacklist", uc->protocol_blacklist, 0)) < 0) return err; err = uc->prot->url_open2 ? uc->prot->url_open2(uc, uc->filename, uc->flags, options) : uc->prot->url_open(uc, uc->filename, uc->flags); av_dict_set(options, "protocol_whitelist", NULL, 0); av_dict_set(options, "protocol_blacklist", NULL, 0); if (err) return err; uc->is_connected = 1; /* We must be careful here as ffurl_seek() could be slow, * for example for http */ if ((uc->flags & AVIO_FLAG_WRITE) || !strcmp(uc->prot->name, "file")) if (!uc->is_streamed && ffurl_seek(uc, 0, SEEK_SET) < 0) uc->is_streamed = 1; return 0; }
int ffurl_connect(URLContext* uc) { int err = uc->prot->url_open(uc, uc->filename, uc->flags); if (err) return err; uc->is_connected = 1; //We must be careful here as ffurl_seek() could be slow, for example for http if( (uc->flags & AVIO_FLAG_WRITE) || !strcmp(uc->prot->name, "file")) if(!uc->is_streamed && ffurl_seek(uc, 0, SEEK_SET) < 0) uc->is_streamed= 1; return 0; }
static int slave_seek(URLContext *h) { SubfileContext *c = h->priv_data; int64_t ret; if ((ret = ffurl_seek(c->h, c->pos, SEEK_SET)) != c->pos) { if (ret >= 0) ret = AVERROR_BUG; av_log(h, AV_LOG_ERROR, "Impossible to seek in file: %s\n", av_err2str(ret)); return ret; } return 0; }
long long StreamingRingBuffer::Seek(long long pos, int whence, bool has_lock) { if (!m_context) return 0; poslock.lockForWrite(); int seek = ffurl_seek(m_context, pos, whence); poslock.unlock(); if (seek < 0) { ateof = true; return 0; } return pos; }
bool StreamingRingBuffer::OpenFile(const QString &lfilename, uint retry_ms) { avcodeclock->lock(); av_register_all(); avcodeclock->unlock(); RingBuffer::AVFormatInitNetwork(); rwlock.lockForWrite(); safefilename = lfilename; filename = lfilename; // TODO check whether local area file QUrl url = filename; if (url.path().endsWith(QLatin1String("m3u8"), Qt::CaseInsensitive)) { url.setScheme("hls+http"); } int res = ffurl_open(&m_context, url.toString().toLatin1(), AVIO_FLAG_READ, NULL, NULL); if (res >=0 && m_context && !m_context->is_streamed && ffurl_seek(m_context, 0, SEEK_SET) >= 0) { m_streamed = false; m_allowSeeks = true; } LOG(VB_GENERAL, LOG_INFO, LOC + QString("Trying %1 (allow seeks: %2") .arg(filename).arg(m_allowSeeks)); rwlock.unlock(); if (res < 0 || !m_context) { LOG(VB_GENERAL, LOG_ERR, LOC + QString("Failed to open stream (error %1)") .arg(res)); return false; } return true; }
static int concat_read(URLContext *h, unsigned char *buf, int size) { int result, total = 0; struct concat_data *data = h->priv_data; struct concat_nodes *nodes = data->nodes; size_t i = data->current; while (size > 0) { result = ffurl_read(nodes[i].uc, buf, size); if (result < 0) return total ? total : result; if (!result) if (i + 1 == data->length || ffurl_seek(nodes[++i].uc, 0, SEEK_SET) < 0) break; total += result; buf += result; size -= result; } data->current = i; return total; }
static int64_t CacheHttp_ffurl_seek(URLContext *h, int64_t pos, int whence) { return ffurl_seek(h, pos, whence); }
int64_t url_seek(URLContext *h, int64_t pos, int whence) { return ffurl_seek(h, pos, whence); }
static int64_t crypto_seek(URLContext *h, int64_t pos, int whence) { CryptoContext *c = h->priv_data; int64_t block; int64_t newpos; if (c->flags & AVIO_FLAG_WRITE) { av_log(h, AV_LOG_ERROR, "Crypto: seek not supported for write\r\n"); /* seems the most appropriate error to return */ return AVERROR(ESPIPE); } // reset eof, else we won't read it correctly if we already hit eof. c->eof = 0; switch (whence) { case SEEK_SET: break; case SEEK_CUR: pos = pos + c->position; break; case SEEK_END: { int64_t newpos = ffurl_seek( c->hd, pos, AVSEEK_SIZE ); if (newpos < 0) { av_log(h, AV_LOG_ERROR, "Crypto: seek_end - can't get file size (pos=%lld)\r\n", (long long int)pos); return newpos; } pos = newpos - pos; } break; case AVSEEK_SIZE: { int64_t newpos = ffurl_seek( c->hd, pos, AVSEEK_SIZE ); return newpos; } break; default: av_log(h, AV_LOG_ERROR, "Crypto: no support for seek where 'whence' is %d\r\n", whence); return AVERROR(EINVAL); } c->outdata = 0; c->indata = 0; c->indata_used = 0; c->outptr = c->outbuffer; // identify the block containing the IV for the // next block we will decrypt block = pos/BLOCKSIZE; if (block == 0) { // restore the iv to the seed one - this is the iv for the FIRST block memcpy( c->decrypt_iv, c->iv, c->ivlen ); c->position = 0; } else { // else, go back one block - we will get av_cyrpt to read this block // which it will then store use as the iv. // note that the DECRYPTED result will not be correct, // but will be discarded block--; c->position = (block * BLOCKSIZE); } newpos = ffurl_seek( c->hd, c->position, SEEK_SET ); if (newpos < 0) { av_log(h, AV_LOG_ERROR, "Crypto: nested protocol no support for seek or seek failed\n"); return newpos; } // read and discard from here up to required position // (which will set the iv correctly to it). if (pos - c->position) { uint8_t buff[BLOCKSIZE*2]; // maximum size of pos-c->position int len = pos - c->position; int res; while (len > 0) { // note: this may not return all the bytes first time res = crypto_read(h, buff, len); if (res < 0) break; len -= res; } // if we did not get all the bytes if (len != 0) { char errbuf[100] = "unknown error"; av_strerror(res, errbuf, sizeof(errbuf)); av_log(h, AV_LOG_ERROR, "Crypto: discard read did not get all the bytes (%d remain) - read returned (%d)-%s\n", len, res, errbuf); return AVERROR(EINVAL); } } return c->position; }