return NULL;
}
- int av_get_packet(AVIOContext *s, AVPacket *pkt, int size)
+ /* an arbitrarily chosen "sane" max packet size -- 50M */
+ #define SANE_CHUNK_SIZE (50000000)
+
+int ffio_limit(AVIOContext *s, int size)
+{
+ if(s->maxsize>=0){
+ int64_t remaining= s->maxsize - avio_tell(s);
+ if(remaining < size){
+ int64_t newsize= avio_size(s);
+ if(!s->maxsize || s->maxsize<newsize)
+ s->maxsize= newsize - !newsize;
+ remaining= s->maxsize - avio_tell(s);
+ remaining= FFMAX(remaining, 0);
+ }
+
+ if(s->maxsize>=0 && remaining+1 < size){
+ av_log(NULL, remaining ? AV_LOG_ERROR : AV_LOG_DEBUG, "Truncating packet of size %d to %"PRId64"\n", size, remaining+1);
+ size= remaining+1;
+ }
+ }
+ return size;
+}
+
+ /*
+ * Read the data in sane-sized chunks and append to pkt.
+ * Return the number of bytes read or an error.
+ */
+ static int append_packet_chunked(AVIOContext *s, AVPacket *pkt, int size)
{
- int ret;
- int orig_size = size;
- size= ffio_limit(s, size);
+ int64_t chunk_size = size;
+ int orig_pos = pkt->pos; // av_grow_packet might reset pos
+ int orig_size = pkt->size;
+ int ret = 0;
+
+ do {
+ int prev_size = pkt->size;
+ int read_size;
+
+ /*
+ * When the caller requests a lot of data, limit it to the amount left
+ * in file or SANE_CHUNK_SIZE when it is not known
+ */
++#if 0
+ if (size > SANE_CHUNK_SIZE) {
+ int64_t filesize = avio_size(s) - avio_tell(s);
+ chunk_size = FFMAX(filesize, SANE_CHUNK_SIZE);
+ }
+ read_size = FFMIN(size, chunk_size);
++#else
++ read_size = size;
++ if (read_size > SANE_CHUNK_SIZE/10) {
++ read_size = ffio_limit(s, read_size);
++ // If filesize/maxsize is unknown, limit to SANE_CHUNK_SIZE
++ if (s->maxsize < 0)
++ read_size = FFMIN(read_size, SANE_CHUNK_SIZE);
++ }
++#endif
- ret= av_new_packet(pkt, size);
+ ret = av_grow_packet(pkt, read_size);
+ if (ret < 0)
+ break;
- if(ret<0)
- return ret;
+ ret = avio_read(s, pkt->data + prev_size, read_size);
+ if (ret != read_size) {
+ av_shrink_packet(pkt, prev_size + FFMAX(ret, 0));
+ break;
+ }
- pkt->pos= avio_tell(s);
+ size -= read_size;
+ } while (size > 0);
++ if (size > 0)
++ pkt->flags |= AV_PKT_FLAG_CORRUPT;
- ret= avio_read(s, pkt->data, size);
- if(ret<=0)
+ pkt->pos = orig_pos;
+ if (!pkt->size)
av_free_packet(pkt);
- else
- av_shrink_packet(pkt, ret);
- if (pkt->size < orig_size)
- pkt->flags |= AV_PKT_FLAG_CORRUPT;
+ return pkt->size > orig_size ? pkt->size - orig_size : ret;
+ }
+
+ int av_get_packet(AVIOContext *s, AVPacket *pkt, int size)
+ {
+ av_init_packet(pkt);
+ pkt->data = NULL;
+ pkt->size = 0;
+ pkt->pos = avio_tell(s);
- return ret;
+ return append_packet_chunked(s, pkt, size);
}
int av_append_packet(AVIOContext *s, AVPacket *pkt, int size)