Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 334 lines (279 sloc) 10.339 kb
7cee9fd @carsonmcdonald Fixed GPL header.
authored
1 /*
e9d7e7b @carsonmcdonald Fix copyright info
authored
2 * Copyright (c) 2009-2013 Carson McDonald
7cee9fd @carsonmcdonald Fixed GPL header.
authored
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License version 2
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 *
17 * Originaly created by and Copyright (c) 2009 Chase Douglas
18 */
19
5db4dad @carsonmcdonald Initial add of live_upload and Makefile.
authored
20 #include <stdio.h>
21 #include <string.h>
22 #include <unistd.h>
23
24 #include "libavformat/avformat.h"
25
3696bcc Added readme.
Your Name authored
26 struct config_info
27 {
28 const char *input_filename;
29 int segment_length;
30 const char *temp_directory;
31 const char *filename_prefix;
32 const char *encoding_profile;
33 };
34
5db4dad @carsonmcdonald Initial add of live_upload and Makefile.
authored
35 static AVStream *add_output_stream(AVFormatContext *output_format_context, AVStream *input_stream)
36 {
37 AVCodecContext *input_codec_context;
38 AVCodecContext *output_codec_context;
39 AVStream *output_stream;
40
9f768c6 @danrossi Fixes for OSX ffmpeg macports installation
danrossi authored
41 output_stream = avformat_new_stream(output_format_context, 0);
5db4dad @carsonmcdonald Initial add of live_upload and Makefile.
authored
42 if (!output_stream)
43 {
3696bcc Added readme.
Your Name authored
44 fprintf(stderr, "Segmenter error: Could not allocate stream\n");
5db4dad @carsonmcdonald Initial add of live_upload and Makefile.
authored
45 exit(1);
46 }
47
48 input_codec_context = input_stream->codec;
49 output_codec_context = output_stream->codec;
50
51 output_codec_context->codec_id = input_codec_context->codec_id;
52 output_codec_context->codec_type = input_codec_context->codec_type;
53 output_codec_context->codec_tag = input_codec_context->codec_tag;
54 output_codec_context->bit_rate = input_codec_context->bit_rate;
55 output_codec_context->extradata = input_codec_context->extradata;
56 output_codec_context->extradata_size = input_codec_context->extradata_size;
57
58 if(av_q2d(input_codec_context->time_base) * input_codec_context->ticks_per_frame > av_q2d(input_stream->time_base) && av_q2d(input_stream->time_base) < 1.0/1000)
59 {
60 output_codec_context->time_base = input_codec_context->time_base;
61 output_codec_context->time_base.num *= input_codec_context->ticks_per_frame;
62 }
63 else
64 {
65 output_codec_context->time_base = input_stream->time_base;
66 }
67
68 switch (input_codec_context->codec_type)
69 {
9f768c6 @danrossi Fixes for OSX ffmpeg macports installation
danrossi authored
70 case AVMEDIA_TYPE_AUDIO:
5db4dad @carsonmcdonald Initial add of live_upload and Makefile.
authored
71 output_codec_context->channel_layout = input_codec_context->channel_layout;
72 output_codec_context->sample_rate = input_codec_context->sample_rate;
73 output_codec_context->channels = input_codec_context->channels;
74 output_codec_context->frame_size = input_codec_context->frame_size;
75 if ((input_codec_context->block_align == 1 && input_codec_context->codec_id == CODEC_ID_MP3) || input_codec_context->codec_id == CODEC_ID_AC3)
76 {
77 output_codec_context->block_align = 0;
78 }
79 else
80 {
81 output_codec_context->block_align = input_codec_context->block_align;
82 }
83 break;
9f768c6 @danrossi Fixes for OSX ffmpeg macports installation
danrossi authored
84 case AVMEDIA_TYPE_VIDEO:
5db4dad @carsonmcdonald Initial add of live_upload and Makefile.
authored
85 output_codec_context->pix_fmt = input_codec_context->pix_fmt;
86 output_codec_context->width = input_codec_context->width;
87 output_codec_context->height = input_codec_context->height;
88 output_codec_context->has_b_frames = input_codec_context->has_b_frames;
89
90 if (output_format_context->oformat->flags & AVFMT_GLOBALHEADER)
91 {
92 output_codec_context->flags |= CODEC_FLAG_GLOBAL_HEADER;
93 }
94 break;
95 default:
96 break;
97 }
98
99 return output_stream;
100 }
101
3696bcc Added readme.
Your Name authored
102 void output_transfer_command(const unsigned int first_segment, const unsigned int last_segment, const int end, const char *encoding_profile)
5db4dad @carsonmcdonald Initial add of live_upload and Makefile.
authored
103 {
104 char buffer[1024 * 10];
105 memset(buffer, 0, sizeof(char) * 1024 * 10);
106
3696bcc Added readme.
Your Name authored
107 sprintf(buffer, "%d, %d, %d, %s", first_segment, last_segment, end, encoding_profile);
5db4dad @carsonmcdonald Initial add of live_upload and Makefile.
authored
108
3696bcc Added readme.
Your Name authored
109 fprintf(stderr, "segmenter: %s\n\r", buffer);
5db4dad @carsonmcdonald Initial add of live_upload and Makefile.
authored
110 }
111
112 int main(int argc, char **argv)
113 {
3696bcc Added readme.
Your Name authored
114 if(argc != 5)
5db4dad @carsonmcdonald Initial add of live_upload and Makefile.
authored
115 {
3696bcc Added readme.
Your Name authored
116 fprintf(stderr, "Usage: %s <segment length> <output location> <filename prefix> <encoding profile>\n", argv[0]);
117 return 1;
5db4dad @carsonmcdonald Initial add of live_upload and Makefile.
authored
118 }
119
3696bcc Added readme.
Your Name authored
120 struct config_info config;
5db4dad @carsonmcdonald Initial add of live_upload and Makefile.
authored
121
3696bcc Added readme.
Your Name authored
122 memset(&config, 0, sizeof(struct config_info));
123
124 config.segment_length = atoi(argv[1]);
125 config.temp_directory = argv[2];
126 config.filename_prefix = argv[3];
127 config.encoding_profile = argv[4];
128 config.input_filename = "pipe://1";
129
130 char *output_filename = malloc(sizeof(char) * (strlen(config.temp_directory) + 1 + strlen(config.filename_prefix) + 10));
5db4dad @carsonmcdonald Initial add of live_upload and Makefile.
authored
131 if (!output_filename)
132 {
3696bcc Added readme.
Your Name authored
133 fprintf(stderr, "Segmenter error: Could not allocate space for output filenames\n");
5db4dad @carsonmcdonald Initial add of live_upload and Makefile.
authored
134 exit(1);
135 }
136
137 // ------------------ Done parsing input --------------
138
139 av_register_all();
140
141 AVInputFormat *input_format = av_find_input_format("mpegts");
142 if (!input_format)
143 {
3696bcc Added readme.
Your Name authored
144 fprintf(stderr, "Segmenter error: Could not find MPEG-TS demuxer\n");
5db4dad @carsonmcdonald Initial add of live_upload and Makefile.
authored
145 exit(1);
146 }
147
148 AVFormatContext *input_context = NULL;
9f768c6 @danrossi Fixes for OSX ffmpeg macports installation
danrossi authored
149 int ret = avformat_open_input(&input_context, config.input_filename, input_format, NULL);
5db4dad @carsonmcdonald Initial add of live_upload and Makefile.
authored
150 if (ret != 0)
151 {
3696bcc Added readme.
Your Name authored
152 fprintf(stderr, "Segmenter error: Could not open input file, make sure it is an mpegts file: %d\n", ret);
5db4dad @carsonmcdonald Initial add of live_upload and Makefile.
authored
153 exit(1);
154 }
155
9f768c6 @danrossi Fixes for OSX ffmpeg macports installation
danrossi authored
156 if (avformat_find_stream_info(input_context, NULL) < 0)
5db4dad @carsonmcdonald Initial add of live_upload and Makefile.
authored
157 {
3696bcc Added readme.
Your Name authored
158 fprintf(stderr, "Segmenter error: Could not read stream information\n");
5db4dad @carsonmcdonald Initial add of live_upload and Makefile.
authored
159 exit(1);
160 }
161
9f768c6 @danrossi Fixes for OSX ffmpeg macports installation
danrossi authored
162 //#if LIBAVFORMAT_VERSION_MAJOR >= 52 && LIBAVFORMAT_VERSION_MINOR >= 45
8595f70 @carsonmcdonald Added pthread linkage for newer versions of avformat.
authored
163 AVOutputFormat *output_format = av_guess_format("mpegts", NULL, NULL);
9f768c6 @danrossi Fixes for OSX ffmpeg macports installation
danrossi authored
164 //#else
165 // AVOutputFormat *output_format = guess_format("mpegts", NULL, NULL);
166 //#endif
5db4dad @carsonmcdonald Initial add of live_upload and Makefile.
authored
167 if (!output_format)
168 {
3696bcc Added readme.
Your Name authored
169 fprintf(stderr, "Segmenter error: Could not find MPEG-TS muxer\n");
5db4dad @carsonmcdonald Initial add of live_upload and Makefile.
authored
170 exit(1);
171 }
172
173 AVFormatContext *output_context = avformat_alloc_context();
174 if (!output_context)
175 {
3696bcc Added readme.
Your Name authored
176 fprintf(stderr, "Segmenter error: Could not allocated output context");
5db4dad @carsonmcdonald Initial add of live_upload and Makefile.
authored
177 exit(1);
178 }
179 output_context->oformat = output_format;
180
181 int video_index = -1;
182 int audio_index = -1;
183
184 AVStream *video_stream;
185 AVStream *audio_stream;
186
3696bcc Added readme.
Your Name authored
187 int i;
188
5db4dad @carsonmcdonald Initial add of live_upload and Makefile.
authored
189 for (i = 0; i < input_context->nb_streams && (video_index < 0 || audio_index < 0); i++)
190 {
191 switch (input_context->streams[i]->codec->codec_type) {
9f768c6 @danrossi Fixes for OSX ffmpeg macports installation
danrossi authored
192 case AVMEDIA_TYPE_VIDEO:
5db4dad @carsonmcdonald Initial add of live_upload and Makefile.
authored
193 video_index = i;
194 input_context->streams[i]->discard = AVDISCARD_NONE;
195 video_stream = add_output_stream(output_context, input_context->streams[i]);
196 break;
9f768c6 @danrossi Fixes for OSX ffmpeg macports installation
danrossi authored
197 case AVMEDIA_TYPE_AUDIO:
5db4dad @carsonmcdonald Initial add of live_upload and Makefile.
authored
198 audio_index = i;
199 input_context->streams[i]->discard = AVDISCARD_NONE;
200 audio_stream = add_output_stream(output_context, input_context->streams[i]);
201 break;
202 default:
203 input_context->streams[i]->discard = AVDISCARD_ALL;
204 break;
205 }
206 }
207
9f768c6 @danrossi Fixes for OSX ffmpeg macports installation
danrossi authored
208 // if (av_set_parameters(output_context, NULL) < 0)
209 // {
210 // fprintf(stderr, "Segmenter error: Invalid output format parameters\n");
211 // exit(1);
212 // }
5db4dad @carsonmcdonald Initial add of live_upload and Makefile.
authored
213
9f768c6 @danrossi Fixes for OSX ffmpeg macports installation
danrossi authored
214 av_dump_format(output_context, 0, config.filename_prefix, 1);
5db4dad @carsonmcdonald Initial add of live_upload and Makefile.
authored
215
c7d280c @carsonmcdonald Apply and test audio patch from Scott Kidder. This patch skips any vi…
authored
216 if(video_index >= 0)
5db4dad @carsonmcdonald Initial add of live_upload and Makefile.
authored
217 {
c7d280c @carsonmcdonald Apply and test audio patch from Scott Kidder. This patch skips any vi…
authored
218 AVCodec *codec = avcodec_find_decoder(video_stream->codec->codec_id);
219 if (!codec)
220 {
221 fprintf(stderr, "Segmenter error: Could not find video decoder, key frames will not be honored\n");
222 }
5db4dad @carsonmcdonald Initial add of live_upload and Makefile.
authored
223
9f768c6 @danrossi Fixes for OSX ffmpeg macports installation
danrossi authored
224 if (avcodec_open2(video_stream->codec, codec, NULL) < 0)
c7d280c @carsonmcdonald Apply and test audio patch from Scott Kidder. This patch skips any vi…
authored
225 {
226 fprintf(stderr, "Segmenter error: Could not open video decoder, key frames will not be honored\n");
227 }
5db4dad @carsonmcdonald Initial add of live_upload and Makefile.
authored
228 }
229
230 unsigned int output_index = 1;
3696bcc Added readme.
Your Name authored
231 snprintf(output_filename, strlen(config.temp_directory) + 1 + strlen(config.filename_prefix) + 10, "%s/%s-%05u.ts", config.temp_directory, config.filename_prefix, output_index++);
9f768c6 @danrossi Fixes for OSX ffmpeg macports installation
danrossi authored
232
233 if (avio_open(&output_context->pb, output_filename, AVIO_FLAG_WRITE) < 0)
5db4dad @carsonmcdonald Initial add of live_upload and Makefile.
authored
234 {
3696bcc Added readme.
Your Name authored
235 fprintf(stderr, "Segmenter error: Could not open '%s'\n", output_filename);
5db4dad @carsonmcdonald Initial add of live_upload and Makefile.
authored
236 exit(1);
237 }
238
9f768c6 @danrossi Fixes for OSX ffmpeg macports installation
danrossi authored
239 if (avformat_write_header(output_context, NULL))
5db4dad @carsonmcdonald Initial add of live_upload and Makefile.
authored
240 {
3696bcc Added readme.
Your Name authored
241 fprintf(stderr, "Segmenter error: Could not write mpegts header to first output file\n");
5db4dad @carsonmcdonald Initial add of live_upload and Makefile.
authored
242 exit(1);
243 }
244
245 unsigned int first_segment = 1;
246 unsigned int last_segment = 0;
247
248 double prev_segment_time = 0;
249 int decode_done;
250 do
251 {
252 double segment_time;
253 AVPacket packet;
254
255 decode_done = av_read_frame(input_context, &packet);
256 if (decode_done < 0)
257 {
258 break;
259 }
260
261 if (av_dup_packet(&packet) < 0)
262 {
3696bcc Added readme.
Your Name authored
263 fprintf(stderr, "Segmenter error: Could not duplicate packet");
5db4dad @carsonmcdonald Initial add of live_upload and Makefile.
authored
264 av_free_packet(&packet);
265 break;
266 }
267
9f768c6 @danrossi Fixes for OSX ffmpeg macports installation
danrossi authored
268 if (packet.stream_index == video_index && (packet.flags & AV_PKT_FLAG_KEY))
5db4dad @carsonmcdonald Initial add of live_upload and Makefile.
authored
269 {
270 segment_time = (double)video_stream->pts.val * video_stream->time_base.num / video_stream->time_base.den;
271 }
272 else if (video_index < 0)
273 {
274 segment_time = (double)audio_stream->pts.val * audio_stream->time_base.num / audio_stream->time_base.den;
275 }
276 else
277 {
278 segment_time = prev_segment_time;
279 }
280
281 // done writing the current file?
3696bcc Added readme.
Your Name authored
282 if (segment_time - prev_segment_time >= config.segment_length)
5db4dad @carsonmcdonald Initial add of live_upload and Makefile.
authored
283 {
9f768c6 @danrossi Fixes for OSX ffmpeg macports installation
danrossi authored
284 avio_flush(output_context->pb);
285 avio_close(output_context->pb);
5db4dad @carsonmcdonald Initial add of live_upload and Makefile.
authored
286
3696bcc Added readme.
Your Name authored
287 output_transfer_command(first_segment, ++last_segment, 0, config.encoding_profile);
5db4dad @carsonmcdonald Initial add of live_upload and Makefile.
authored
288
3696bcc Added readme.
Your Name authored
289 snprintf(output_filename, strlen(config.temp_directory) + 1 + strlen(config.filename_prefix) + 10, "%s/%s-%05u.ts", config.temp_directory, config.filename_prefix, output_index++);
9f768c6 @danrossi Fixes for OSX ffmpeg macports installation
danrossi authored
290 if (avio_open(&output_context->pb, output_filename, AVIO_FLAG_WRITE) < 0)
5db4dad @carsonmcdonald Initial add of live_upload and Makefile.
authored
291 {
3696bcc Added readme.
Your Name authored
292 fprintf(stderr, "Segmenter error: Could not open '%s'\n", output_filename);
5db4dad @carsonmcdonald Initial add of live_upload and Makefile.
authored
293 break;
294 }
295
296 prev_segment_time = segment_time;
297 }
298
5374525 @carsonmcdonald Removed commented out break and removed packet free since it is freed…
authored
299 ret = av_interleaved_write_frame(output_context, &packet);
5db4dad @carsonmcdonald Initial add of live_upload and Makefile.
authored
300 if (ret < 0)
301 {
3696bcc Added readme.
Your Name authored
302 fprintf(stderr, "Segmenter error: Could not write frame of stream: %d\n", ret);
5db4dad @carsonmcdonald Initial add of live_upload and Makefile.
authored
303 }
304 else if (ret > 0)
305 {
d0b0234 @carsonmcdonald The end of stream request isn't an error.
authored
306 fprintf(stderr, "Segmenter info: End of stream requested\n");
5db4dad @carsonmcdonald Initial add of live_upload and Makefile.
authored
307 av_free_packet(&packet);
308 break;
309 }
310
311 av_free_packet(&packet);
312 } while (!decode_done);
313
314 av_write_trailer(output_context);
315
c7d280c @carsonmcdonald Apply and test audio patch from Scott Kidder. This patch skips any vi…
authored
316 if (video_index >= 0)
317 {
318 avcodec_close(video_stream->codec);
319 }
5db4dad @carsonmcdonald Initial add of live_upload and Makefile.
authored
320
321 for(i = 0; i < output_context->nb_streams; i++)
322 {
323 av_freep(&output_context->streams[i]->codec);
324 av_freep(&output_context->streams[i]);
325 }
326
9f768c6 @danrossi Fixes for OSX ffmpeg macports installation
danrossi authored
327 avio_close(output_context->pb);
5db4dad @carsonmcdonald Initial add of live_upload and Makefile.
authored
328 av_free(output_context);
329
3696bcc Added readme.
Your Name authored
330 output_transfer_command(first_segment, ++last_segment, 1, config.encoding_profile);
5db4dad @carsonmcdonald Initial add of live_upload and Makefile.
authored
331
332 return 0;
333 }
Something went wrong with that request. Please try again.