yading@11
|
1 /*
|
yading@11
|
2 * Image format
|
yading@11
|
3 * Copyright (c) 2000, 2001, 2002 Fabrice Bellard
|
yading@11
|
4 * Copyright (c) 2004 Michael Niedermayer
|
yading@11
|
5 *
|
yading@11
|
6 * This file is part of FFmpeg.
|
yading@11
|
7 *
|
yading@11
|
8 * FFmpeg is free software; you can redistribute it and/or
|
yading@11
|
9 * modify it under the terms of the GNU Lesser General Public
|
yading@11
|
10 * License as published by the Free Software Foundation; either
|
yading@11
|
11 * version 2.1 of the License, or (at your option) any later version.
|
yading@11
|
12 *
|
yading@11
|
13 * FFmpeg is distributed in the hope that it will be useful,
|
yading@11
|
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
yading@11
|
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
yading@11
|
16 * Lesser General Public License for more details.
|
yading@11
|
17 *
|
yading@11
|
18 * You should have received a copy of the GNU Lesser General Public
|
yading@11
|
19 * License along with FFmpeg; if not, write to the Free Software
|
yading@11
|
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
yading@11
|
21 */
|
yading@11
|
22
|
yading@11
|
23 #include "libavutil/intreadwrite.h"
|
yading@11
|
24 #include "libavutil/avstring.h"
|
yading@11
|
25 #include "libavutil/log.h"
|
yading@11
|
26 #include "libavutil/opt.h"
|
yading@11
|
27 #include "libavutil/pixdesc.h"
|
yading@11
|
28 #include "avformat.h"
|
yading@11
|
29 #include "avio_internal.h"
|
yading@11
|
30 #include "internal.h"
|
yading@11
|
31 #include "libavutil/opt.h"
|
yading@11
|
32
|
yading@11
|
33 typedef struct {
|
yading@11
|
34 const AVClass *class; /**< Class for private options. */
|
yading@11
|
35 int img_number;
|
yading@11
|
36 int is_pipe;
|
yading@11
|
37 int split_planes; /**< use independent file for each Y, U, V plane */
|
yading@11
|
38 char path[1024];
|
yading@11
|
39 int update;
|
yading@11
|
40 } VideoMuxData;
|
yading@11
|
41
|
yading@11
|
42 static int write_header(AVFormatContext *s)
|
yading@11
|
43 {
|
yading@11
|
44 VideoMuxData *img = s->priv_data;
|
yading@11
|
45 AVStream *st = s->streams[0];
|
yading@11
|
46 const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(st->codec->pix_fmt);
|
yading@11
|
47 const char *str;
|
yading@11
|
48
|
yading@11
|
49 av_strlcpy(img->path, s->filename, sizeof(img->path));
|
yading@11
|
50
|
yading@11
|
51 /* find format */
|
yading@11
|
52 if (s->oformat->flags & AVFMT_NOFILE)
|
yading@11
|
53 img->is_pipe = 0;
|
yading@11
|
54 else
|
yading@11
|
55 img->is_pipe = 1;
|
yading@11
|
56
|
yading@11
|
57 str = strrchr(img->path, '.');
|
yading@11
|
58 img->split_planes = str
|
yading@11
|
59 && !av_strcasecmp(str + 1, "y")
|
yading@11
|
60 && s->nb_streams == 1
|
yading@11
|
61 && st->codec->codec_id == AV_CODEC_ID_RAWVIDEO
|
yading@11
|
62 && desc
|
yading@11
|
63 &&(desc->flags & PIX_FMT_PLANAR)
|
yading@11
|
64 && desc->nb_components >= 3;
|
yading@11
|
65 return 0;
|
yading@11
|
66 }
|
yading@11
|
67
|
yading@11
|
68 static int write_packet(AVFormatContext *s, AVPacket *pkt)
|
yading@11
|
69 {
|
yading@11
|
70 VideoMuxData *img = s->priv_data;
|
yading@11
|
71 AVIOContext *pb[4];
|
yading@11
|
72 char filename[1024];
|
yading@11
|
73 AVCodecContext *codec = s->streams[pkt->stream_index]->codec;
|
yading@11
|
74 const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(codec->pix_fmt);
|
yading@11
|
75 int i;
|
yading@11
|
76
|
yading@11
|
77 if (!img->is_pipe) {
|
yading@11
|
78 if (img->update) {
|
yading@11
|
79 av_strlcpy(filename, img->path, sizeof(filename));
|
yading@11
|
80 } else if (av_get_frame_filename(filename, sizeof(filename), img->path, img->img_number) < 0 &&
|
yading@11
|
81 img->img_number > 1) {
|
yading@11
|
82 av_log(s, AV_LOG_ERROR,
|
yading@11
|
83 "Could not get frame filename number %d from pattern '%s' (either set updatefirst or use a pattern like %%03d within the filename pattern)\n",
|
yading@11
|
84 img->img_number, img->path);
|
yading@11
|
85 return AVERROR(EINVAL);
|
yading@11
|
86 }
|
yading@11
|
87 for (i = 0; i < 4; i++) {
|
yading@11
|
88 if (avio_open2(&pb[i], filename, AVIO_FLAG_WRITE,
|
yading@11
|
89 &s->interrupt_callback, NULL) < 0) {
|
yading@11
|
90 av_log(s, AV_LOG_ERROR, "Could not open file : %s\n", filename);
|
yading@11
|
91 return AVERROR(EIO);
|
yading@11
|
92 }
|
yading@11
|
93
|
yading@11
|
94 if (!img->split_planes || i+1 >= desc->nb_components)
|
yading@11
|
95 break;
|
yading@11
|
96 filename[strlen(filename) - 1] = ((int[]){'U','V','A','x'})[i];
|
yading@11
|
97 }
|
yading@11
|
98 } else {
|
yading@11
|
99 pb[0] = s->pb;
|
yading@11
|
100 }
|
yading@11
|
101
|
yading@11
|
102 if (img->split_planes) {
|
yading@11
|
103 int ysize = codec->width * codec->height;
|
yading@11
|
104 int usize = ((-codec->width)>>desc->log2_chroma_w) * ((-codec->height)>>desc->log2_chroma_h);
|
yading@11
|
105 if (desc->comp[0].depth_minus1 >= 8) {
|
yading@11
|
106 ysize *= 2;
|
yading@11
|
107 usize *= 2;
|
yading@11
|
108 }
|
yading@11
|
109 avio_write(pb[0], pkt->data , ysize);
|
yading@11
|
110 avio_write(pb[1], pkt->data + ysize , usize);
|
yading@11
|
111 avio_write(pb[2], pkt->data + ysize + usize, usize);
|
yading@11
|
112 avio_close(pb[1]);
|
yading@11
|
113 avio_close(pb[2]);
|
yading@11
|
114 if (desc->nb_components > 3) {
|
yading@11
|
115 avio_write(pb[3], pkt->data + ysize + 2*usize, ysize);
|
yading@11
|
116 avio_close(pb[3]);
|
yading@11
|
117 }
|
yading@11
|
118 } else {
|
yading@11
|
119 avio_write(pb[0], pkt->data, pkt->size);
|
yading@11
|
120 }
|
yading@11
|
121 avio_flush(pb[0]);
|
yading@11
|
122 if (!img->is_pipe) {
|
yading@11
|
123 avio_close(pb[0]);
|
yading@11
|
124 }
|
yading@11
|
125
|
yading@11
|
126 img->img_number++;
|
yading@11
|
127 return 0;
|
yading@11
|
128 }
|
yading@11
|
129
|
yading@11
|
130 #define OFFSET(x) offsetof(VideoMuxData, x)
|
yading@11
|
131 #define ENC AV_OPT_FLAG_ENCODING_PARAM
|
yading@11
|
132 static const AVOption muxoptions[] = {
|
yading@11
|
133 { "updatefirst", "continuously overwrite one file", OFFSET(update), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, ENC },
|
yading@11
|
134 { "update", "continuously overwrite one file", OFFSET(update), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, ENC },
|
yading@11
|
135 { "start_number", "set first number in the sequence", OFFSET(img_number), AV_OPT_TYPE_INT, { .i64 = 1 }, 1, INT_MAX, ENC },
|
yading@11
|
136 { NULL },
|
yading@11
|
137 };
|
yading@11
|
138
|
yading@11
|
139 #if CONFIG_IMAGE2_MUXER
|
yading@11
|
140 static const AVClass img2mux_class = {
|
yading@11
|
141 .class_name = "image2 muxer",
|
yading@11
|
142 .item_name = av_default_item_name,
|
yading@11
|
143 .option = muxoptions,
|
yading@11
|
144 .version = LIBAVUTIL_VERSION_INT,
|
yading@11
|
145 };
|
yading@11
|
146
|
yading@11
|
147 AVOutputFormat ff_image2_muxer = {
|
yading@11
|
148 .name = "image2",
|
yading@11
|
149 .long_name = NULL_IF_CONFIG_SMALL("image2 sequence"),
|
yading@11
|
150 .extensions = "bmp,dpx,jls,jpeg,jpg,ljpg,pam,pbm,pcx,pgm,pgmyuv,png,"
|
yading@11
|
151 "ppm,sgi,tga,tif,tiff,jp2,j2c,xwd,sun,ras,rs,im1,im8,im24,"
|
yading@11
|
152 "sunras,xbm,xface",
|
yading@11
|
153 .priv_data_size = sizeof(VideoMuxData),
|
yading@11
|
154 .video_codec = AV_CODEC_ID_MJPEG,
|
yading@11
|
155 .write_header = write_header,
|
yading@11
|
156 .write_packet = write_packet,
|
yading@11
|
157 .flags = AVFMT_NOTIMESTAMPS | AVFMT_NODIMENSIONS | AVFMT_NOFILE,
|
yading@11
|
158 .priv_class = &img2mux_class,
|
yading@11
|
159 };
|
yading@11
|
160 #endif
|
yading@11
|
161 #if CONFIG_IMAGE2PIPE_MUXER
|
yading@11
|
162 AVOutputFormat ff_image2pipe_muxer = {
|
yading@11
|
163 .name = "image2pipe",
|
yading@11
|
164 .long_name = NULL_IF_CONFIG_SMALL("piped image2 sequence"),
|
yading@11
|
165 .priv_data_size = sizeof(VideoMuxData),
|
yading@11
|
166 .video_codec = AV_CODEC_ID_MJPEG,
|
yading@11
|
167 .write_header = write_header,
|
yading@11
|
168 .write_packet = write_packet,
|
yading@11
|
169 .flags = AVFMT_NOTIMESTAMPS | AVFMT_NODIMENSIONS
|
yading@11
|
170 };
|
yading@11
|
171 #endif
|