diff --git a/libavformat/oggdec.c b/libavformat/oggdec.c
index 628ef23d8f36c421c831d7297b0fc6be471fc50e..30583c495dc27b271c77c8a94a6e763c1d22db1b 100644
--- a/libavformat/oggdec.c
+++ b/libavformat/oggdec.c
@@ -605,6 +605,10 @@ static int ogg_read_close(AVFormatContext *s)
 
     for (i = 0; i < ogg->nstreams; i++) {
         av_free(ogg->streams[i].buf);
+        if (ogg->streams[i].codec &&
+            ogg->streams[i].codec->cleanup) {
+            ogg->streams[i].codec->cleanup(s, i);
+        }
         av_free(ogg->streams[i].private);
     }
     av_free(ogg->streams);
diff --git a/libavformat/oggdec.h b/libavformat/oggdec.h
index febf8cb6426ea27694ba403f321ce1f1bc83faf5..2a22946099e7f29033a31e60f31da624d16740a7 100644
--- a/libavformat/oggdec.h
+++ b/libavformat/oggdec.h
@@ -55,6 +55,7 @@ struct ogg_codec {
      * Number of expected headers
      */
     int nb_header;
+    void (*cleanup)(AVFormatContext *s, int idx);
 };
 
 struct ogg_stream {
diff --git a/libavformat/oggparsevorbis.c b/libavformat/oggparsevorbis.c
index 7e8f6cede3bf1605203eac6a9619209b437caf6f..5510115bc8bffe0d999cc53f94cb7f4fd8f73d01 100644
--- a/libavformat/oggparsevorbis.c
+++ b/libavformat/oggparsevorbis.c
@@ -192,6 +192,16 @@ fixup_vorbis_headers(AVFormatContext * as, struct oggvorbis_private *priv,
     return offset;
 }
 
+static int vorbis_cleanup(AVFormatContext *s, int idx)
+{
+    struct ogg *ogg = s->priv_data;
+    struct ogg_stream *os = ogg->streams + idx;
+    struct oggvorbis_private *priv = os->private;
+    int i;
+    if (os->private)
+        for (i = 0; i < 3; i++)
+            av_freep(&priv->packet[i]);
+}
 
 static int
 vorbis_header (AVFormatContext * s, int idx)
@@ -373,5 +383,6 @@ const struct ogg_codec ff_vorbis_codec = {
     .magicsize = 7,
     .header = vorbis_header,
     .packet = vorbis_packet,
+    .cleanup= vorbis_cleanup,
     .nb_header = 3,
 };