]> git.ipfire.org Git - thirdparty/freeswitch.git/blob - src/mod/applications/mod_av/avformat.c
d17f4eac390dead5123b9c6bc3efd385e2e3ce0d
[thirdparty/freeswitch.git] / src / mod / applications / mod_av / avformat.c
1 /*
2 * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
3 * Copyright (C) 2005-2015, Anthony Minessale II <anthm@freeswitch.org>
4 *
5 * Version: MPL 1.1
6 *
7 * The contents of this file are subject to the Mozilla Public License Version
8 * 1.1 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
11 *
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 * for the specific language governing rights and limitations under the
15 * License.
16 *
17 * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
18 *
19 * The Initial Developer of the Original Code is
20 * Seven Du <dujinfang@gmail.com>
21 * Portions created by the Initial Developer are Copyright (C)
22 * the Initial Developer. All Rights Reserved.
23 *
24 * Contributor(s):
25 *
26 * Seven Du <dujinfang@gmail.com>
27 * Anthony Minessale <anthm@freeswitch.org>
28 *
29 * mod_avformat -- File Formats with libav.org
30 *
31 */
32
33 #include <switch.h>
34 #include "mod_av.h"
35 GCC_DIAG_OFF(deprecated-declarations)
36 #include <libavcodec/avcodec.h>
37 #include <libavformat/avformat.h>
38 #include <libavutil/opt.h>
39 #include <libavutil/imgutils.h>
40 #include <libavutil/avstring.h>
41 #include <libavutil/channel_layout.h>
42 #include <libswscale/swscale.h>
43 #ifdef USE_AVRESAMPLE
44 #include <libavresample/avresample.h>
45 #define SwrContext AVAudioResampleContext
46 #define swr_alloc avresample_alloc_context
47 #define swr_init avresample_open
48 #define swr_free avresample_free
49 #define swr_get_out_samples avresample_get_out_samples
50 #define swr_get_out_samples avresample_get_out_samples
51 #define swr_convert(ctx, odata, osamples, idata, isamples) \
52 avresample_convert(ctx, odata, 0, osamples, (uint8_t **)idata, 0, isamples)
53 #else
54 #include <libswresample/swresample.h>
55 #endif
56
57 #define SLICE_SIZE (SWITCH_DEFAULT_VIDEO_SIZE + 100)
58
59 GCC_DIAG_ON(deprecated-declarations)
60 #define SCALE_FLAGS SWS_BICUBIC
61 #define DFT_RECORD_OFFSET 0
62
63
64 #ifndef AVUTIL_TIMESTAMP_H
65 #define AVUTIL_TIMESTAMP_H
66
67 #define AV_TS_MAX_STRING_SIZE 32
68 #define UINTVAL(v) (v > 0 ? v : 0);
69
70 // Compatibility with old libav on Debian Jessie
71 // Not required if libavcodec version > 56.34.1
72 #ifndef AV_CODEC_FLAG_LOOP_FILTER
73 #define AV_CODEC_FLAG_LOOP_FILTER CODEC_FLAG_LOOP_FILTER
74 #define AV_CODEC_FLAG_GLOBAL_HEADER CODEC_FLAG_GLOBAL_HEADER
75 #define AV_CODEC_CAP_VARIABLE_FRAME_SIZE CODEC_CAP_VARIABLE_FRAME_SIZE
76 #endif
77
78 struct avformat_globals {
79 enum AVColorSpace colorspace;
80 };
81
82 struct avformat_globals avformat_globals = { 0 };
83
84 /* App interface */
85
86 // a wrapper around a single output AVStream
87 typedef struct MediaStream {
88 AVStream *st;
89 AVFrame *frame;
90 AVFrame *tmp_frame;
91
92 // audio
93 int channels;
94 int sample_rate;
95 struct SwrContext *resample_ctx;
96
97 //video
98 int width;
99 int height;
100 struct SwsContext *sws_ctx;
101 int64_t next_pts;
102 int active;
103 int r;
104 } MediaStream;
105
106 typedef struct record_helper_s {
107 switch_mutex_t *mutex;
108 AVFormatContext *fc;
109 MediaStream *video_st;
110 switch_timer_t *video_timer;
111 int in_callback;
112 switch_queue_t *video_queue;
113 switch_thread_t *video_thread;
114 switch_mm_t *mm;
115 int finalize;
116 switch_file_handle_t *fh;
117 switch_time_t record_timer_paused;
118 uint64_t last_ts;
119 } record_helper_t;
120
121 /* file interface */
122
123 struct av_file_context {
124 switch_memory_pool_t *pool;
125 switch_mutex_t *mutex;
126 switch_thread_cond_t *cond;
127 switch_buffer_t *buf;
128 switch_buffer_t *audio_buffer;
129 switch_timer_t video_timer;
130 int offset;
131 int audio_start;
132 int aud_ready;
133 int vid_ready;
134 int audio_ready;
135 int closed;
136
137 MediaStream video_st;
138 MediaStream audio_st[2];
139 AVFormatContext *fc;
140 AVCodec *audio_codec;
141 AVCodec *video_codec;
142 enum AVColorSpace colorspace;
143
144 int has_audio;
145 int has_video;
146
147 record_helper_t eh;
148 switch_thread_t *file_read_thread;
149 int file_read_thread_running;
150 int file_read_thread_started;
151 switch_time_t video_start_time;
152 switch_image_t *last_img;
153 int read_fps;
154 switch_time_t last_vid_push;
155 int64_t seek_ts;
156 switch_bool_t read_paused;
157 int errs;
158 switch_file_handle_t *handle;
159 int16_t *mux_buf;
160 switch_size_t mux_buf_len;
161
162 switch_time_t last_vid_write;
163 int audio_timer;
164
165 switch_bool_t no_video_decode;
166 switch_queue_t *video_pkt_queue;
167 switch_packetizer_t *packetizer;
168 AVPacket *last_read_pkt;
169 };
170
171 typedef struct av_file_context av_file_context_t;
172
173
174 /**
175 * Fill the provided buffer with a string containing a timestamp
176 * representation.
177 *
178 * @param buf a buffer with size in bytes of at least AV_TS_MAX_STRING_SIZE
179 * @param ts the timestamp to represent
180 * @return the buffer in input
181 */
182 static inline char *av_ts_make_string(char *buf, int64_t ts)
183 {
184 if (ts == AV_NOPTS_VALUE) snprintf(buf, AV_TS_MAX_STRING_SIZE, "NOPTS");
185 else snprintf(buf, AV_TS_MAX_STRING_SIZE, "%"PRId64"", ts);
186 return buf;
187 }
188
189 /**
190 * Convenience macro, the return value should be used only directly in
191 * function arguments but never stand-alone.
192 */
193 #define av_ts2str(ts) av_ts_make_string((char[AV_TS_MAX_STRING_SIZE]){0}, ts)
194
195 /**
196 * Fill the provided buffer with a string containing a timestamp time
197 * representation.
198 *
199 * @param buf a buffer with size in bytes of at least AV_TS_MAX_STRING_SIZE
200 * @param ts the timestamp to represent
201 * @param tb the timebase of the timestamp
202 * @return the buffer in input
203 */
204 static inline char *av_ts_make_time_string(char *buf, int64_t ts, AVRational *tb)
205 {
206 if (ts == AV_NOPTS_VALUE) snprintf(buf, AV_TS_MAX_STRING_SIZE, "NOPTS");
207 else snprintf(buf, AV_TS_MAX_STRING_SIZE, "%.6g", av_q2d(*tb) * ts);
208 return buf;
209 }
210
211 /**
212 * Convenience macro, the return value should be used only directly in
213 * function arguments but never stand-alone.
214 */
215 #define av_ts2timestr(ts, tb) av_ts_make_time_string((char[AV_TS_MAX_STRING_SIZE]){0}, ts, tb)
216
217 #endif /* AVUTIL_TIMESTAMP_H */
218
219
220 static switch_status_t av_file_close(switch_file_handle_t *handle);
221 SWITCH_MODULE_LOAD_FUNCTION(mod_avformat_load);
222
223 static char *const get_error_text(const int error, char *error_buffer, switch_size_t error_buflen)
224 {
225 av_strerror(error, error_buffer, error_buflen);
226 return error_buffer;
227 }
228
229 static void av_unused fill_avframe(AVFrame *pict, switch_image_t *img)
230 {
231 int i;
232 uint8_t *y = img->planes[0];
233 uint8_t *u = img->planes[1];
234 uint8_t *v = img->planes[2];
235
236 /* Y */
237 for (i = 0; i < pict->height; i++) {
238 memcpy(&pict->data[0][i * pict->linesize[0]], y + i * img->stride[0], pict->width);
239 }
240
241 /* U/V */
242 for(i = 0; i < pict->height / 2; i++) {
243 memcpy(&pict->data[1][i * pict->linesize[1]], u + i * img->stride[1], pict->width / 2);
244 memcpy(&pict->data[2][i * pict->linesize[2]], v + i * img->stride[2], pict->width / 2);
245 }
246 }
247
248 static void av_unused avframe2img(AVFrame *pict, switch_image_t *img)
249 {
250 int i, j;
251
252 if (img->fmt == SWITCH_IMG_FMT_I420) {
253 if (pict->format == AV_PIX_FMT_YUV420P) {
254 switch_I420_copy2(pict->data, pict->linesize, img->planes, img->stride, img->d_w, img->d_h);
255 } else if (pict->format == AV_PIX_FMT_YUVA420P) {
256 int linesize[3];
257 linesize[0] = pict->linesize[0];
258 linesize[1] = pict->linesize[1];
259 linesize[2] = pict->linesize[2] + pict->linesize[0];
260
261 switch_I420_copy2(pict->data, linesize, img->planes, img->stride, img->d_w, img->d_h);
262 }
263
264 } else if (img->fmt == SWITCH_IMG_FMT_ARGB) {
265 if (pict->format == AV_PIX_FMT_YUV420P) {
266 switch_rgb_color_t *color = (switch_rgb_color_t *)img->planes[SWITCH_PLANE_PACKED];
267 uint8_t *alpha = pict->data[3];
268
269 /*!\brief I420 to ARGB Convertion*/
270 switch_I420ToARGB(pict->data[0], pict->linesize[0],
271 pict->data[1], pict->linesize[1],
272 pict->data[2], pict->linesize[2],
273 img->planes[SWITCH_PLANE_PACKED], img->stride[SWITCH_PLANE_PACKED],
274 img->d_w, img->d_h);
275
276
277 for (j = 0; j < img->d_h; j++) {
278 for (i = 0; i < img->d_w; i++) {
279 color->a = *alpha++;
280 color++;
281 }
282 color = (switch_rgb_color_t *)(img->planes[SWITCH_PLANE_PACKED] + img->stride[SWITCH_PLANE_PACKED] * j);
283 }
284 } else if (pict->format == AV_PIX_FMT_RGBA) {
285 #if SWITCH_BYTE_ORDER == __BIG_ENDIAN
286 switch_RGBAToARGB(pict->data[0], pict->linesize[0],
287 mg->planes[SWITCH_PLANE_PACKED], img->stride[SWITCH_PLANE_PACKED],
288 img->d_w, img->d_h);
289 #else
290 switch_ABGRToARGB(pict->data[0], pict->linesize[0],
291 img->planes[SWITCH_PLANE_PACKED], img->stride[SWITCH_PLANE_PACKED],
292 img->d_w, img->d_h);
293 #endif
294 } else if (pict->format == AV_PIX_FMT_BGRA) {
295 #if SWITCH_BYTE_ORDER == __BIG_ENDIAN
296 switch_BGRAToARGB(pict->data[0], pict->linesize[0],
297 , img->planes[SWITCH_PLANE_PACKED], img->stride[SWITCH_PLANE_PACKED],
298 , img->d_w, img->d_h);
299 #else
300 switch_ARGBToARGB(pict->data[0], pict->linesize[0],
301 img->planes[SWITCH_PLANE_PACKED], img->stride[SWITCH_PLANE_PACKED],
302 img->d_w, img->d_h);
303 #endif
304 }
305 }
306 }
307
308 static void av_unused avframe2fd(AVFrame *pict, int fd)
309 {
310 int i;
311 uint8_t *y = pict->data[0];
312 uint8_t *u = pict->data[1];
313 uint8_t *v = pict->data[2];
314
315 /* Y */
316 for (i = 0; i < pict->height; i++) {
317 write(fd, y + i * pict->linesize[0], pict->width);
318 }
319
320 /* U/V */
321 for(i = 0; i < pict->height / 2; i++) {
322 write(fd, u + i * pict->linesize[1], pict->width / 2);
323 }
324
325 for(i = 0; i < pict->height / 2; i++) {
326 write(fd, v + i * pict->linesize[2], pict->width / 2);
327 }
328 }
329
330 static void log_packet(const AVFormatContext *fmt_ctx, const AVPacket *pkt)
331 {
332 if (mod_av_globals.debug < 2) return;
333
334 {
335 AVRational *time_base = &fmt_ctx->streams[pkt->stream_index]->time_base;
336
337 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "pts:%s pts_time:%s dts:%s dts_time:%s duration:%s duration_time:%s stream_index:%d\n",
338 av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, time_base),
339 av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, time_base),
340 av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, time_base),
341 pkt->stream_index);
342 }
343 }
344
345 static int interrupt_cb(void *cp)
346 {
347 av_file_context_t *context = (av_file_context_t *) cp;
348
349 if (context->closed) {
350 return 1;
351 }
352
353 return 0;
354 }
355
356
357 static int mod_avformat_alloc_output_context2(AVFormatContext **avctx, AVOutputFormat *oformat,
358 const char *format, const char *filename, av_file_context_t *context)
359 {
360 AVFormatContext *s = avformat_alloc_context();
361 int ret = 0;
362
363 s->interrupt_callback.callback = interrupt_cb;
364 s->interrupt_callback.opaque = context;
365
366 *avctx = NULL;
367 if (!s)
368 goto nomem;
369
370 if (!oformat) {
371 if (format) {
372 oformat = av_guess_format(format, NULL, NULL);
373 if (!oformat) {
374 av_log(s, AV_LOG_ERROR, "Requested output format '%s' is not a suitable output format\n", format);
375 ret = AVERROR(EINVAL);
376 goto error;
377 }
378 } else {
379 oformat = av_guess_format(NULL, filename, NULL);
380 if (!oformat) {
381 ret = AVERROR(EINVAL);
382 av_log(s, AV_LOG_ERROR, "Unable to find a suitable output format for '%s'\n",
383 filename);
384 goto error;
385 }
386 }
387 }
388
389 s->oformat = oformat;
390 if (s->oformat->priv_data_size > 0) {
391 s->priv_data = av_mallocz(s->oformat->priv_data_size);
392 if (!s->priv_data)
393 goto nomem;
394 if (s->oformat->priv_class) {
395 *(const AVClass**)s->priv_data= s->oformat->priv_class;
396 av_opt_set_defaults(s->priv_data);
397 }
398 } else
399 s->priv_data = NULL;
400
401 if (filename) {
402 #if (LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58,7,100))
403 av_strlcpy(s->filename, filename, sizeof(s->filename));
404 #else
405 s->url = av_strdup(filename);
406 switch_assert(s->url);
407 #endif
408 }
409
410 *avctx = s;
411 return 0;
412 nomem:
413 av_log(s, AV_LOG_ERROR, "Out of memory\n");
414 ret = AVERROR(ENOMEM);
415 error:
416 avformat_free_context(s);
417 return ret;
418 }
419
420 static int write_frame(AVFormatContext *fmt_ctx, const AVRational *time_base, AVStream *st, AVPacket *pkt)
421 {
422 /* rescale output packet timestamp values from codec to stream timebase */
423 av_packet_rescale_ts(pkt, *time_base, st->time_base);
424 pkt->stream_index = st->index;
425
426 /* Write the compressed frame to the media file. */
427 log_packet(fmt_ctx, pkt);
428 return av_interleaved_write_frame(fmt_ctx, pkt);
429 }
430
431 /* Add an output stream. */
432 static switch_status_t add_stream(av_file_context_t *context, MediaStream *mst, AVFormatContext *fc, AVCodec **codec, enum AVCodecID codec_id, switch_mm_t *mm)
433 {
434 AVCodecContext *c;
435 switch_status_t status = SWITCH_STATUS_FALSE;
436 //int threads = switch_core_cpu_count();
437 int buffer_bytes = 2097152; /* 2 mb */
438 int fps = 15;
439
440 //if (mm->try_hardware_encoder && codec_id == AV_CODEC_ID_H264) {
441 // *codec = avcodec_find_encoder_by_name("nvenc_h264");
442 //}
443
444 if (!*codec) {
445 /* find the encoder */
446 *codec = avcodec_find_encoder(codec_id);
447 }
448
449 if (!(*codec)) {
450 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not find encoder\n");
451 return status;
452 }
453
454 mst->st = avformat_new_stream(fc, *codec);
455 if (!mst->st) {
456 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not allocate stream\n");
457 return status;
458 }
459 mst->st->id = fc->nb_streams - 1;
460 GCC_DIAG_OFF(deprecated-declarations)
461 c = mst->st->codec;
462 GCC_DIAG_ON(deprecated-declarations)
463 //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "id:%d den:%d num:%d\n", mst->st->id, mst->st->time_base.den, mst->st->time_base.num);
464
465 //if (threads > 4) {
466 // threads = 4;
467 // }
468
469 switch ((*codec)->type) {
470 case AVMEDIA_TYPE_AUDIO:
471 c->sample_fmt = (*codec)->sample_fmts ? (*codec)->sample_fmts[0] : AV_SAMPLE_FMT_FLTP;
472 c->bit_rate = 128000;
473 c->sample_rate = mst->sample_rate = context->handle->samplerate;
474 c->channels = mst->channels;
475 c->channel_layout = av_get_default_channel_layout(c->channels);
476
477 if (mm) {
478 if (mm->ab) {
479 c->bit_rate = mm->ab * 1024;
480 }
481 if (mm->samplerate) {
482 c->sample_rate = mst->sample_rate = mm->samplerate;
483 }
484 }
485
486 if (context && context->has_video && !context->handle->stream_name) {
487 mst->st->time_base.den = c->sample_rate;
488 mst->st->time_base.num = 1;
489 c->time_base.den = c->sample_rate;
490 c->time_base.num = 1;
491 } else {
492 // nothing to do for audio only recording, just leave the time base as is
493 // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "stream_timebase: %d/%d codec_timebase: %d/%d nb_samples: %d\n",
494 // mst->st->time_base.num, mst->st->time_base.den, c->time_base.num, c->time_base.den, c->frame_size);
495 }
496
497 break;
498
499 case AVMEDIA_TYPE_VIDEO:
500
501 switch_assert(mm);
502
503 if (mm->vbuf) {
504 buffer_bytes = mm->vbuf;
505 }
506 if (mm->fps) {
507 fps = mm->fps;
508 } else {
509 mm->fps = fps;
510 }
511
512 if (mm->vw && mm->vh) {
513 mst->width = mm->vw;
514 mst->height = mm->vh;
515 }
516
517 c->codec_id = codec_id;
518
519 /* Resolution must be a multiple of two. */
520 c->width = mst->width;
521 c->height = mst->height;
522 c->bit_rate = mm->vb * 1024;
523 mst->st->time_base.den = 90000;
524 mst->st->time_base.num = 1;
525 c->time_base.den = 90000;
526 c->time_base.num = 1;
527 c->gop_size = fps * 10; /* emit one intra frame every 10 frames at most */
528 c->pix_fmt = AV_PIX_FMT_YUV420P;
529 //c->thread_count = threads;
530 c->rc_initial_buffer_occupancy = buffer_bytes * 8;
531
532 if (codec_id == AV_CODEC_ID_H264) {
533 c->ticks_per_frame = 2;
534
535
536 c->flags|=AV_CODEC_FLAG_LOOP_FILTER; // flags=+loop
537 c->me_cmp|= 1; // cmp=+chroma, where CHROMA = 1
538 c->me_range = 16; // me_range=16
539 c->max_b_frames = 3; // bf=3
540
541 av_opt_set_int(c->priv_data, "b_strategy", 1, 0);
542 //av_opt_set_int(c->priv_data, "motion_est", ME_HEX, 0);
543 av_opt_set(c->priv_data, "motion_est", "hex", 0);
544 av_opt_set_int(c->priv_data, "coder", 1, 0);
545
546 switch (mm->vprofile) {
547 case SWITCH_VIDEO_PROFILE_BASELINE:
548 av_opt_set(c->priv_data, "profile", "baseline", 0);
549 c->level = 41;
550 break;
551 case SWITCH_VIDEO_PROFILE_MAIN:
552 av_opt_set(c->priv_data, "profile", "main", 0);
553 av_opt_set(c->priv_data, "level", "5", 0);
554 c->level = 5;
555 break;
556 case SWITCH_VIDEO_PROFILE_HIGH:
557 av_opt_set(c->priv_data, "profile", "high", 0);
558 av_opt_set(c->priv_data, "level", "52", 0);
559 c->level = 52;
560 break;
561 }
562
563 switch (mm->vencspd) {
564 case SWITCH_VIDEO_ENCODE_SPEED_SLOW:
565 av_opt_set(c->priv_data, "preset", "veryslow", 0);
566 break;
567 case SWITCH_VIDEO_ENCODE_SPEED_MEDIUM:
568 av_opt_set(c->priv_data, "preset", "medium", 0);
569 break;
570 case SWITCH_VIDEO_ENCODE_SPEED_FAST:
571 //av_opt_set_int(c->priv_data, "intra-refresh", 1, 0);
572 av_opt_set(c->priv_data, "preset", "veryfast", 0);
573 //av_opt_set(c->priv_data, "tune", "animation+zerolatency", 0);
574 av_opt_set(c->priv_data, "tune", "fastdecode", 0);
575 break;
576 default:
577 break;
578 }
579 }
580
581 if (mm->cbr) {
582 c->rc_min_rate = c->bit_rate;
583 c->rc_max_rate = c->bit_rate;
584 c->rc_buffer_size = c->bit_rate;
585 c->qcompress = 0;
586 c->gop_size = fps * 2;
587 c->keyint_min = fps * 2;
588 } else {
589 c->gop_size = fps * 10;
590 c->keyint_min = fps;
591 c->i_quant_factor = 0.71; // i_qfactor=0.71
592 c->qcompress = 0.6; // qcomp=0.6
593 c->qmin = 10; // qmin=10
594 c->qmax = 31; // qmax=31
595 c->max_qdiff = 4; // qdiff=4
596 av_opt_set_int(c->priv_data, "crf", 18, 0);
597 }
598
599 if (mm->vb) {
600 c->bit_rate = mm->vb * 1024;
601 }
602
603 if (mm->keyint) {
604 c->gop_size = mm->keyint;
605 }
606
607 if (codec_id == AV_CODEC_ID_VP8) {
608 av_set_options_string(c, "quality=realtime", "=", ":");
609 }
610
611 // av_opt_set_int(c->priv_data, "slice-max-size", SWITCH_DEFAULT_VIDEO_SIZE, 0);
612
613 c->colorspace = context->colorspace;
614 c->color_range = AVCOL_RANGE_JPEG;
615 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "colorspace = %d\n", c->colorspace);
616
617 break;
618 default:
619 break;
620 }
621
622 /* Some formats want stream headers to be separate. */
623 if (fc->oformat->flags & AVFMT_GLOBALHEADER) {
624 c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
625 }
626
627 mst->active = 1;
628
629 return SWITCH_STATUS_SUCCESS;
630 }
631
632 static AVFrame *alloc_picture(enum AVPixelFormat pix_fmt, int width, int height)
633 {
634 AVFrame *picture;
635 int ret;
636
637 picture = av_frame_alloc();
638 if (!picture) return NULL;
639
640 picture->format = pix_fmt;
641 picture->width = width;
642 picture->height = height;
643
644 /* allocate the buffers for the frame data */
645 ret = av_frame_get_buffer(picture, 32);
646 if (ret < 0) {
647 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not allocate frame data.\n");
648 return NULL;
649 }
650
651 return picture;
652 }
653
654 static switch_status_t open_video(AVFormatContext *fc, AVCodec *codec, MediaStream *mst)
655 {
656 int ret;
657 GCC_DIAG_OFF(deprecated-declarations)
658 AVCodecContext *c = mst->st->codec;
659 GCC_DIAG_ON(deprecated-declarations)
660 switch_status_t status = SWITCH_STATUS_FALSE;
661 //int threads = switch_core_cpu_count();
662
663 // if (threads > 4) threads = 4;
664 // c->thread_count = threads;
665
666 /* open the codec */
667 ret = avcodec_open2(c, codec, NULL);
668 if (ret < 0) {
669 char ebuf[255] = "";
670 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not open video codec: %s\n", get_error_text(ret, ebuf, sizeof(ebuf)));
671 return status;
672 }
673
674 /* allocate and init a re-usable frame */
675 mst->frame = alloc_picture(c->pix_fmt, c->width, c->height);
676 switch_assert(mst->frame);
677 mst->frame->pts = 0;
678
679 // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "pix_fmt: %d\n", c->pix_fmt);
680 switch_assert(c->pix_fmt == AV_PIX_FMT_YUV420P); // always I420 for NOW
681
682 return SWITCH_STATUS_SUCCESS;
683 }
684
685 static switch_status_t open_audio(AVFormatContext *fc, AVCodec *codec, MediaStream *mst)
686 {
687 AVCodecContext *c;
688 int ret;
689 switch_status_t status = SWITCH_STATUS_FALSE;
690 GCC_DIAG_OFF(deprecated-declarations)
691 c = mst->st->codec;
692 GCC_DIAG_ON(deprecated-declarations)
693 ret = avcodec_open2(c, codec, NULL);
694
695 if (ret == AVERROR_EXPERIMENTAL) {
696 const AVCodecDescriptor *desc = avcodec_descriptor_get(c->codec_id);
697 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Codec [%s] is experimental feature in libavcodec, never mind\n", desc->name);
698 c->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
699 ret = avcodec_open2(c, codec, NULL);
700 }
701
702 if (ret < 0) {
703 const AVCodecDescriptor *desc = avcodec_descriptor_get(c->codec_id);
704 char ebuf[255] = "";
705 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not open audio codec [%s], error: %s\n", desc->name, get_error_text(ret, ebuf, sizeof(ebuf)));
706 return status;
707 }
708
709 mst->frame = av_frame_alloc();
710 switch_assert(mst->frame);
711
712 mst->frame->sample_rate = c->sample_rate;
713 mst->frame->format = AV_SAMPLE_FMT_S16;
714 mst->frame->channel_layout = c->channel_layout;
715
716 if (c->codec->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE) {
717 //mst->frame->nb_samples = 10000;
718 mst->frame->nb_samples = (mst->frame->sample_rate / 50) * c->channels;
719 } else {
720 mst->frame->nb_samples = c->frame_size;
721 }
722
723 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "sample_rate: %d nb_samples: %d\n", mst->frame->sample_rate, mst->frame->nb_samples);
724
725 if (c->sample_fmt != AV_SAMPLE_FMT_S16 || c->sample_rate != mst->sample_rate) {
726 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "sample_fmt %d != AV_SAMPLE_FMT_S16, start resampler\n", c->sample_fmt);
727
728 mst->resample_ctx = swr_alloc();
729
730 if (!mst->resample_ctx) {
731 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not allocate resampler context\n");
732 return status;
733 }
734
735 /* set options */
736 av_opt_set_int(mst->resample_ctx, "in_channel_count", c->channels, 0);
737 av_opt_set_int(mst->resample_ctx, "in_sample_rate", c->sample_rate, 0);
738 av_opt_set_int(mst->resample_ctx, "in_sample_fmt", AV_SAMPLE_FMT_S16, 0);
739 av_opt_set_int(mst->resample_ctx, "in_channel_layout", c->channel_layout, 0);
740 av_opt_set_int(mst->resample_ctx, "out_channel_count", c->channels, 0);
741 av_opt_set_int(mst->resample_ctx, "out_sample_rate", c->sample_rate, 0);
742 av_opt_set_int(mst->resample_ctx, "out_sample_fmt", c->sample_fmt, 0);
743 av_opt_set_int(mst->resample_ctx, "out_channel_layout", c->channel_layout, 0);
744
745 if (swr_init(mst->resample_ctx) < 0) {
746 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to initialize the resampling context\n");
747 av_free(mst->resample_ctx);
748 mst->resample_ctx = NULL;
749 return status;
750 }
751 }
752
753 ret = av_frame_get_buffer(mst->frame, 0);
754 if (ret < 0) {
755 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not allocate audio frame.\n");
756 return status;
757 }
758
759 if (mst->resample_ctx) {
760 mst->tmp_frame = av_frame_alloc();
761 switch_assert(mst->tmp_frame);
762
763 mst->tmp_frame->sample_rate = c->sample_rate;
764 mst->tmp_frame->format = c->sample_fmt;
765 mst->tmp_frame->channel_layout = c->channel_layout;
766 mst->tmp_frame->nb_samples = mst->frame->nb_samples;
767
768 ret = av_frame_get_buffer(mst->tmp_frame, 0);
769 if (ret < 0) {
770 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not allocate audio frame.\n");
771 return status;
772 }
773 }
774
775 return SWITCH_STATUS_SUCCESS;
776 }
777
778 static int flush_video_queue(switch_queue_t *q, int min)
779 {
780 void *pop;
781
782 if (switch_queue_size(q) > min) {
783 while (switch_queue_trypop(q, &pop) == SWITCH_STATUS_SUCCESS) {
784 switch_image_t *img = (switch_image_t *) pop;
785 switch_img_free(&img);
786 if (min && switch_queue_size(q) <= min) {
787 break;
788 }
789 }
790 }
791
792 return switch_queue_size(q);
793 }
794
795 static void flush_video_pkt_queue(switch_queue_t *q)
796 {
797 AVPacket *pkt;
798
799 while (switch_queue_trypop(q, (void **)&pkt) == SWITCH_STATUS_SUCCESS) {
800 av_packet_unref(pkt);
801 free(pkt);
802 }
803 }
804
805 static void *SWITCH_THREAD_FUNC video_thread_run(switch_thread_t *thread, void *obj)
806 {
807 av_file_context_t *context = (av_file_context_t *) obj;
808 void *pop = NULL;
809 switch_image_t *img = NULL;
810 int d_w = context->eh.video_st->width, d_h = context->eh.video_st->height;
811 int size = 0, skip = 0, skip_freq = 0, skip_count = 0, skip_total = 0, skip_total_count = 0;
812 uint64_t delta_avg = 0, delta_sum = 0, delta_i = 0, delta = 0;
813 int first = 1;
814
815 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "video thread start\n");
816 switch_assert(context->eh.video_queue);
817 for(;;) {
818 AVPacket pkt = { 0 };
819 int got_packet;
820 int ret = -1;
821
822 top:
823
824 switch_assert(context->eh.video_queue);
825 while(switch_queue_size(context->eh.video_queue) > 1) {
826 switch_image_t *tmp_img;
827 switch_queue_pop(context->eh.video_queue, &pop);
828 tmp_img = (switch_image_t *) pop;
829 switch_img_free(&tmp_img);
830 }
831 if (switch_queue_pop(context->eh.video_queue, &pop) == SWITCH_STATUS_SUCCESS) {
832 switch_img_free(&img);
833
834 if (!pop) {
835 goto endfor;
836 }
837
838 img = (switch_image_t *) pop;
839
840 if (!d_w) d_w = img->d_w;
841 if (!d_h) d_h = img->d_h;
842
843 if (d_w && d_h && (d_w != img->d_w || d_h != img->d_h)) {
844 /* scale to match established stream */
845 switch_img_fit(&img, d_w, d_h, SWITCH_FIT_SIZE);
846 }
847 } else {
848 continue;
849 }
850
851 if (skip) {
852 if ((skip_total_count > 0 && !--skip_total_count) || ++skip_count >= skip_freq) {
853 skip_total_count = skip_total;
854 skip_count = 0;
855 skip--;
856
857 goto top;
858 }
859 } else {
860
861 size = switch_queue_size(context->eh.video_queue);
862
863 if (size > 5 && !context->eh.finalize) {
864 skip = size;
865
866 if (size > 10) {
867 skip_freq = 3;
868 skip_total = 1;
869 } else {
870 skip_freq = 2;
871 skip_total = 1;
872 }
873 }
874 }
875
876 //switch_mutex_lock(context->eh.mutex);
877
878 context->eh.in_callback = 1;
879
880 GCC_DIAG_OFF(deprecated-declarations)
881 av_init_packet(&pkt);
882 GCC_DIAG_ON(deprecated-declarations)
883
884 if (context->eh.video_st->frame) {
885 ret = av_frame_make_writable(context->eh.video_st->frame);
886 }
887
888 if (ret < 0) {
889 continue;
890 }
891
892 if (context->eh.record_timer_paused) {
893 context->eh.last_ts = 0;
894 continue;
895 }
896
897 fill_avframe(context->eh.video_st->frame, img);
898
899 if (first) {
900 first = 0; // pts = 0;
901 } else if (context->eh.finalize) {
902 if (delta_i && !delta_avg) {
903 delta_avg = (int)(double)(delta_sum / delta_i);
904 delta_i = 1;
905 delta_sum = delta_avg;
906 }
907
908 if (delta_avg) {
909 delta = delta_avg;
910 } else if (context->eh.mm->fps) {
911 delta = 1000 / context->eh.mm->fps;
912 } else {
913 delta = 33;
914 }
915
916 context->eh.video_st->frame->pts += delta * 90;
917 } else {
918 uint64_t delta_tmp;
919
920 switch_core_timer_next(context->eh.video_timer);
921 delta_tmp = (context->eh.video_timer->samplecount * 90) - context->eh.last_ts;
922
923 if (delta_tmp != 0) {
924 delta_sum += delta_tmp;
925 delta_i++;
926
927 if (delta_i == UINT64_MAX) {
928 delta_i = 1;
929 delta_sum = delta_avg;
930 }
931
932 if ((delta_i % 10) == 0) {
933 delta_avg = (int)(double)(delta_sum / delta_i);
934 }
935
936 context->eh.video_st->frame->pts = context->eh.video_timer->samplecount * 90;
937 } else {
938 context->eh.video_st->frame->pts = ((context->eh.video_timer->samplecount) * 90) + 1;
939 }
940 }
941
942 context->eh.last_ts = context->eh.video_st->frame->pts;
943
944 // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "pts: %" SWITCH_INT64_T_FMT "\n", context->eh.video_st->frame->pts);
945
946 /* encode the image */
947 GCC_DIAG_OFF(deprecated-declarations)
948 ret = avcodec_encode_video2(context->eh.video_st->st->codec, &pkt, context->eh.video_st->frame, &got_packet);
949 GCC_DIAG_ON(deprecated-declarations)
950
951 if (ret < 0) {
952 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Encoding Error %d\n", ret);
953 continue;
954 }
955
956 if (got_packet) {
957 switch_mutex_lock(context->eh.mutex);
958 GCC_DIAG_OFF(deprecated-declarations)
959 write_frame(context->eh.fc, &context->eh.video_st->st->codec->time_base, context->eh.video_st->st, &pkt);
960 GCC_DIAG_ON(deprecated-declarations)
961 switch_mutex_unlock(context->eh.mutex);
962 av_packet_unref(&pkt);
963 }
964
965 context->eh.in_callback = 0;
966 //switch_mutex_unlock(context->eh.mutex);
967 }
968
969 endfor:
970
971 for(;;) {
972 AVPacket pkt = { 0 };
973 int got_packet = 0;
974 int ret = 0;
975
976 GCC_DIAG_OFF(deprecated-declarations)
977 av_init_packet(&pkt);
978 GCC_DIAG_ON(deprecated-declarations)
979
980 GCC_DIAG_OFF(deprecated-declarations)
981 ret = avcodec_encode_video2(context->eh.video_st->st->codec, &pkt, NULL, &got_packet);
982 GCC_DIAG_ON(deprecated-declarations)
983
984 if (ret < 0) {
985 break;
986 } else if (got_packet) {
987 switch_mutex_lock(context->eh.mutex);
988 GCC_DIAG_OFF(deprecated-declarations)
989 ret = write_frame(context->eh.fc, &context->eh.video_st->st->codec->time_base, context->eh.video_st->st, &pkt);
990 GCC_DIAG_ON(deprecated-declarations)
991 switch_mutex_unlock(context->eh.mutex);
992 av_packet_unref(&pkt);
993 if (ret < 0) break;
994 } else {
995 break;
996 }
997 }
998
999 while(switch_queue_trypop(context->eh.video_queue, &pop) == SWITCH_STATUS_SUCCESS) {
1000 if (!pop) break;
1001 img = (switch_image_t *) pop;
1002 switch_img_free(&img);
1003 }
1004
1005 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "video thread done\n");
1006
1007 return NULL;
1008 }
1009
1010
1011 static void close_stream(AVFormatContext *fc, MediaStream *mst)
1012 {
1013 if (!mst->active) return;
1014
1015 if (mst->resample_ctx) swr_free(&mst->resample_ctx);
1016 if (mst->sws_ctx) sws_freeContext(mst->sws_ctx);
1017 if (mst->frame) av_frame_free(&mst->frame);
1018 if (mst->tmp_frame) av_frame_free(&mst->tmp_frame);
1019
1020 GCC_DIAG_OFF(deprecated-declarations)
1021 if (mst->st && mst->st->codec) {
1022 avcodec_close(mst->st->codec);
1023 }
1024 GCC_DIAG_ON(deprecated-declarations)
1025
1026 mst->active = 0;
1027 }
1028
1029
1030 static int is_device(const AVClass *avclass)
1031 {
1032 #if defined (AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT)
1033 if (!avclass) return 0;
1034
1035
1036 return avclass->category == AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT ||
1037 avclass->category == AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT ||
1038 avclass->category == AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT ||
1039 avclass->category == AV_CLASS_CATEGORY_DEVICE_AUDIO_INPUT ||
1040 avclass->category == AV_CLASS_CATEGORY_DEVICE_OUTPUT ||
1041 avclass->category == AV_CLASS_CATEGORY_DEVICE_INPUT;
1042 #endif
1043
1044 return 0;
1045
1046 }
1047
1048 void show_formats(switch_stream_handle_t *stream) {
1049 const AVInputFormat *ifmt = NULL;
1050 const AVOutputFormat *ofmt = NULL;
1051 const char *last_name;
1052 // int is_dev;
1053
1054 stream->write_function(stream, "============= File Formats ==============================:\n"
1055 " D. = Demuxing supported\n"
1056 " .M = Muxing supported\n"
1057 "----------------------\n");
1058
1059 last_name = "000";
1060
1061 for (;;) {
1062 int decode = 0;
1063 int encode = 0;
1064 int is_dev = 0;
1065 const char *name = NULL;
1066 const char *long_name = NULL;
1067
1068 #if (LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58,9,100))
1069 while ((ofmt = av_oformat_next(ofmt))) {
1070 #else
1071 void *i = 0;
1072
1073 while ((ofmt = av_muxer_iterate(&i))) {
1074 #endif
1075
1076 is_dev = is_device(ofmt->priv_class);
1077
1078 if ((name == NULL || strcmp(ofmt->name, name) < 0) &&
1079 strcmp(ofmt->name, last_name) > 0) {
1080 name = ofmt->name;
1081 long_name = ofmt->long_name;
1082 encode = 1;
1083 }
1084 }
1085
1086 #if (LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58,9,100))
1087 while ((ifmt = av_iformat_next(ifmt))) {
1088 #else
1089 i = 0;
1090 while ((ifmt = av_demuxer_iterate(&i))) {
1091 #endif
1092 is_dev = is_device(ifmt->priv_class);
1093
1094 if ((name == NULL || strcmp(ifmt->name, name) < 0) &&
1095 strcmp(ifmt->name, last_name) > 0) {
1096 name = ifmt->name;
1097 long_name = ifmt->long_name;
1098 encode = 0;
1099 }
1100
1101 if (name && strcmp(ifmt->name, name) == 0) decode = 1;
1102 }
1103
1104 if (name == NULL) break;
1105
1106 last_name = name;
1107
1108 stream->write_function(stream, "%s%s%s %-15s %s\n",
1109 is_dev ? "*" : " ",
1110 decode ? "D" : " ",
1111 encode ? "M" : " ",
1112 name, long_name ? long_name:" ");
1113 }
1114
1115 }
1116
1117 static void mod_avformat_destroy_output_context(av_file_context_t *context)
1118 {
1119
1120 close_stream(context->fc, &context->video_st);
1121 close_stream(context->fc, &context->audio_st[0]);
1122 close_stream(context->fc, &context->audio_st[1]);
1123
1124 if (context->audio_st[0].resample_ctx) {
1125 swr_free(&context->audio_st[0].resample_ctx);
1126 }
1127
1128 if (context->audio_st[1].resample_ctx) {
1129 swr_free(&context->audio_st[1].resample_ctx);
1130 }
1131
1132 avformat_close_input(&context->fc);
1133
1134 context->fc = NULL;
1135 context->audio_st[0].st = NULL;
1136 context->audio_st[1].st = NULL;
1137 context->video_st.st = NULL;
1138
1139 }
1140
1141 static switch_status_t open_input_file(av_file_context_t *context, switch_file_handle_t *handle, const char *filename)
1142 {
1143 AVCodec *audio_codec = NULL;
1144 AVCodec *video_codec = NULL;
1145 AVDictionary *opts = NULL;
1146 int error;
1147 int i, idx = 0;
1148 switch_status_t status = SWITCH_STATUS_SUCCESS;
1149
1150 // av_dict_set(&opts, "c:v", "libvpx", 0);
1151
1152 /** Open the input file to read from it. */
1153
1154 if (!context->fc) {
1155 context->fc = avformat_alloc_context();
1156 }
1157
1158 if (!context->fc) {
1159 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not open input file '%s' (error '%s')\n", filename, "NO MEM");
1160 switch_goto_status(SWITCH_STATUS_FALSE, err);
1161 }
1162
1163 context->fc->interrupt_callback.callback = interrupt_cb;
1164 context->fc->interrupt_callback.opaque = context;
1165
1166 if ((error = avformat_open_input(&context->fc, filename, NULL, NULL)) < 0) {
1167 char ebuf[255] = "";
1168 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Could not open input file '%s' (error '%s')\n", filename, get_error_text(error, ebuf, sizeof(ebuf)));
1169 avformat_free_context(context->fc);
1170 context->fc = NULL;
1171 switch_goto_status(SWITCH_STATUS_FALSE, err);
1172 }
1173
1174 handle->seekable = context->fc->iformat->read_seek2 ? 1 : (context->fc->iformat->read_seek ? 1 : 0);
1175 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "file %s is %sseekable\n", filename, handle->seekable ? "" : "not ");
1176
1177 /** Get information on the input file (number of streams etc.). */
1178 if ((error = avformat_find_stream_info(context->fc, opts ? &opts : NULL)) < 0) {
1179 char ebuf[255] = "";
1180 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Could not find stream info in file: %s, error = %s)\n", filename, get_error_text(error, ebuf, sizeof(ebuf)));
1181 if (opts) av_dict_free(&opts);
1182 switch_goto_status(SWITCH_STATUS_FALSE, err);
1183 }
1184
1185 if (opts) av_dict_free(&opts);
1186
1187 av_dump_format(context->fc, 0, filename, 0);
1188
1189 for (i = 0; i< context->fc->nb_streams; i++) {
1190 GCC_DIAG_OFF(deprecated-declarations)
1191 if (context->fc->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO && context->has_audio < 2 && idx < 2) {
1192 context->audio_st[idx++].st = context->fc->streams[i];
1193 context->has_audio++;
1194 } else if (context->fc->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO && !context->has_video) {
1195 GCC_DIAG_ON(deprecated-declarations)
1196 context->video_st.st = context->fc->streams[i];
1197 if (switch_test_flag(handle, SWITCH_FILE_FLAG_VIDEO)) {
1198 context->has_video = 1;
1199 handle->duration = av_rescale_q(context->video_st.st->duration != AV_NOPTS_VALUE ? context->video_st.st->duration : context->fc->duration / AV_TIME_BASE * 1000,
1200 context->video_st.st->time_base, AV_TIME_BASE_Q);
1201 }
1202
1203 if (context->fc->bit_rate) {
1204 handle->mm.source_kps = context->fc->bit_rate / 1024;
1205 }
1206
1207 if (context->video_st.st->avg_frame_rate.num) {
1208 handle->mm.source_fps = ceil(av_q2d(context->video_st.st->avg_frame_rate));
1209 } else {
1210 handle->mm.source_fps = 25;
1211 }
1212
1213 context->read_fps = (int)handle->mm.source_fps;
1214 }
1215 }
1216
1217 /** Find a decoder for the audio stream. */
1218 GCC_DIAG_OFF(deprecated-declarations)
1219 if (context->has_audio && !(audio_codec = avcodec_find_decoder(context->audio_st[0].st->codec->codec_id))) {
1220 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Could not find input codec %d\n", context->audio_st[0].st->codec->codec_id);
1221 context->has_audio = 0;
1222 }
1223
1224 if (context->has_video && !(video_codec = avcodec_find_decoder(context->video_st.st->codec->codec_id))) {
1225 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not find input codec %d\n", context->video_st.st->codec->codec_id);
1226 context->has_video = 0;
1227 }
1228
1229 if (context->has_audio && (error = avcodec_open2(context->audio_st[0].st->codec, audio_codec, NULL)) < 0) {
1230 char ebuf[255] = "";
1231 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not open input audio codec (error '%s')\n", get_error_text(error, ebuf, sizeof(ebuf)));
1232 context->has_audio = 0;
1233 }
1234
1235 if (context->has_audio == 2 && (error = avcodec_open2(context->audio_st[1].st->codec, audio_codec, NULL)) < 0) {
1236 char ebuf[255] = "";
1237 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not open input audio codec channel 2 (error '%s')\n", get_error_text(error, ebuf, sizeof(ebuf)));
1238 if (context->audio_st[0].st->codec) {
1239 avcodec_close(context->audio_st[0].st->codec);
1240 }
1241 context->has_audio = 0;
1242 }
1243
1244 if (context->has_video && (error = avcodec_open2(context->video_st.st->codec, video_codec, NULL)) < 0) {
1245 char ebuf[255] = "";
1246 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not open input codec (error '%s')\n", get_error_text(error, ebuf, sizeof(ebuf)));
1247 context->has_video = 0;
1248 }
1249 GCC_DIAG_ON(deprecated-declarations)
1250
1251 context->video_st.active = 1;
1252
1253 // printf("has audio:%d has_video:%d\n", context->has_audio, context->has_video);
1254
1255 if ((!context->has_audio) && (!context->has_video)) {
1256 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Neither audio nor video stream found in file %s\n", filename);
1257 switch_goto_status(SWITCH_STATUS_FALSE, err);
1258 }
1259
1260 if (context->has_audio) {
1261 GCC_DIAG_OFF(deprecated-declarations)
1262 AVCodecContext *c[2] = { NULL };
1263
1264 c[0] = context->audio_st[0].st->codec;
1265
1266 if (context->audio_st[1].st && context->audio_st[1].st->codec) {
1267 c[1] = context->audio_st[1].st->codec;
1268 }
1269 GCC_DIAG_ON(deprecated-declarations)
1270
1271 context->audio_st[0].frame = av_frame_alloc();
1272 switch_assert(context->audio_st[0].frame);
1273
1274 context->audio_st[0].active = 1;
1275
1276 if (c[1]) {
1277 context->audio_st[1].frame = av_frame_alloc();
1278 switch_assert(context->audio_st[1].frame);
1279 }
1280
1281 if (c[0] && c[1]) {
1282 context->audio_st[0].channels = 1;
1283 context->audio_st[1].channels = 1;
1284 } else {
1285 handle->channels = c[0]->channels > 2 ? 2 : c[0]->channels;
1286 context->audio_st[0].channels = handle->channels;
1287 }
1288
1289 context->audio_st[0].sample_rate = handle->samplerate;
1290 context->audio_st[1].sample_rate = handle->samplerate;
1291
1292 GCC_DIAG_OFF(deprecated-declarations)
1293 if (context->audio_st[0].st->codec->sample_fmt != AV_SAMPLE_FMT_S16 || context->audio_st[0].st->codec->sample_rate != handle->samplerate) {
1294 GCC_DIAG_ON(deprecated-declarations)
1295 int x;
1296 for (x = 0; x < context->has_audio && x < 2 && c[x]; x++) {
1297 struct SwrContext *resample_ctx = swr_alloc();
1298
1299 if (resample_ctx) {
1300 int ret;
1301
1302 av_opt_set_int(resample_ctx, "in_channel_count", c[x]->channels, 0);
1303 av_opt_set_int(resample_ctx, "in_sample_rate", c[x]->sample_rate, 0);
1304 av_opt_set_int(resample_ctx, "in_sample_fmt", c[x]->sample_fmt, 0);
1305 av_opt_set_int(resample_ctx, "in_channel_layout",
1306 (c[x]->channel_layout == 0 && c[x]->channels == 2) ? AV_CH_LAYOUT_STEREO : c[x]->channel_layout, 0);
1307 av_opt_set_int(resample_ctx, "out_channel_count", handle->channels, 0);
1308 av_opt_set_int(resample_ctx, "out_sample_rate", handle->samplerate,0);
1309 av_opt_set_int(resample_ctx, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0);
1310 av_opt_set_int(resample_ctx, "out_channel_layout", handle->channels == 2 ? AV_CH_LAYOUT_STEREO : AV_CH_LAYOUT_MONO, 0);
1311
1312 if ((ret = swr_init(resample_ctx)) < 0) {
1313 char errbuf[1024];
1314 av_strerror(ret, errbuf, 1024);
1315
1316 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to initialize the resampling context, ret=%d: %s\n", ret, errbuf);
1317 av_free(resample_ctx);
1318 switch_goto_status(SWITCH_STATUS_FALSE, err);
1319 }
1320
1321 context->audio_st[x].resample_ctx = resample_ctx;
1322 }
1323 }
1324 }
1325 }
1326
1327 if (!context->has_video) {
1328 switch_clear_flag(handle, SWITCH_FILE_FLAG_VIDEO);
1329 } else {
1330 GCC_DIAG_OFF(deprecated-declarations)
1331 switch (context->video_st.st->codec->pix_fmt) {
1332 case AV_PIX_FMT_YUVA420P:
1333 case AV_PIX_FMT_RGBA:
1334 case AV_PIX_FMT_ARGB:
1335 case AV_PIX_FMT_BGRA:
1336 context->handle->mm.fmt = SWITCH_IMG_FMT_ARGB;
1337 break;
1338 default:
1339 context->handle->mm.fmt = SWITCH_IMG_FMT_I420;
1340 break;
1341 }
1342 GCC_DIAG_ON(deprecated-declarations)
1343
1344 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
1345 "Opening file in mode: %s\n", context->handle->mm.fmt == SWITCH_IMG_FMT_ARGB ? "ARGB" : "I420");
1346 }
1347
1348 return status;
1349
1350 err:
1351 if (context->fc) {
1352 int nb_streams = context->fc->nb_streams;
1353
1354 if (nb_streams > 2) nb_streams = 2;
1355
1356 if (context->has_video) close_stream(context->fc, &context->video_st);
1357
1358 for (i = 0; i < nb_streams; i++) {
1359 close_stream(context->fc, &context->audio_st[i]);
1360 }
1361
1362 avformat_free_context(context->fc);
1363 context->fc = NULL;
1364 }
1365
1366 return status;
1367 }
1368
1369 //#define ALT_WAY
1370 #define AUDIO_BUF_SEC 5
1371
1372 static void *SWITCH_THREAD_FUNC file_read_thread_run(switch_thread_t *thread, void *obj)
1373 {
1374 av_file_context_t *context = (av_file_context_t *) obj;
1375 AVPacket pkt = { 0 };
1376 int got_data = 0;
1377 int error;
1378 int sync = 0;
1379 int eof = 0;
1380
1381 switch_mutex_lock(context->mutex);
1382 context->file_read_thread_started = 1;
1383 context->file_read_thread_running = 1;
1384 switch_thread_cond_signal(context->cond);
1385 switch_mutex_unlock(context->mutex);
1386
1387 while (context->file_read_thread_running && !context->closed) {
1388 int vid_frames = 0;
1389
1390 if (context->seek_ts >= 0) {
1391 int stream_id = -1;
1392
1393 switch_mutex_lock(context->mutex);
1394 switch_buffer_zero(context->audio_buffer);
1395 switch_mutex_unlock(context->mutex);
1396
1397
1398
1399 // if (context->has_audio) stream_id = context->audio_st.st->index;
1400 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "seeking to %" SWITCH_INT64_T_FMT "\n", context->seek_ts);
1401 avformat_seek_file(context->fc, stream_id, 0, context->seek_ts, INT64_MAX, 0);
1402 context->seek_ts = -2;
1403
1404 if (context->has_video) {
1405 void *pop;
1406
1407 context->video_st.next_pts = 0;
1408 context->video_start_time = 0;
1409 GCC_DIAG_OFF(deprecated-declarations)
1410 avcodec_flush_buffers(context->video_st.st->codec);
1411 GCC_DIAG_ON(deprecated-declarations)
1412
1413 while(switch_queue_trypop(context->eh.video_queue, &pop) == SWITCH_STATUS_SUCCESS) {
1414 switch_image_t *img;
1415 if (!pop) break;
1416 img = (switch_image_t *) pop;
1417 switch_img_free(&img);
1418 }
1419 }
1420 }
1421
1422 if (context->has_video) {
1423 vid_frames = switch_queue_size(context->eh.video_queue);
1424 }
1425
1426 if (switch_buffer_inuse(context->audio_buffer) > AUDIO_BUF_SEC * context->handle->samplerate * context->handle->channels * 2 &&
1427 (!context->has_video || vid_frames > 5)) {
1428 switch_yield(context->has_video ? 1000 : 10000);
1429 continue;
1430 }
1431
1432
1433
1434 GCC_DIAG_OFF(deprecated-declarations)
1435 av_init_packet(&pkt);
1436 GCC_DIAG_ON(deprecated-declarations)
1437 pkt.data = NULL;
1438 pkt.size = 0;
1439
1440 if ((error = av_read_frame(context->fc, &pkt)) < 0) {
1441 if (error == AVERROR_EOF) {
1442 if (!context->has_video) break;
1443
1444 eof = 1;
1445 /* just make sure*/
1446 pkt.data = NULL;
1447 pkt.size = 0;
1448 pkt.stream_index = context->video_st.st->index;
1449 } else {
1450 char ebuf[255] = "";
1451 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Could not read frame (error '%s')\n", get_error_text(error, ebuf, sizeof(ebuf)));
1452 continue;
1453 }
1454 }
1455
1456 // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "stream: %d, pkt size %d\n", pkt.stream_index, pkt.size);
1457 if (context->has_video && pkt.stream_index == context->video_st.st->index) {
1458 AVFrame *vframe;
1459 switch_image_t *img;
1460
1461 if (context->no_video_decode) {
1462 if (eof) {
1463 break;
1464 } else {
1465 switch_status_t status;
1466 AVPacket *new_pkt = malloc(sizeof(AVPacket));
1467
1468 if (0) { // debug
1469 uint8_t *p = pkt.data;
1470 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "size = %u %x %x %x %x %x %x\n", pkt.size, *p, *(p+1), *(p+2), *(p+3), *(p+4), *(p+5));
1471 }
1472
1473 GCC_DIAG_OFF(deprecated-declarations)
1474 av_init_packet(new_pkt);
1475 GCC_DIAG_ON(deprecated-declarations)
1476 av_packet_ref(new_pkt, &pkt);
1477 status = switch_queue_push(context->video_pkt_queue, new_pkt);
1478 // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "size = %4u flag=%x pts=%" SWITCH_INT64_T_FMT " dts=%" SWITCH_INT64_T_FMT "\n", pkt.size, pkt.flags, pkt.pts, pkt.dts);
1479
1480 context->vid_ready = 1;
1481 if (status != SWITCH_STATUS_SUCCESS) {
1482 av_packet_unref(new_pkt);
1483 free(new_pkt);
1484 }
1485 av_packet_unref(&pkt);
1486 continue;
1487 }
1488 }
1489
1490 if (!sync) {
1491 switch_buffer_zero(context->audio_buffer);
1492 sync = 1;
1493 }
1494
1495 again:
1496 vframe = av_frame_alloc();
1497 switch_assert(vframe);
1498
1499 GCC_DIAG_OFF(deprecated-declarations)
1500 if ((error = avcodec_decode_video2(context->video_st.st->codec, vframe, &got_data, &pkt)) < 0) {
1501 GCC_DIAG_ON(deprecated-declarations)
1502 char ebuf[255] = "";
1503 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Could not decode frame (error '%s')\n", get_error_text(error, ebuf, sizeof(ebuf)));
1504 av_packet_unref(&pkt);
1505 av_frame_free(&vframe);
1506 continue;
1507 }
1508
1509 // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "pkt: %d, pts: %lld dts: %lld\n", pkt.size, pkt.pts, pkt.dts);
1510 av_packet_unref(&pkt);
1511
1512 //if (switch_queue_size(context->eh.video_queue) > 300) {
1513 // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Dropping frames\n");
1514 // av_frame_free(&vframe);
1515 // continue;
1516 //}
1517 // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "got_data=%d, error=%d\n", got_data, error);
1518
1519 if (got_data && error >= 0) {
1520 switch_img_fmt_t fmt = SWITCH_IMG_FMT_I420;
1521 if ((
1522 vframe->format == AV_PIX_FMT_YUVA420P ||
1523 vframe->format == AV_PIX_FMT_RGBA ||
1524 vframe->format == AV_PIX_FMT_ARGB ||
1525 vframe->format == AV_PIX_FMT_BGRA )) {
1526 fmt = SWITCH_IMG_FMT_ARGB;
1527 } else if (vframe->format != AV_PIX_FMT_YUV420P) {
1528 AVFrame *frm = vframe;
1529 int ret;
1530
1531 if (!context->video_st.sws_ctx) {
1532 context->video_st.sws_ctx =
1533 sws_getContext(frm->width, frm->height,
1534 frm->format,
1535 frm->width, frm->height,
1536 AV_PIX_FMT_YUV420P,
1537 SCALE_FLAGS, NULL, NULL, NULL);
1538 if (!context->video_st.sws_ctx) {
1539 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Cannot init sws context\n");
1540 av_frame_free(&frm);
1541 continue;
1542 }
1543 }
1544
1545 vframe = av_frame_alloc();
1546 switch_assert(vframe);
1547
1548 vframe->format = AV_PIX_FMT_YUV420P;
1549 vframe->width = frm->width;
1550 vframe->height = frm->height;
1551 vframe->pts = frm->pts;
1552 GCC_DIAG_OFF(deprecated-declarations)
1553 vframe->pkt_pts = frm->pkt_pts;
1554 GCC_DIAG_ON(deprecated-declarations)
1555 vframe->pkt_dts = frm->pkt_dts;
1556 ret = av_frame_get_buffer(vframe, 32);
1557
1558 switch_assert(ret >= 0);
1559
1560 ret = sws_scale(context->video_st.sws_ctx, (const uint8_t *const *)frm->data, frm->linesize,
1561 0, frm->height, vframe->data, vframe->linesize);
1562
1563 av_frame_free(&frm);
1564
1565 if (ret <= 0 ) {
1566 av_frame_free(&vframe);
1567 continue;
1568 }
1569 }
1570
1571 context->handle->mm.fmt = fmt;
1572
1573 img = switch_img_alloc(NULL, fmt, vframe->width, vframe->height, 1);
1574
1575 if (img) {
1576 int64_t *pts = malloc(sizeof(int64_t));
1577
1578 if (pts) {
1579 #ifdef ALT_WAY
1580 int diff;
1581 int sleep = 66000;
1582 #endif
1583 GCC_DIAG_OFF(deprecated-declarations)
1584 *pts = vframe->pkt_pts;
1585 GCC_DIAG_ON(deprecated-declarations)
1586 avframe2img(vframe, img);
1587 img->user_priv = pts;
1588
1589 #ifdef ALT_WAY
1590 diff = sleep - (switch_time_now() - context->last_vid_push);
1591
1592 if (diff > 0 && diff <= sleep) {
1593 switch_core_timer_next(&context->video_timer);
1594 } else {
1595 switch_core_timer_sync(&context->video_timer);
1596 }
1597 #endif
1598
1599 context->vid_ready = 1;
1600 switch_queue_push(context->eh.video_queue, img);
1601 context->last_vid_push = switch_time_now();
1602 } else {
1603 switch_img_free(&img);
1604 }
1605 }
1606 }
1607
1608 av_frame_free(&vframe);
1609
1610 if (eof) {
1611 if (got_data) {
1612 goto again; // to get all delayed video frames in decoder
1613 } else {
1614 break;
1615 }
1616 }
1617 continue;
1618 } else if (context->has_audio && pkt.stream_index == context->audio_st[0].st->index) {
1619 AVFrame in_frame = { { 0 } };
1620
1621 GCC_DIAG_OFF(deprecated-declarations)
1622 if ((error = avcodec_decode_audio4(context->audio_st[0].st->codec, &in_frame, &got_data, &pkt)) < 0) {
1623 GCC_DIAG_ON(deprecated-declarations)
1624 char ebuf[255] = "";
1625 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Could not decode frame (error '%s')\n", get_error_text(error, ebuf, sizeof(ebuf)));
1626 av_packet_unref(&pkt);
1627 continue;
1628 }
1629
1630 // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "pkt: %d, decodedddd: %d pts: %lld dts: %lld\n", pkt.size, error, pkt.pts, pkt.dts);
1631 av_packet_unref(&pkt);
1632
1633 if (got_data) {
1634 // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "got data frm->format: %d samples: %d\n", in_frame.format, in_frame.nb_samples);
1635
1636 if (context->audio_st[0].resample_ctx) {
1637 int out_samples = swr_get_out_samples(context->audio_st[0].resample_ctx, in_frame.nb_samples);
1638 int ret;
1639 uint8_t *data[2] = { 0 };
1640
1641 data[0] = malloc(out_samples * context->audio_st[0].channels * 2);
1642 switch_assert(data[0]);
1643
1644 ret = swr_convert(context->audio_st[0].resample_ctx, data, out_samples,
1645 (const uint8_t **)in_frame.data, in_frame.nb_samples);
1646
1647 // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "out_samples: %d ret: %d delay: %ld buffer: %zu\n", out_samples, ret, swr_get_delay(context->audio_st[0].resample_ctx, 8000), switch_buffer_inuse(context->audio_buffer));
1648
1649 if (ret) {
1650 switch_mutex_lock(context->mutex);
1651 switch_buffer_write(context->audio_buffer, data[0], ret * 2 * context->audio_st[0].channels);
1652 switch_mutex_unlock(context->mutex);
1653 }
1654
1655 // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "decoded samples: %d\n", ret);
1656
1657 free(data[0]);
1658
1659 // if (ret == 0 && avresample_get_delay(context->audio_st[0].resample_ctx)) {
1660 // frameP = NULL;
1661 // goto again;
1662 // }
1663
1664 } else {
1665 //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "this block is not tested samples: %d\n", in_frame.nb_samples);
1666 switch_mutex_lock(context->mutex);
1667 switch_buffer_write(context->audio_buffer, in_frame.data[0], in_frame.nb_samples * 2 * context->audio_st[0].channels);
1668 switch_mutex_unlock(context->mutex);
1669 }
1670
1671 }
1672
1673 } else {
1674 av_packet_unref(&pkt);
1675 }
1676 }
1677
1678 if (context->has_video) switch_queue_push(context->eh.video_queue, NULL);
1679
1680 context->file_read_thread_running = 0;
1681
1682 return NULL;
1683 }
1684
1685 static switch_status_t av_file_open(switch_file_handle_t *handle, const char *path)
1686 {
1687 av_file_context_t *context = NULL;
1688 char *ext;
1689 const char *tmp = NULL;
1690 AVOutputFormat *fmt;
1691 const char *format = NULL;
1692 int ret;
1693 char file[1024];
1694 int disable_write_buffer = 0;
1695 switch_status_t status = SWITCH_STATUS_SUCCESS;
1696
1697 switch_set_string(file, path);
1698
1699 if (handle->stream_name) {
1700 disable_write_buffer = 1;
1701 }
1702
1703 if (handle->stream_name && (!strcasecmp(handle->stream_name, "rtmp") || !strcasecmp(handle->stream_name, "rtmps") || !strcasecmp(handle->stream_name, "youtube"))) {
1704 char *secure = "";
1705
1706 format = "flv";
1707 if ((ext = strrchr((char *)path, '.')) == 0) {
1708 ext = ".flv";
1709 }
1710
1711 if (!strcasecmp(handle->stream_name, "rtmps")) secure = "s";
1712
1713 // meh really silly format for the user / pass libav.....
1714 if (handle->mm.auth_username && handle->mm.auth_password) {
1715 switch_snprintf(file, sizeof(file), "rtmp%s://%s pubUser=%s pubPasswd=%s flashver=FMLE/3.0", secure, path, handle->mm.auth_username, handle->mm.auth_password);
1716 } else {
1717 switch_snprintf(file, sizeof(file), "rtmp%s://%s", secure, path);
1718 }
1719
1720 } else if (handle->stream_name && !strcasecmp(handle->stream_name, "rtsp")) {
1721 format = "rtsp";
1722 if ((ext = strrchr((char *)path, '.')) == 0) {
1723 ext = ".rtsp";
1724 }
1725 switch_snprintf(file, sizeof(file), "rtsp://%s", path);
1726 disable_write_buffer = 1;
1727 } else if ((ext = strrchr((char *)path, '.')) == 0) {
1728 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Format\n");
1729 return SWITCH_STATUS_GENERR;
1730 }
1731
1732
1733 ext++;
1734
1735 if ((context = (av_file_context_t *)switch_core_alloc(handle->memory_pool, sizeof(av_file_context_t))) == 0) {
1736 switch_goto_status(SWITCH_STATUS_MEMERR, end);
1737 }
1738
1739 memset(context, 0, sizeof(av_file_context_t));
1740 handle->private_info = context;
1741 context->pool = handle->memory_pool;
1742 context->seek_ts = -1;
1743 context->offset = DFT_RECORD_OFFSET;
1744 context->handle = handle;
1745 context->audio_timer = 1;
1746 context->colorspace = avformat_globals.colorspace;
1747
1748 if (handle->params) {
1749 if ((tmp = switch_event_get_header(handle->params, "av_video_offset"))) {
1750 context->offset = atoi(tmp);
1751 }
1752 if ((tmp = switch_event_get_header(handle->params, "video_time_audio"))) {
1753 if (switch_false(tmp)) {
1754 context->audio_timer = 0;
1755 }
1756 }
1757 if ((tmp = switch_event_get_header(handle->params, "colorspace"))) {
1758 int value = atoi(tmp);
1759 enum AVColorSpace colorspace = UINTVAL(value);
1760
1761 if (colorspace <= AVCOL_SPC_NB) {
1762 context->colorspace = colorspace;
1763 }
1764 }
1765 }
1766
1767 switch_mutex_init(&context->mutex, SWITCH_MUTEX_NESTED, handle->memory_pool);
1768 switch_thread_cond_create(&context->cond, handle->memory_pool);
1769 switch_buffer_create_dynamic(&context->audio_buffer, 512, 512, 0);
1770
1771 if (!context->audio_buffer) {
1772 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not allocate buffer for %s\n", path);
1773 switch_goto_status(SWITCH_STATUS_MEMERR, end);
1774 }
1775
1776 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "sample rate: %d, channels: %d\n", handle->samplerate, handle->channels);
1777
1778 if (switch_test_flag(handle, SWITCH_FILE_FLAG_READ)) {
1779 if (open_input_file(context, handle, path) != SWITCH_STATUS_SUCCESS) {
1780 //clean up;
1781 switch_goto_status(SWITCH_STATUS_GENERR, end);
1782 }
1783
1784 if (context->has_video) {
1785 switch_fps_t fps_data = { 0 };
1786 switch_queue_create(&context->eh.video_queue, context->read_fps, handle->memory_pool);
1787 context->no_video_decode = handle->params && switch_true(switch_event_get_header(handle->params, "no_video_decode"));
1788 if (context->no_video_decode) {
1789 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Opening video in no decode mode\n");
1790 switch_queue_create(&context->video_pkt_queue, 120 * 5, handle->memory_pool);
1791 }
1792 switch_mutex_init(&context->eh.mutex, SWITCH_MUTEX_NESTED, handle->memory_pool);
1793 switch_calc_video_fps(&fps_data, context->read_fps);
1794 switch_core_timer_init(&context->video_timer, "soft", fps_data.ms, fps_data.samples, context->pool);
1795 }
1796
1797 {
1798 switch_threadattr_t *thd_attr = NULL;
1799
1800 switch_threadattr_create(&thd_attr, handle->memory_pool);
1801 switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
1802 switch_thread_create(&context->file_read_thread, thd_attr, file_read_thread_run, context, handle->memory_pool);
1803 }
1804
1805 return SWITCH_STATUS_SUCCESS;
1806 }
1807
1808 mod_avformat_alloc_output_context2(&context->fc, NULL, format, (char *)file, context);
1809
1810 if (!context->fc) {
1811 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Could not deduce output format from file extension\n");
1812 switch_goto_status(SWITCH_STATUS_GENERR, end);
1813 }
1814
1815 fmt = context->fc->oformat;
1816
1817 if (handle->params && (tmp = switch_event_get_header(handle->params, "av_audio_codec"))) {
1818 if ((context->audio_codec = avcodec_find_encoder_by_name(tmp))) {
1819 fmt->audio_codec = context->audio_codec->id;
1820 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "specified audio codec %s %s [%s]\n",
1821 tmp, context->audio_codec->name, context->audio_codec->long_name);
1822
1823 if (!strcasecmp(tmp, "pcm_mulaw")) {
1824 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "specified audio codec requires 8000hz\n");
1825 handle->mm.samplerate = 8000;
1826 handle->mm.ab = 64;
1827
1828 if (!switch_event_get_header(handle->params, "channelsplit")) {
1829 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "specified audio codec requires mono\n");
1830 handle->real_channels = handle->channels;
1831 handle->channels = 1;
1832 handle->mm.channels = 1;
1833 }
1834 }
1835 }
1836 }
1837
1838 if (handle->params && (tmp = switch_event_get_header(handle->params, "av_video_codec"))) {
1839 if ((context->video_codec = avcodec_find_encoder_by_name(tmp))) {
1840 fmt->video_codec = context->video_codec->id;
1841 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "specified video codec %s %s [%s]\n",
1842 tmp, context->video_codec->name, context->video_codec->long_name);
1843 }
1844 }
1845
1846 if (!strcasecmp(ext, "wav") || (handle->params && switch_true(switch_event_get_header(handle->params, "av_record_audio_only")))) {
1847 context->has_video = 0;
1848 switch_clear_flag(handle, SWITCH_FILE_FLAG_VIDEO);
1849 }
1850
1851 /* open the output file, if needed */
1852 if (!(fmt->flags & AVFMT_NOFILE)) {
1853 ret = avio_open(&context->fc->pb, file, AVIO_FLAG_WRITE);
1854 if (ret < 0) {
1855 char ebuf[255] = "";
1856 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not open '%s': %s\n", file, get_error_text(ret, ebuf, sizeof(ebuf)));
1857 switch_goto_status(SWITCH_STATUS_GENERR, end);
1858 }
1859 } else {
1860 avformat_network_init();
1861 }
1862
1863 if (handle->mm.samplerate) {
1864 handle->samplerate = handle->mm.samplerate;
1865 } else {
1866 handle->mm.samplerate = handle->samplerate;
1867 }
1868
1869 if (!handle->mm.ab) {
1870 handle->mm.ab = 128;
1871 }
1872
1873 if (!handle->mm.vb) {
1874 handle->mm.vb = switch_calc_bitrate(handle->mm.vw, handle->mm.vh, 1, handle->mm.fps);
1875 }
1876
1877 if (switch_test_flag(handle, SWITCH_FILE_FLAG_VIDEO) && fmt->video_codec != AV_CODEC_ID_NONE) {
1878 const AVCodecDescriptor *desc;
1879
1880 if ((handle->stream_name && (!strcasecmp(handle->stream_name, "rtmp") || !strcasecmp(handle->stream_name, "rtmps") || !strcasecmp(handle->stream_name, "youtube")))) {
1881
1882 if (fmt->video_codec != AV_CODEC_ID_H264 ) {
1883 fmt->video_codec = AV_CODEC_ID_H264; // force H264
1884 }
1885
1886 fmt->audio_codec = AV_CODEC_ID_AAC;
1887 handle->samplerate = 44100;
1888 handle->mm.samplerate = 44100;
1889 handle->mm.ab = 128;
1890 handle->mm.cbr = 1;
1891 handle->mm.vencspd = SWITCH_VIDEO_ENCODE_SPEED_FAST;
1892 handle->mm.vprofile = SWITCH_VIDEO_PROFILE_BASELINE;
1893
1894 if (!handle->mm.vb && handle->mm.vw && handle->mm.vh) {
1895 switch(handle->mm.vh) {
1896 case 240:
1897 handle->mm.vb = 400;
1898 break;
1899 case 360:
1900 handle->mm.vb = 750;
1901 break;
1902 case 480:
1903 handle->mm.vb = 1000;
1904 break;
1905 case 720:
1906 handle->mm.vb = 2500;
1907 break;
1908 case 1080:
1909 handle->mm.vb = 4500;
1910 break;
1911 default:
1912 handle->mm.vb = switch_calc_bitrate(handle->mm.vw, handle->mm.vh, 1, handle->mm.fps);
1913 break;
1914 }
1915 }
1916
1917 if (handle->mm.fps > 0.0f) {
1918 handle->mm.keyint = (int) 2.0f * handle->mm.fps;
1919 }
1920 }
1921
1922 desc = avcodec_descriptor_get(fmt->video_codec);
1923
1924 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "use video codec: [%d] %s (%s)\n", fmt->video_codec, desc->name, desc->long_name);
1925 }
1926
1927 if (fmt->audio_codec != AV_CODEC_ID_NONE) {
1928 const char *issplit = 0;
1929
1930 context->audio_st[0].channels = handle->channels;
1931 context->audio_st[1].sample_rate = handle->samplerate;
1932
1933 if (handle->channels > 1 && handle->params && (issplit = switch_event_get_header(handle->params, "channelsplit"))) {
1934 int lr = (!strcasecmp(issplit, "lr") || switch_true(issplit));
1935 int rl = !strcasecmp(issplit, "rl");
1936
1937 if (lr || rl) {
1938 context->audio_st[0].channels = 1;
1939 context->audio_st[1].channels = 1;
1940 add_stream(context, &context->audio_st[0], context->fc, &context->audio_codec, fmt->audio_codec, &handle->mm);
1941 add_stream(context, &context->audio_st[1], context->fc, &context->audio_codec, fmt->audio_codec, &handle->mm);
1942 }
1943
1944 if (lr) {
1945 context->audio_st[0].r = 1;
1946 } else if (rl) {
1947 context->audio_st[1].r = 1;
1948 }
1949 }
1950
1951 if (!context->audio_st[0].active) {
1952 add_stream(context, &context->audio_st[0], context->fc, &context->audio_codec, fmt->audio_codec, &handle->mm);
1953 }
1954
1955 if (open_audio(context->fc, context->audio_codec, &context->audio_st[0]) != SWITCH_STATUS_SUCCESS) {
1956 switch_goto_status(SWITCH_STATUS_GENERR, end);
1957 }
1958
1959 context->has_audio = 1;
1960
1961 if (context->audio_st[1].active) {
1962 if (open_audio(context->fc, context->audio_codec, &context->audio_st[1]) != SWITCH_STATUS_SUCCESS) {
1963 switch_goto_status(SWITCH_STATUS_GENERR, end);
1964 }
1965
1966 context->has_audio++;
1967 }
1968 }
1969
1970 av_dump_format(context->fc, 0, file, 1);
1971
1972 handle->format = 0;
1973 handle->sections = 0;
1974 handle->seekable = 0;
1975 handle->speed = 0;
1976 handle->pos = 0;
1977
1978 if (disable_write_buffer) {
1979 handle->pre_buffer_datalen = 0;
1980 }
1981
1982 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Opening File [%s] %dhz %s\n",
1983 file, handle->samplerate, context->has_video ? " with VIDEO" : "");
1984
1985 return SWITCH_STATUS_SUCCESS;
1986
1987 end:
1988
1989 if (!context) {
1990 return status;
1991 }
1992
1993 if (context->fc) {
1994 mod_avformat_destroy_output_context(context);
1995 }
1996
1997 if (context->video_timer.interval) {
1998 switch_core_timer_destroy(&context->video_timer);
1999 }
2000
2001 if (context->audio_buffer) {
2002 switch_buffer_destroy(&context->audio_buffer);
2003 }
2004
2005 return status;
2006 }
2007
2008 static switch_status_t av_file_truncate(switch_file_handle_t *handle, int64_t offset)
2009 {
2010 return SWITCH_STATUS_FALSE;
2011 }
2012
2013
2014 static switch_status_t av_file_write(switch_file_handle_t *handle, void *data, size_t *len)
2015 {
2016 uint32_t datalen = 0;
2017 switch_status_t status = SWITCH_STATUS_SUCCESS;
2018 // uint8_t buf[SWITCH_RECOMMENDED_BUFFER_SIZE] = { 0 }, *bp = buf;
2019 // uint32_t encoded_rate;
2020 av_file_context_t *context = (av_file_context_t *)handle->private_info;
2021 // uint32_t size = 0;
2022 uint32_t bytes;
2023 int inuse;
2024 int sample_start = 0;
2025
2026 if (!switch_test_flag(handle, SWITCH_FILE_FLAG_WRITE)) {
2027 return SWITCH_STATUS_FALSE;
2028 }
2029
2030 if (!context->vid_ready) {
2031 if (switch_test_flag(handle, SWITCH_FILE_FLAG_VIDEO)) {
2032 switch_buffer_zero(context->audio_buffer);
2033 return status;
2034 } else if (!context->aud_ready) { // audio only recording
2035 int ret = avformat_write_header(context->fc, NULL);
2036 if (ret < 0) {
2037 char ebuf[255] = "";
2038 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error occurred when opening output file: %s\n", get_error_text(ret, ebuf, sizeof(ebuf)));
2039 return SWITCH_STATUS_FALSE;
2040 }
2041 context->aud_ready = 1;
2042 }
2043 }
2044
2045 if (data && len) {
2046 datalen = *len * 2 * handle->channels;
2047
2048 if (context->offset) {
2049 switch_size_t samples = *len;
2050 int fps = handle->samplerate / samples;
2051 int lead_frames = (context->offset * fps) / 1000;
2052
2053 for (int x = 0; x < lead_frames; x++) {
2054 switch_buffer_zero_fill(context->audio_buffer, datalen);
2055 }
2056 context->offset = 0;
2057 }
2058
2059 switch_buffer_write(context->audio_buffer, data, datalen);
2060 }
2061
2062 GCC_DIAG_OFF(deprecated-declarations)
2063 bytes = context->audio_st[0].frame->nb_samples * 2 * context->handle->channels; //context->audio_st[0].st->codec->channels;
2064 GCC_DIAG_ON(deprecated-declarations)
2065
2066 //{
2067 // int inuse = switch_buffer_inuse(context->audio_buffer);
2068 // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "inuse: %d samples: %d bytes: %d\n", inuse, context->audio_st[0].frame->nb_samples, bytes);
2069 //}
2070
2071 if (context->closed) {
2072 inuse = switch_buffer_inuse(context->audio_buffer);
2073 if (inuse < bytes) {
2074 switch_buffer_zero_fill(context->audio_buffer, bytes - inuse);
2075 }
2076 }
2077
2078
2079 if (context->video_timer.interval) {
2080 int delta;
2081 switch_core_timer_sync(&context->video_timer);
2082
2083 delta = context->video_timer.samplecount - context->last_vid_write;
2084
2085 if (context->audio_timer || delta >= 200) {
2086 uint32_t new_pts = context->video_timer.samplecount * (handle->samplerate / 1000);
2087 if (!context->audio_timer) {
2088 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Delta of %d detected. Video timer sync: %" SWITCH_UINT64_T_FMT "/%d %" SWITCH_UINT64_T_FMT "\n", delta, context->audio_st[0].next_pts, context->video_timer.samplecount, new_pts - context->audio_st[0].next_pts);
2089 }
2090 sample_start = new_pts;
2091 }
2092
2093 context->last_vid_write = context->video_timer.samplecount;
2094 }
2095
2096
2097 if (sample_start) {
2098 int j = 0;
2099
2100 for (j = 0; j < 2; j++) {
2101 if (context->audio_st[j].active) {
2102 context->audio_st[j].next_pts = sample_start;
2103 }
2104 }
2105 }
2106
2107 while (switch_buffer_inuse(context->audio_buffer) >= bytes) {
2108 AVPacket pkt[2] = { {0} };
2109 int got_packet[2] = {0};
2110 int j = 0, ret = -1, audio_stream_count = 1;
2111 AVFrame *use_frame = NULL;
2112
2113 GCC_DIAG_OFF(deprecated-declarations)
2114 av_init_packet(&pkt[0]);
2115 av_init_packet(&pkt[1]);
2116 GCC_DIAG_ON(deprecated-declarations)
2117
2118 if (context->audio_st[1].active) {
2119 switch_size_t len = 0;
2120 int i = 0, j = 0;
2121 int l = 0, r = 1;
2122
2123 if (!context->mux_buf || context->mux_buf_len < bytes / 2) {
2124 context->mux_buf_len = bytes / 2;
2125 context->mux_buf = (int16_t *)realloc((void *)context->mux_buf, context->mux_buf_len * 2);
2126 }
2127
2128 audio_stream_count = 2;
2129 len = switch_buffer_read(context->audio_buffer, (uint8_t *)context->mux_buf, bytes);
2130
2131 if (context->audio_st[0].r) {
2132 l = 1;
2133 r = 0;
2134 }
2135
2136 for (i = 0; i < len / 4; i++) {
2137 *((int16_t *)context->audio_st[l].frame->data[0] + i) = context->mux_buf[j++];
2138 *((int16_t *)context->audio_st[r].frame->data[0] + i) = context->mux_buf[j++];
2139 }
2140 } else {
2141 switch_buffer_read(context->audio_buffer, context->audio_st[0].frame->data[0], bytes);
2142 }
2143
2144 for (j = 0; j < audio_stream_count; j++) {
2145
2146 av_frame_make_writable(context->audio_st[j].frame);
2147 use_frame = context->audio_st[j].frame;
2148
2149 if (context->audio_st[j].resample_ctx) {
2150 int out_samples = swr_get_out_samples(context->audio_st[j].resample_ctx, context->audio_st[j].frame->nb_samples);
2151
2152 av_frame_make_writable(context->audio_st[j].tmp_frame);
2153
2154 /* convert to destination format */
2155 ret = swr_convert(context->audio_st[j].resample_ctx,
2156 context->audio_st[j].tmp_frame->data, out_samples,
2157 (const uint8_t **)context->audio_st[j].frame->data, context->audio_st[j].frame->nb_samples);
2158
2159 if (ret < 0) {
2160 char ebuf[255] = "";
2161 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error while converting %d samples, error text: %s\n",
2162 context->audio_st[j].frame->nb_samples, get_error_text(ret, ebuf, sizeof(ebuf)));
2163 continue;
2164 }
2165
2166 use_frame = context->audio_st[j].tmp_frame;
2167 }
2168
2169 use_frame->pts = context->audio_st[j].next_pts;
2170
2171 // context->audio_st[j].next_pts = use_frame->pts + use_frame->nb_samples;
2172
2173 GCC_DIAG_OFF(deprecated-declarations)
2174 ret = avcodec_encode_audio2(context->audio_st[j].st->codec, &pkt[j], use_frame, &got_packet[j]);
2175 GCC_DIAG_ON(deprecated-declarations)
2176
2177 context->audio_st[j].next_pts += use_frame->nb_samples;
2178 }
2179
2180 if (ret < 0) {
2181 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Error encoding audio frame: %d\n", ret);
2182 continue;
2183 }
2184
2185 for (j = 0; j < audio_stream_count; j++) {
2186 if (got_packet[j]) {
2187 if (context->mutex) switch_mutex_lock(context->mutex);
2188 GCC_DIAG_OFF(deprecated-declarations)
2189 ret = write_frame(context->fc, &context->audio_st[j].st->codec->time_base, context->audio_st[j].st, &pkt[j]);
2190 GCC_DIAG_ON(deprecated-declarations)
2191 if (context->mutex) switch_mutex_unlock(context->mutex);
2192
2193 if (ret < 0) {
2194 context->errs++;
2195 if ((context->errs % 10) == 0) {
2196 char ebuf[255] = "";
2197 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error while writing audio frame: %s\n", get_error_text(ret, ebuf, sizeof(ebuf)));
2198 }
2199 //switch_goto_status(SWITCH_STATUS_FALSE, end);
2200 } else {
2201 context->errs = 0;
2202 }
2203
2204 if (context->errs > 1000) {
2205 status = SWITCH_STATUS_FALSE;
2206 goto end;
2207 }
2208 }
2209 }
2210 }
2211
2212 end:
2213
2214 return status;
2215 }
2216
2217 static switch_status_t av_file_command(switch_file_handle_t *handle, switch_file_command_t command)
2218 {
2219 av_file_context_t *context = (av_file_context_t *)handle->private_info;
2220 uint32_t offset = 0;
2221
2222 switch(command) {
2223 case SCFC_FLUSH_AUDIO:
2224 switch_mutex_lock(context->mutex);
2225 switch_buffer_zero(context->audio_buffer);
2226 switch_mutex_unlock(context->mutex);
2227 break;
2228 case SCFC_PAUSE_READ:
2229 if (context->read_paused) {
2230 context->read_paused = SWITCH_FALSE;
2231 context->video_st.next_pts = 0;
2232 context->video_start_time = 0;
2233 } else {
2234 context->read_paused = SWITCH_TRUE;
2235 }
2236 break;
2237 case SCFC_PAUSE_WRITE:
2238 context->vid_ready = 0;
2239 context->eh.record_timer_paused = switch_micro_time_now();
2240 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s pause write\n", handle->file_path);
2241 break;
2242 case SCFC_RESUME_WRITE:
2243 if (context->eh.record_timer_paused) {
2244 context->eh.last_ts = 0;
2245 offset = (uint32_t)(switch_micro_time_now() - context->eh.record_timer_paused);
2246 context->video_timer.start += offset;
2247 switch_core_timer_sync(&context->video_timer);
2248 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s resume write\n", handle->file_path);
2249 context->eh.record_timer_paused = 0;
2250 }
2251 break;
2252 default:
2253 break;
2254 }
2255
2256 return SWITCH_STATUS_SUCCESS;
2257 }
2258
2259 static switch_status_t av_file_close(switch_file_handle_t *handle)
2260 {
2261 av_file_context_t *context = (av_file_context_t *)handle->private_info;
2262 switch_status_t status;
2263
2264 context->closed = 1;
2265 context->eh.finalize = 1;
2266
2267 if (context->eh.video_queue) {
2268 if (!switch_test_flag(handle, SWITCH_FILE_FLAG_WRITE)) {
2269 flush_video_queue(context->eh.video_queue, 0);
2270 switch_queue_push(context->eh.video_queue, NULL);
2271 switch_queue_term(context->eh.video_queue);
2272 } else {
2273 switch_queue_push(context->eh.video_queue, NULL);
2274 }
2275 }
2276
2277 if (context->eh.video_thread) {
2278 switch_thread_join(&status, context->eh.video_thread);
2279 }
2280
2281 if (switch_test_flag(handle, SWITCH_FILE_FLAG_WRITE)) {
2282 av_file_write(handle, NULL, NULL);
2283 }
2284
2285 if (context->file_read_thread_running) {
2286 context->file_read_thread_running = 0;
2287 }
2288
2289 if (context->video_pkt_queue) {
2290 flush_video_pkt_queue(context->video_pkt_queue);
2291 switch_queue_term(context->video_pkt_queue);
2292 }
2293
2294 if (context->packetizer) {
2295 switch_packetizer_close(&context->packetizer);
2296 }
2297
2298 if (context->file_read_thread) {
2299 switch_thread_join(&status, context->file_read_thread);
2300 context->file_read_thread = NULL;
2301 }
2302
2303 if (context->eh.video_queue) {
2304 flush_video_queue(context->eh.video_queue, 0);
2305 }
2306
2307 if (context->fc) {
2308 if ((context->aud_ready || context->has_video) && switch_test_flag(handle, SWITCH_FILE_FLAG_WRITE)) {
2309 av_write_trailer(context->fc);
2310 }
2311
2312 mod_avformat_destroy_output_context(context);
2313 }
2314
2315 if (context->video_timer.interval) {
2316 switch_core_timer_destroy(&context->video_timer);
2317 }
2318
2319 switch_img_free(&context->last_img);
2320
2321 switch_buffer_destroy(&context->audio_buffer);
2322
2323 switch_safe_free(context->mux_buf);
2324
2325 return SWITCH_STATUS_SUCCESS;
2326 }
2327
2328 static switch_status_t av_file_seek(switch_file_handle_t *handle, unsigned int *cur_sample, int64_t samples, int whence)
2329 {
2330 av_file_context_t *context = (av_file_context_t *)handle->private_info;
2331
2332 if (whence == SEEK_SET) {
2333 handle->pos = handle->offset_pos = samples;
2334 }
2335
2336 context->seek_ts = samples / handle->native_rate * AV_TIME_BASE;
2337 *cur_sample = context->seek_ts;
2338
2339 context->closed = 0;
2340
2341 if (!context->file_read_thread_running) {
2342 switch_threadattr_t *thd_attr = NULL;
2343
2344 if (context->file_read_thread) {
2345 switch_status_t status;
2346 switch_thread_join(&status, context->file_read_thread);
2347 context->file_read_thread = NULL;
2348 }
2349
2350 switch_threadattr_create(&thd_attr, handle->memory_pool);
2351 switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
2352 switch_thread_create(&context->file_read_thread, thd_attr, file_read_thread_run, context, handle->memory_pool);
2353 }
2354
2355 return SWITCH_STATUS_FALSE;
2356 }
2357
2358 static switch_status_t av_file_read(switch_file_handle_t *handle, void *data, size_t *len)
2359 {
2360 av_file_context_t *context = (av_file_context_t *)handle->private_info;
2361 int size;
2362 size_t need = *len * 2 * context->audio_st[0].channels;
2363
2364 if (!context->has_audio && context->has_video && context->file_read_thread_running) {
2365 memset(data, 0, *len * handle->channels * 2);
2366 return SWITCH_STATUS_SUCCESS;
2367 }
2368
2369 switch_mutex_lock(context->mutex);
2370
2371 while (!context->file_read_thread_started) {
2372 switch_thread_cond_wait(context->cond, context->mutex);
2373 }
2374 switch_mutex_unlock(context->mutex);
2375
2376 if (context->closed || (!context->file_read_thread_running && switch_buffer_inuse(context->audio_buffer) == 0)) {
2377 *len = 0;
2378 return SWITCH_STATUS_FALSE;
2379 }
2380
2381 while (context->has_video && !context->vid_ready && !context->closed) {
2382 switch_yield(1000);
2383 }
2384
2385 switch_mutex_lock(context->mutex);
2386 size = switch_buffer_read(context->audio_buffer, data, need);
2387 switch_mutex_unlock(context->mutex);
2388
2389 if (size == 0) {
2390 size_t blank = (handle->samplerate / 20) * 2 * handle->real_channels;
2391
2392 if (need > blank) {
2393 need = blank;
2394 }
2395 memset(data, 0, need);
2396 *len = need / 2 / handle->real_channels;
2397 } else {
2398 *len = size / context->audio_st[0].channels / 2;
2399 }
2400
2401 handle->pos += *len;
2402 handle->sample_count += *len;
2403
2404 return *len == 0 ? SWITCH_STATUS_FALSE : SWITCH_STATUS_SUCCESS;
2405 }
2406
2407
2408 #ifdef ALT_WAY
2409 static switch_status_t av_file_read_video(switch_file_handle_t *handle, switch_frame_t *frame, switch_video_read_flag_t flags)
2410 {
2411 void *pop;
2412 av_file_context_t *context = (av_file_context_t *)handle->private_info;
2413 switch_status_t status;
2414
2415
2416 if (!context->has_video || context->closed) return SWITCH_STATUS_FALSE;
2417 if ((flags & SVR_CHECK)) {
2418 return SWITCH_STATUS_BREAK;
2419 }
2420
2421 if ((flags & SVR_FLUSH)) {
2422 flush_video_queue(context->eh.video_queue, 1);
2423 }
2424
2425 if ((flags & SVR_BLOCK)) {
2426 status = switch_queue_pop(context->eh.video_queue, &pop);
2427 } else {
2428 status = switch_queue_trypop(context->eh.video_queue, &pop);
2429 }
2430
2431 if (status == SWITCH_STATUS_SUCCESS) {
2432 if (!pop) {
2433 return SWITCH_STATUS_FALSE;
2434 }
2435
2436 context->vid_ready = 1;
2437
2438 frame->img = (switch_image_t *) pop;
2439
2440 if (frame->img) {
2441 if (frame->img && context->handle->mm.scale_w && context->handle->mm.scale_h) {
2442 if (frame->img->d_w != context->handle->mm.scale_w || frame->img->d_h != context->handle->mm.scale_h) {
2443 switch_img_fit(&frame->img, context->handle->mm.scale_w, context->handle->mm.scale_h, SWITCH_FIT_SIZE);
2444 }
2445 }
2446 context->vid_ready = 1;
2447 }
2448
2449 return SWITCH_STATUS_SUCCESS;
2450 }
2451
2452 return (flags & SVR_FLUSH) ? SWITCH_STATUS_BREAK : status;
2453 }
2454 #else
2455
2456 static switch_status_t no_video_decode_packets(switch_file_handle_t *handle, switch_frame_t *frame, switch_video_read_flag_t flags)
2457 {
2458 av_file_context_t *context = (av_file_context_t *)handle->private_info;
2459 MediaStream *mst = &context->video_st;
2460 AVStream *st = mst->st;
2461 // AVCodecContext *ctx = st->codec;
2462 // int ticks = 0;
2463 // int64_t max_delta = 1 * AV_TIME_BASE; // 1 second
2464 switch_status_t status = SWITCH_STATUS_SUCCESS;
2465 AVPacket *pkt;
2466 int64_t pts;
2467
2468
2469 if (!context->packetizer) {
2470 // uint8_t *p = st->codecpar->extradata;
2471 // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "size = %u %x %x %x %x %x %x\n", st->codecpar->extradata_size, *p, *(p+1), *(p+2), *(p+3), *(p+4), *(p+5));
2472
2473 context->packetizer = switch_packetizer_create(SPT_H264_SIZED_BITSTREAM, SLICE_SIZE);
2474 if (!context->packetizer) return SWITCH_STATUS_FALSE;
2475
2476 switch_packetizer_feed_extradata(context->packetizer, st->codecpar->extradata, st->codecpar->extradata_size);
2477 }
2478
2479 if (context->last_read_pkt) {
2480 status = switch_packetizer_read(context->packetizer, frame);
2481 if (status == SWITCH_STATUS_SUCCESS) {
2482 av_packet_unref(context->last_read_pkt);
2483 free(context->last_read_pkt);
2484 context->last_read_pkt = NULL;
2485 }
2486 return status;
2487 }
2488
2489 status = switch_queue_trypop(context->video_pkt_queue, (void **)&pkt);
2490
2491 if (status != SWITCH_STATUS_SUCCESS || !pkt) {
2492 switch_cond_next();
2493 return SWITCH_STATUS_BREAK;
2494 }
2495
2496 context->last_read_pkt = pkt;
2497 switch_packetizer_feed(context->packetizer, pkt->data, pkt->size);
2498 status = switch_packetizer_read(context->packetizer, frame);
2499 pts = av_rescale_q(pkt->pts, st->time_base, AV_TIME_BASE_Q);
2500 frame->timestamp = pts * 9 / 100; // scale to sample 900000
2501 // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "pts=%" SWITCH_INT64_T_FMT " status = %d\n", pts, status);
2502
2503 if (status == SWITCH_STATUS_SUCCESS) {
2504 av_packet_unref(context->last_read_pkt);
2505 free(context->last_read_pkt);
2506 context->last_read_pkt = NULL;
2507 }
2508
2509
2510 if (status == SWITCH_STATUS_SUCCESS || status == SWITCH_STATUS_MORE_DATA) {
2511 if (!context->video_start_time) {
2512 context->video_start_time = switch_time_now() - pts;
2513 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "set start time: %" SWITCH_INT64_T_FMT " now: %" SWITCH_INT64_T_FMT " pts: %" SWITCH_INT64_T_FMT "\n", context->video_start_time, switch_time_now(), pts);
2514 } else if (flags & SVR_BLOCK) {
2515 int64_t sleep = pts - (switch_time_now() - context->video_start_time);
2516 if (sleep > 0) {
2517 // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "zzZ... %" SWITCH_INT64_T_FMT "\n", sleep);
2518 if (sleep > 1000000) {
2519 sleep = 1000000;
2520 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "but zzZ... %" SWITCH_INT64_T_FMT " at most\n", sleep);
2521 }
2522 switch_yield(sleep);
2523 } else {
2524 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "video is late %" SWITCH_INT64_T_FMT "\n", sleep);
2525 }
2526 }
2527 }
2528
2529 return status;
2530 }
2531
2532 static switch_status_t av_file_read_video(switch_file_handle_t *handle, switch_frame_t *frame, switch_video_read_flag_t flags)
2533 {
2534 av_file_context_t *context = (av_file_context_t *)handle->private_info;
2535 void *pop;
2536 MediaStream *mst = &context->video_st;
2537 AVStream *st = mst->st;
2538 int ticks = 0;
2539 int64_t max_delta = 1 * AV_TIME_BASE; // 1 second
2540 switch_status_t status = SWITCH_STATUS_SUCCESS;
2541 double fl_to = 0.02;
2542 int do_fl = 0;
2543 int smaller_ts = context->read_fps;
2544
2545 if (!context->has_video) return SWITCH_STATUS_FALSE;
2546
2547 if ((flags & SVR_CHECK)) {
2548 return SWITCH_STATUS_BREAK;
2549 }
2550
2551 if (context->no_video_decode) {
2552 switch_set_flag(frame, SFF_ENCODED);
2553 status = no_video_decode_packets(handle, frame, flags);
2554 // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "return len=%4u nalu=%02x m=%d ts=%u\n", frame->datalen, *(uint8_t *)frame->data, frame->m, frame->timestamp);
2555 return status;
2556 }
2557
2558 if (handle->mm.fps > 0 && handle->mm.fps < smaller_ts) {
2559 smaller_ts = handle->mm.fps;
2560 }
2561
2562 fl_to = (1000 / smaller_ts) * 1000;
2563 //printf("WTF %d (%f)\n",switch_queue_size(context->eh.video_queue), fl_to);
2564 if (flags & SVR_FLUSH) {
2565 max_delta = fl_to;
2566 do_fl = 1;
2567 }
2568
2569 if (!context->file_read_thread_running && switch_queue_size(context->eh.video_queue) == 0) {
2570 return SWITCH_STATUS_FALSE;
2571 }
2572
2573 if (context->read_paused || context->seek_ts == -2) {
2574 int sanity = 10;
2575
2576 if (context->seek_ts == -2) { // just seeked, try read a new img
2577 again1:
2578 status = switch_queue_trypop(context->eh.video_queue, &pop);
2579 if (pop && status == SWITCH_STATUS_SUCCESS) {
2580 context->seek_ts = -1;
2581 switch_img_free(&context->last_img);
2582 context->last_img = (switch_image_t *)pop;
2583 switch_img_copy(context->last_img, &frame->img);
2584 context->vid_ready = 1;
2585 goto resize_check;
2586 }
2587
2588 if (context->last_img) { // repeat the last img
2589 switch_img_copy(context->last_img, &frame->img);
2590 context->vid_ready = 1;
2591 context->seek_ts = -1;
2592 goto resize_check;
2593 }
2594
2595 if ((flags & SVR_BLOCK) && sanity-- > 0) {
2596 switch_yield(10000);
2597 goto again1;
2598 }
2599
2600 return SWITCH_STATUS_BREAK;
2601 }
2602
2603 if (context->last_img) { // repeat the last img
2604 if ((flags & SVR_BLOCK)) switch_yield(100000);
2605 switch_img_copy(context->last_img, &frame->img);
2606 context->vid_ready = 1;
2607 goto resize_check;
2608 }
2609
2610 if ((flags & SVR_BLOCK)) {
2611 status = switch_queue_pop(context->eh.video_queue, &pop);
2612 } else {
2613 status = switch_queue_trypop(context->eh.video_queue, &pop);
2614 }
2615
2616 if (pop && status == SWITCH_STATUS_SUCCESS) {
2617 switch_img_free(&context->last_img);
2618 context->last_img = (switch_image_t *)pop;
2619 switch_img_copy(context->last_img, &frame->img);
2620 context->vid_ready = 1;
2621 goto resize_check;
2622 }
2623
2624 return SWITCH_STATUS_BREAK;
2625 }
2626
2627 #if 0
2628 if (context->last_img) {
2629 if (mst->next_pts && (switch_time_now() - mst->next_pts > max_delta)) {
2630 switch_img_free(&context->last_img); // too late
2631 } else if (mst->next_pts && (switch_time_now() - mst->next_pts > -10000)) {
2632 frame->img = context->last_img;
2633 context->last_img = NULL;
2634 context->vid_ready = 1;
2635 return SWITCH_STATUS_SUCCESS;
2636 }
2637
2638 if (!(flags & SVR_BLOCK) && !do_fl) {
2639 if (!mst->next_pts) {
2640 frame->img = context->last_img;
2641 context->last_img = NULL;
2642 context->vid_ready = 1;
2643 return SWITCH_STATUS_SUCCESS;
2644 }
2645
2646 return SWITCH_STATUS_BREAK;
2647 }
2648 }
2649 #endif
2650
2651 GCC_DIAG_OFF(deprecated-declarations)
2652 if (st->codec->time_base.num) {
2653 ticks = st->parser ? st->parser->repeat_pict + 1 : st->codec->ticks_per_frame;
2654 // mst->next_pts += ((int64_t)AV_TIME_BASE * st->codec->time_base.num * ticks) / st->codec->time_base.den;
2655 }
2656
2657 if (!context->video_start_time) {
2658 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "start: %" SWITCH_INT64_T_FMT " ticks: %d ticks_per_frame: %d st num:%d st den:%d codec num:%d codec den:%d start: %" SWITCH_TIME_T_FMT ", duration:%" SWITCH_INT64_T_FMT " nb_frames:%" SWITCH_INT64_T_FMT " q2d:%f\n",
2659 context->video_start_time, ticks, st->codec->ticks_per_frame, st->time_base.num, st->time_base.den, st->codec->time_base.num, st->codec->time_base.den,
2660 st->start_time, st->duration == AV_NOPTS_VALUE ? context->fc->duration / AV_TIME_BASE * 1000 : st->duration, st->nb_frames, av_q2d(st->time_base));
2661 }
2662 GCC_DIAG_ON(deprecated-declarations)
2663
2664 again:
2665
2666 if (context->last_img) {
2667 pop = (void *) context->last_img;
2668 context->last_img = NULL;
2669 status = SWITCH_STATUS_SUCCESS;
2670 } else {
2671 if ((flags & SVR_BLOCK)) {
2672 status = switch_queue_pop(context->eh.video_queue, &pop);
2673 } else {
2674 status = switch_queue_trypop(context->eh.video_queue, &pop);
2675 }
2676 }
2677
2678 if (pop && status == SWITCH_STATUS_SUCCESS) {
2679 switch_image_t *img = (switch_image_t *)pop;
2680 int64_t pts;
2681 int64_t now = switch_time_now();
2682
2683 pts = av_rescale_q(*((uint64_t *)img->user_priv), st->time_base, AV_TIME_BASE_Q);
2684 // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "pkt_pts: %lld pts: %lld queue size: %u\n", *((uint64_t *)img->user_priv), pts, switch_queue_size(context->eh.video_queue));
2685 handle->vpos = pts;
2686
2687 if (!context->video_start_time) {
2688 context->video_start_time = now - pts;
2689 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "set start time: %" SWITCH_INT64_T_FMT " now: %" SWITCH_INT64_T_FMT " pts: %" SWITCH_INT64_T_FMT "\n", context->video_start_time, now, pts);
2690 }
2691
2692 if (st->time_base.num == 0) {
2693 mst->next_pts = 0;
2694 } else {
2695 // int64_t last_pts = mst->next_pts;
2696 mst->next_pts = context->video_start_time + pts;
2697 // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "pts: %" SWITCH_INT64_T_FMT " last_pts: %" SWITCH_INT64_T_FMT " delta: %" SWITCH_INT64_T_FMT " frame_pts: %" SWITCH_INT64_T_FMT " nextpts: %" SWITCH_INT64_T_FMT ", num: %d, den:%d num:%d den:%d sleep: %" SWITCH_INT64_T_FMT "\n",
2698 // pts, last_pts, mst->next_pts - last_pts, *((uint64_t *)img->user_priv), mst->next_pts, st->time_base.num, st->time_base.den, st->codec->time_base.num, st->codec->time_base.den, mst->next_pts - now);
2699 }
2700
2701 if (pts == 0 || context->video_start_time == 0) mst->next_pts = 0;
2702
2703 if ((mst->next_pts && (now - mst->next_pts) > max_delta)) {
2704 //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "picture is too late, off: %" SWITCH_INT64_T_FMT " max delta: %" SWITCH_INT64_T_FMT " queue size:%u fps:%u/%0.2f\n", (int64_t)(now - mst->next_pts), max_delta, switch_queue_size(context->eh.video_queue), context->read_fps, handle->mm.fps);
2705 switch_img_free(&img);
2706 //max_delta = AV_TIME_BASE;
2707
2708 if (switch_queue_size(context->eh.video_queue) > 0) {
2709 // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "WTF again\n");
2710 goto again;
2711 } else if (!(flags & SVR_BLOCK) && !do_fl) {
2712 mst->next_pts = 0;
2713 context->video_start_time = 0;
2714 return SWITCH_STATUS_BREAK;
2715 }
2716 }
2717
2718 if ((flags & SVR_BLOCK)) {
2719 while (switch_micro_time_now() - mst->next_pts < -10000) {
2720 // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "yield, delta=%" SWITCH_INT64_T_FMT "\n", switch_micro_time_now() - mst->next_pts);
2721 switch_yield(1000);
2722 }
2723 frame->img = img;
2724 } else {
2725 if (switch_micro_time_now() - mst->next_pts > -10000) {
2726 frame->img = img;
2727 } else {
2728 switch_img_free(&context->last_img);
2729 context->last_img = img;
2730 return SWITCH_STATUS_BREAK;
2731 }
2732 }
2733
2734 } else {
2735 return SWITCH_STATUS_BREAK;
2736 }
2737
2738 resize_check:
2739
2740 if (frame->img) {
2741 if (context->handle->mm.scale_w && context->handle->mm.scale_h) {
2742 if (frame->img->d_w != context->handle->mm.scale_w || frame->img->d_h != context->handle->mm.scale_h) {
2743 switch_img_fit(&frame->img, context->handle->mm.scale_w, context->handle->mm.scale_h, SWITCH_FIT_SCALE);
2744 }
2745 }
2746 context->vid_ready = 1;
2747 }
2748
2749 if ((flags & SVR_BLOCK)) {
2750 if (!frame->img) context->closed = 1;
2751 return frame->img ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
2752 } else {
2753 return frame->img ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_BREAK;
2754 }
2755 }
2756 #endif
2757
2758 static switch_status_t av_file_write_video(switch_file_handle_t *handle, switch_frame_t *frame)
2759 {
2760 switch_status_t status = SWITCH_STATUS_SUCCESS;
2761 av_file_context_t *context = (av_file_context_t *)handle->private_info;
2762 switch_image_t *img = NULL;
2763
2764 if (!switch_test_flag(handle, SWITCH_FILE_FLAG_VIDEO)) {
2765 return SWITCH_STATUS_FALSE;
2766 }
2767
2768 if (!frame->img) {
2769 switch_goto_status(SWITCH_STATUS_FALSE, end);
2770 }
2771
2772 if (!context->has_video) {
2773 context->video_st.width = frame->img->d_w;
2774 context->video_st.height = frame->img->d_h;
2775 context->video_st.next_pts = switch_time_now() / 1000;
2776 if (add_stream(context, &context->video_st, context->fc, &context->video_codec, context->fc->oformat->video_codec, &handle->mm) == SWITCH_STATUS_SUCCESS &&
2777 open_video(context->fc, context->video_codec, &context->video_st) == SWITCH_STATUS_SUCCESS) {
2778
2779 char codec_str[256];
2780 int ret;
2781
2782 GCC_DIAG_OFF(deprecated-declarations)
2783 avcodec_string(codec_str, sizeof(codec_str), context->video_st.st->codec, 1);
2784 GCC_DIAG_ON(deprecated-declarations)
2785 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "use video codec implementation %s\n", codec_str);
2786 context->has_video = 1;
2787
2788 // av_dump_format(context->fc, 0, "/tmp/av.mp4", 1);
2789
2790 ret = avformat_write_header(context->fc, NULL);
2791 if (ret < 0) {
2792 char ebuf[255] = "";
2793 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error occurred when opening output file: %s\n", get_error_text(ret, ebuf, sizeof(ebuf)));
2794 switch_goto_status(SWITCH_STATUS_FALSE, end);
2795 }
2796
2797 } else {
2798 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error adding video stream\n");
2799 switch_goto_status(SWITCH_STATUS_FALSE, end);
2800 }
2801 }
2802
2803 if (!context->eh.video_thread) {
2804 switch_threadattr_t *thd_attr = NULL;
2805
2806 switch_mutex_init(&context->mutex, SWITCH_MUTEX_NESTED, handle->memory_pool);
2807 context->eh.mutex = context->mutex;
2808 context->eh.video_st = &context->video_st;
2809 context->eh.fc = context->fc;
2810 context->eh.mm = &handle->mm;
2811 switch_queue_create(&context->eh.video_queue, SWITCH_CORE_QUEUE_LEN, handle->memory_pool);
2812 switch_threadattr_create(&thd_attr, handle->memory_pool);
2813 //switch_threadattr_priority_set(thd_attr, SWITCH_PRI_REALTIME);
2814 switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
2815 switch_core_timer_init(&context->video_timer, "soft", 1, 1, context->pool);
2816 context->eh.video_timer = &context->video_timer;
2817 context->audio_st[0].frame->pts = 0;
2818 context->audio_st[0].next_pts = 0;
2819 switch_thread_create(&context->eh.video_thread, thd_attr, video_thread_run, context, handle->memory_pool);
2820 }
2821
2822 switch_img_copy(frame->img, &img);
2823 switch_queue_push(context->eh.video_queue, img);
2824
2825 if (!context->vid_ready) {
2826 switch_mutex_lock(context->mutex);
2827 switch_buffer_zero(context->audio_buffer);
2828 switch_mutex_unlock(context->mutex);
2829 context->vid_ready = 1;
2830 }
2831
2832 end:
2833 return status;
2834 }
2835
2836
2837 static switch_status_t av_file_set_string(switch_file_handle_t *handle, switch_audio_col_t col, const char *string)
2838 {
2839 av_file_context_t *context = (av_file_context_t *)handle->private_info;
2840
2841 if (context->fc) {
2842 const char *field = switch_parse_audio_col(col);
2843
2844 if (field) {
2845 av_dict_set(&context->fc->metadata, field, string, 0);
2846 return SWITCH_STATUS_SUCCESS;
2847 }
2848 }
2849
2850 return SWITCH_STATUS_FALSE;
2851 }
2852
2853 static switch_status_t av_file_get_string(switch_file_handle_t *handle, switch_audio_col_t col, const char **string)
2854 {
2855 av_file_context_t *context = (av_file_context_t *)handle->private_info;
2856
2857 if (context->fc) {
2858 AVDictionaryEntry *tag = NULL;
2859 const char *field = switch_parse_audio_col(col);
2860
2861 if (field && (tag = av_dict_get(context->fc->metadata, field, tag, 0))) {
2862 *string = tag->value;
2863 return SWITCH_STATUS_SUCCESS;
2864 }
2865 }
2866
2867 return SWITCH_STATUS_FALSE;
2868 }
2869
2870 static char *supported_formats[SWITCH_MAX_CODECS] = { 0 };
2871
2872 static const char modname[] = "mod_av";
2873
2874 static switch_status_t load_config(void)
2875 {
2876 char *cf = "avformat.conf";
2877 switch_xml_t cfg, xml, param, settings;
2878
2879 if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) {
2880 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "open of %s failed\n", cf);
2881 return SWITCH_STATUS_TERM;
2882 }
2883
2884 if ((settings = switch_xml_child(cfg, "settings"))) {
2885 for (param = switch_xml_child(settings, "param"); param; param = param->next) {
2886 char *var = (char *) switch_xml_attr_soft(param, "name");
2887 char *val = (char *) switch_xml_attr_soft(param, "value");
2888
2889 if (!strcasecmp(var, "colorspace")) {
2890 int value = atoi(val);
2891
2892 avformat_globals.colorspace = UINTVAL(value);
2893
2894 if (avformat_globals.colorspace > AVCOL_SPC_NB) {
2895 avformat_globals.colorspace = AVCOL_SPC_RGB;
2896 }
2897 }
2898 }
2899 }
2900
2901 switch_xml_free(xml);
2902 return SWITCH_STATUS_SUCCESS;
2903 }
2904
2905 SWITCH_MODULE_LOAD_FUNCTION(mod_avformat_load)
2906 {
2907 switch_file_interface_t *file_interface;
2908 int i = 0;
2909
2910 memset(&avformat_globals, 0, sizeof(struct avformat_globals));
2911 load_config();
2912
2913 supported_formats[i++] = "av";
2914 supported_formats[i++] = "rtmp";
2915 supported_formats[i++] = "rtmps";
2916 supported_formats[i++] = "rtsp";
2917 supported_formats[i++] = "mp4";
2918 supported_formats[i++] = "m4a";
2919 supported_formats[i++] = "mov";
2920 supported_formats[i++] = "mkv";
2921 supported_formats[i++] = "webm";
2922 //supported_formats[i++] = "wav";
2923
2924 file_interface = (switch_file_interface_t *)switch_loadable_module_create_interface(*module_interface, SWITCH_FILE_INTERFACE);
2925 file_interface->interface_name = modname;
2926 file_interface->extens = supported_formats;
2927 file_interface->file_open = av_file_open;
2928 file_interface->file_close = av_file_close;
2929 file_interface->file_truncate = av_file_truncate;
2930 file_interface->file_read = av_file_read;
2931 file_interface->file_write = av_file_write;
2932 file_interface->file_read_video = av_file_read_video;
2933 file_interface->file_write_video = av_file_write_video;
2934 file_interface->file_seek = av_file_seek;
2935 file_interface->file_set_string = av_file_set_string;
2936 file_interface->file_get_string = av_file_get_string;
2937 file_interface->file_command = av_file_command;
2938
2939 /* indicate that the module should continue to be loaded */
2940 return SWITCH_STATUS_SUCCESS;
2941 }
2942
2943 /* For Emacs:
2944 * Local Variables:
2945 * mode:c
2946 * indent-tabs-mode:t
2947 * tab-width:4
2948 * c-basic-offset:4
2949 * End:
2950 * For VIM:
2951 * vim:set softtabstop=4 shiftwidth=4 tabstop=4:
2952 */