• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • Examples
  • File List
  • Globals

libavformat/ffmetadec.c

Go to the documentation of this file.
00001 /*
00002  * Metadata demuxer
00003  * Copyright (c) 2010 Anton Khirnov
00004  *
00005  * This file is part of Libav.
00006  *
00007  * Libav is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * Libav is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with Libav; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00020  */
00021 
00022 #include "libavutil/mathematics.h"
00023 #include "avformat.h"
00024 #include "ffmeta.h"
00025 #include "internal.h"
00026 #include "libavutil/dict.h"
00027 
00028 static int probe(AVProbeData *p)
00029 {
00030     if(!memcmp(p->buf, ID_STRING, strlen(ID_STRING)))
00031         return AVPROBE_SCORE_MAX;
00032     return 0;
00033 }
00034 
00035 static void get_line(AVIOContext *s, uint8_t *buf, int size)
00036 {
00037     do {
00038         uint8_t c;
00039         int i = 0;
00040 
00041         while ((c = avio_r8(s))) {
00042             if (c == '\\') {
00043                 if (i < size - 1)
00044                     buf[i++] = c;
00045                 c = avio_r8(s);
00046             } else if (c == '\n')
00047                 break;
00048 
00049             if (i < size - 1)
00050                 buf[i++] = c;
00051         }
00052         buf[i] = 0;
00053     } while (!s->eof_reached && (buf[0] == ';' || buf[0] == '#' || buf[0] == 0));
00054 }
00055 
00056 static AVChapter *read_chapter(AVFormatContext *s)
00057 {
00058     uint8_t line[256];
00059     int64_t start, end;
00060     AVRational tb = {1, 1e9};
00061 
00062     get_line(s->pb, line, sizeof(line));
00063 
00064     if (sscanf(line, "TIMEBASE=%d/%d", &tb.num, &tb.den))
00065         get_line(s->pb, line, sizeof(line));
00066     if (!sscanf(line, "START=%"SCNd64, &start)) {
00067         av_log(s, AV_LOG_ERROR, "Expected chapter start timestamp, found %s.\n", line);
00068         start = (s->nb_chapters && s->chapters[s->nb_chapters - 1]->end != AV_NOPTS_VALUE) ?
00069                  s->chapters[s->nb_chapters - 1]->end : 0;
00070     } else
00071         get_line(s->pb, line, sizeof(line));
00072 
00073     if (!sscanf(line, "END=%"SCNd64, &end)) {
00074         av_log(s, AV_LOG_ERROR, "Expected chapter end timestamp, found %s.\n", line);
00075         end = AV_NOPTS_VALUE;
00076     }
00077 
00078     return avpriv_new_chapter(s, s->nb_chapters, tb, start, end, NULL);
00079 }
00080 
00081 static uint8_t *unescape(uint8_t *buf, int size)
00082 {
00083     uint8_t *ret = av_malloc(size + 1);
00084     uint8_t *p1  = ret, *p2 = buf;
00085 
00086     if (!ret)
00087         return NULL;
00088 
00089     while (p2 < buf + size) {
00090         if (*p2 == '\\')
00091             p2++;
00092         *p1++ = *p2++;
00093     }
00094     *p1 = 0;
00095     return ret;
00096 }
00097 
00098 static int read_tag(uint8_t *line, AVDictionary **m)
00099 {
00100     uint8_t *key, *value, *p = line;
00101 
00102     /* find first not escaped '=' */
00103     while (1) {
00104         if (*p == '=')
00105             break;
00106         else if (*p == '\\')
00107             p++;
00108 
00109         if (*p++)
00110             continue;
00111 
00112         return 0;
00113     }
00114 
00115     if (!(key = unescape(line, p - line)))
00116         return AVERROR(ENOMEM);
00117     if (!(value = unescape(p + 1, strlen(p + 1)))) {
00118         av_free(key);
00119         return AVERROR(ENOMEM);
00120     }
00121 
00122     av_dict_set(m, key, value, AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);
00123     return 0;
00124 }
00125 
00126 static int read_header(AVFormatContext *s, AVFormatParameters *ap)
00127 {
00128     AVDictionary **m = &s->metadata;
00129     uint8_t line[1024];
00130 
00131     while(!s->pb->eof_reached) {
00132         get_line(s->pb, line, sizeof(line));
00133 
00134         if (!memcmp(line, ID_STREAM, strlen(ID_STREAM))) {
00135             AVStream *st = avformat_new_stream(s, NULL);
00136 
00137             if (!st)
00138                 return -1;
00139 
00140             st->codec->codec_type = AVMEDIA_TYPE_DATA;
00141             st->codec->codec_id   = CODEC_ID_FFMETADATA;
00142 
00143             m = &st->metadata;
00144         } else if (!memcmp(line, ID_CHAPTER, strlen(ID_CHAPTER))) {
00145             AVChapter *ch = read_chapter(s);
00146 
00147             if (!ch)
00148                 return -1;
00149 
00150             m = &ch->metadata;
00151         } else
00152             read_tag(line, m);
00153     }
00154 
00155     s->start_time = 0;
00156     if (s->nb_chapters)
00157         s->duration = av_rescale_q(s->chapters[s->nb_chapters - 1]->end,
00158                                    s->chapters[s->nb_chapters - 1]->time_base,
00159                                    AV_TIME_BASE_Q);
00160 
00161     return 0;
00162 }
00163 
00164 static int read_packet(AVFormatContext *s, AVPacket *pkt)
00165 {
00166     return AVERROR_EOF;
00167 }
00168 
00169 AVInputFormat ff_ffmetadata_demuxer = {
00170     .name        = "ffmetadata",
00171     .long_name   = NULL_IF_CONFIG_SMALL("FFmpeg metadata in text format"),
00172     .read_probe  = probe,
00173     .read_header = read_header,
00174     .read_packet = read_packet,
00175 };
Generated on Thu Jan 24 2013 17:08:55 for Libav by doxygen 1.7.1