diff options
Diffstat (limited to 'libavformat/playlist.c')
-rw-r--r-- | libavformat/playlist.c | 110 |
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; +} |