libavformat/segment.c

Go to the documentation of this file.
00001 /*
00002  * Generic Segmenter
00003  * Copyright (c) 2011, Luca Barbato
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/avstring.h"
00023 #include "libavutil/log.h"
00024 #include "libavutil/opt.h"
00025 #include "libavutil/mathematics.h"
00026 #include "libavutil/parseutils.h"
00027 #include "avformat.h"
00028 #include "internal.h"
00029 #include <strings.h>
00030 #include <float.h>
00031 
00032 typedef struct {
00033 const AVClass *class; 
00034 int number;
00035 AVFormatContext *avf;
00036 char *format; 
00037 char *pattern; 
00038 char *path; 
00039 float time; 
00040 int64_t offset_time;
00041 int64_t recording_time;
00042 } SegmentContext;
00043 
00044 #if CONFIG_SEGMENT_MUXER
00045 
00046 static int segment_header(SegmentContext *s)
00047 {
00048 AVFormatContext *oc = s->avf;
00049 int err = 0;
00050 
00051 av_strlcpy(oc->filename, s->path, sizeof(oc->filename));
00052 
00053 av_strlcatf(oc->filename, sizeof(oc->filename),
00054 s->pattern, s->number++);
00055 
00056 if ((err = avio_open(&oc->pb, oc->filename, AVIO_FLAG_WRITE)) < 0) {
00057 return err;
00058 }
00059 
00060 if (!oc->priv_data && oc->oformat->priv_data_size > 0) {
00061 oc->priv_data = av_mallocz(oc->oformat->priv_data_size);
00062 if (!oc->priv_data) {
00063 avio_close(oc->pb);
00064 return AVERROR(ENOMEM);
00065 }
00066 }
00067 
00068 if ((err = oc->oformat->write_header(oc)) < 0) {
00069 avio_close(oc->pb);
00070 av_freep(&oc->priv_data);
00071 }
00072 
00073 return err;
00074 }
00075 
00076 static int segment_trailer(AVFormatContext *oc)
00077 {
00078 int ret = 0;
00079 
00080 if(oc->oformat->write_trailer)
00081 ret = oc->oformat->write_trailer(oc);
00082 
00083 avio_close(oc->pb);
00084 av_freep(&oc->priv_data);
00085 
00086 return ret;
00087 }
00088 
00089 static int seg_write_header(AVFormatContext *s)
00090 {
00091 SegmentContext *seg = s->priv_data;
00092 AVFormatContext *oc;
00093 int ret;
00094 
00095 seg->number = 0;
00096 seg->recording_time = seg->time*1000000;
00097 seg->offset_time = 0;
00098 
00099 if (!seg->path) {
00100 char *t;
00101 seg->path = av_strdup(s->filename);
00102 t = strrchr(seg->path, '.');
00103 if (t) *t = '0円';
00104 }
00105 
00106 oc = avformat_alloc_context();
00107 
00108 if (!oc) {
00109 return AVERROR(ENOMEM);
00110 }
00111 
00112 oc->oformat = av_guess_format(seg->format, NULL, NULL);
00113 
00114 if (!oc->oformat) {
00115 avformat_free_context(oc);
00116 return AVERROR_MUXER_NOT_FOUND;
00117 }
00118 
00119 seg->avf = oc;
00120 
00121 oc->streams = s->streams;
00122 oc->nb_streams = s->nb_streams;
00123 
00124 av_strlcpy(oc->filename, seg->path, sizeof(oc->filename));
00125 
00126 av_strlcatf(oc->filename, sizeof(oc->filename),
00127 seg->pattern, seg->number++);
00128 
00129 if ((ret = avio_open(&oc->pb, oc->filename, AVIO_FLAG_WRITE)) < 0) {
00130 avformat_free_context(oc);
00131 return ret;
00132 }
00133 
00134 if ((ret = avformat_write_header(oc, NULL)) < 0) {
00135 avio_close(oc->pb);
00136 }
00137 
00138 if (ret)
00139 avformat_free_context(oc);
00140 
00141 avio_printf(s->pb, "%s\n", oc->filename);
00142 avio_flush(s->pb);
00143 
00144 return ret;
00145 }
00146 
00147 static int seg_write_packet(AVFormatContext *s, AVPacket *pkt)
00148 {
00149 SegmentContext *seg = s->priv_data;
00150 AVFormatContext *oc = seg->avf;
00151 AVStream *st = oc->streams[pkt->stream_index];
00152 int ret;
00153 
00154 if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO &&
00155 av_compare_ts(pkt->pts, st->time_base,
00156 seg->recording_time*seg->number,
00157 (AVRational){1, 1000000}) >= 0 &&
00158 pkt->flags & AV_PKT_FLAG_KEY) {
00159 av_log(s, AV_LOG_INFO, "I'd reset at %d %"PRId64"\n",
00160 pkt->stream_index, pkt->pts);
00161 
00162 ret = segment_trailer(oc);
00163 if (!ret)
00164 ret = segment_header(seg);
00165 
00166 if (ret) {
00167 avformat_free_context(oc);
00168 return ret;
00169 }
00170 avio_printf(s->pb, "%s\n", oc->filename);
00171 avio_flush(s->pb);
00172 }
00173 
00174 ret = oc->oformat->write_packet(oc, pkt);
00175 
00176 return ret;
00177 }
00178 
00179 static int seg_write_trailer(struct AVFormatContext *s)
00180 {
00181 SegmentContext *seg = s->priv_data;
00182 AVFormatContext *oc = seg->avf;
00183 
00184 return segment_trailer(oc);
00185 }
00186 
00187 #endif /* CONFIG_SEGMENT_MUXER */
00188 
00189 #define OFFSET(x) offsetof(SegmentContext, x)
00190 #define E AV_OPT_FLAG_ENCODING_PARAM
00191 static const AVOption options[] = {
00192 { "container_format", "container format used for the segments", OFFSET(format), AV_OPT_TYPE_STRING, {.str = "nut"}, 0, 0, E },
00193 { "segment_time", "segment lenght in seconds", OFFSET(time), AV_OPT_TYPE_FLOAT, {.dbl = 2}, 0, FLT_MAX, E },
00194 { "segment_pattern", "pattern to use in segment files", OFFSET(pattern),AV_OPT_TYPE_STRING, {.str = "%03d"}, 0, 0, E },
00195 { "segment_basename", "basename to use in segment files", OFFSET(path ),AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E },
00196 { NULL },
00197 };
00198 
00199 static const AVClass seg_class = {
00200 .class_name = "segment muxer",
00201 .item_name = av_default_item_name,
00202 .option = options,
00203 .version = LIBAVUTIL_VERSION_INT,
00204 };
00205 
00206 /* input
00207 #if CONFIG_IMAGE2_DEMUXER
00208 AVInputFormat ff_image2_demuxer = {
00209  .name = "image2",
00210  .long_name = NULL_IF_CONFIG_SMALL("image2 sequence"),
00211  .priv_data_size = sizeof(VideoData),
00212  .read_probe = read_probe,
00213  .read_header = read_header,
00214  .read_packet = read_packet,
00215  .flags = AVFMT_NOFILE,
00216  .priv_class = &img2_class,
00217 };
00218 #endif
00219 */
00220 
00221 /* output */
00222 #if CONFIG_SEGMENT_MUXER
00223 AVOutputFormat ff_segment_muxer = {
00224 .name = "segment",
00225 .long_name = NULL_IF_CONFIG_SMALL("segment muxer"),
00226 .extensions = "m3u8",
00227 .priv_data_size = sizeof(SegmentContext),
00228 .flags = AVFMT_GLOBALHEADER,
00229 .write_header = seg_write_header,
00230 .write_packet = seg_write_packet,
00231 .write_trailer = seg_write_trailer,
00232 .priv_class = &seg_class,
00233 };
00234 #endif

Generated on Fri Oct 26 02:43:44 2012 for FFmpeg by doxygen 1.5.8

AltStyle によって変換されたページ (->オリジナル) /