aboutsummaryrefslogtreecommitdiff
path: root/libavformat/playlist.c
diff options
context:
space:
mode:
Diffstat (limited to 'libavformat/playlist.c')
-rw-r--r--libavformat/playlist.c110
1 files changed, 110 insertions, 0 deletions
diff --git a/libavformat/playlist.c b/libavformat/playlist.c
new file mode 100644
index 0000000000..db91a7ca73
--- /dev/null
+++ b/libavformat/playlist.c
@@ -0,0 +1,110 @@
+/*
+ * Internal playlist functions.
+ * Copyright (c) 2011 Anton Khirnov
+ *
+ * This file is part of Libav.
+ *
+ * Libav is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * Libav is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Libav; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "avformat.h"
+#include "internal.h"
+#include "playlist.h"
+#include "libavutil/mem.h"
+
+AVPlaylistContext *ff_playlist_alloc(void)
+{
+ AVPlaylistContext *p = av_mallocz(sizeof(*p));
+ if (!p)
+ return NULL;
+
+ p->cur_elem = -1;
+
+ return p;
+}
+
+void ff_playlist_free(AVPlaylistContext **pls)
+{
+ AVPlaylistContext *p = *pls;
+
+ if (p) {
+ while (p->nb_elems--) {
+ AVPlaylistElement *e = p->elems[p->nb_elems];
+ while (e->nb_filenames--)
+ av_freep(&e->filenames[e->nb_filenames]);
+ av_freep(&e->filenames);
+ av_freep(&p->elems[p->nb_elems]);
+ }
+ av_freep(pls);
+ }
+}
+
+AVPlaylistElement *ff_playlist_add_entry(AVFormatContext *s, const uint8_t *filename)
+{
+ AVPlaylistElement *elem;
+ uint8_t *tmp;
+
+ if (!s->plist && !(s->plist = ff_playlist_alloc()))
+ return NULL;
+
+ if (!(elem = av_mallocz(sizeof(*elem))))
+ return NULL;
+ tmp = av_strdup(filename);
+ dynarray_add(&elem->filenames, &elem->nb_filenames, tmp);
+ dynarray_add(&s->plist->elems, &s->plist->nb_elems, elem);
+ return elem;
+}
+
+int av_playlist_advance(AVFormatContext *s, int offset, AVDictionary **options)
+{
+ AVPlaylistContext *plist = s->plist;
+ AVPlaylistElement *elem;
+ int ret, i;
+
+ if (!plist)
+ return AVERROR(EINVAL);
+
+ if (plist->cur_elem >= 0) {
+ av_close_input_file(plist->elems[plist->cur_elem]->fc);
+ plist->elems[plist->cur_elem]->fc = NULL;
+ plist->cur_elem += offset;
+ } else
+ plist->cur_elem = (offset >= 0 ? -1 : plist->nb_elems) + offset;
+
+ if (plist->cur_elem >= plist->nb_elems || plist->cur_elem < 0) {
+ plist->cur_elem = -1;
+ return AVERROR_EOF;
+ }
+
+ elem = plist->elems[plist->cur_elem];
+ for (i = 0; i < elem->nb_filenames; i++) {
+ AVDictionary *tmp = NULL;
+
+ if (options && i + 1 < elem->nb_filenames)
+ av_dict_copy(&tmp, *options, 0); // save the options for the next attempt if needed
+
+ ret = avformat_open_input(&elem->fc, plist->elems[plist->cur_elem]->filenames[i],
+ NULL, options);
+ if (ret >= 0) {
+ av_dict_free(&tmp);
+ return plist->cur_elem;
+ }
+ av_dict_free(options);
+ *options = tmp;
+ }
+ av_log(s, AV_LOG_ERROR, "Could not open element %d.\n", plist->cur_elem);
+ plist->cur_elem = -1;
+ return ret;
+}