2 * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
3 * Copyright (C) 2005-2015, Anthony Minessale II <anthm@freeswitch.org>
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/
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
17 * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
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.
26 * Seven Du <dujinfang@gmail.com>
27 * Anthony Minessale <anthm@freeswitch.org>
29 * mod_avformat -- File Formats with libav.org
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>
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)
54 #include <libswresample/swresample.h>
57 #define SLICE_SIZE (SWITCH_DEFAULT_VIDEO_SIZE + 100)
59 GCC_DIAG_ON(deprecated
-declarations
)
60 #define SCALE_FLAGS SWS_BICUBIC
61 #define DFT_RECORD_OFFSET 0
64 #ifndef AVUTIL_TIMESTAMP_H
65 #define AVUTIL_TIMESTAMP_H
67 #define AV_TS_MAX_STRING_SIZE 32
68 #define UINTVAL(v) (v > 0 ? v : 0);
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
78 struct avformat_globals
{
79 enum AVColorSpace colorspace
;
82 struct avformat_globals avformat_globals
= { 0 };
86 // a wrapper around a single output AVStream
87 typedef struct MediaStream
{
95 struct SwrContext
*resample_ctx
;
100 struct SwsContext
*sws_ctx
;
106 typedef struct record_helper_s
{
107 switch_mutex_t
*mutex
;
109 MediaStream
*video_st
;
110 switch_timer_t
*video_timer
;
112 switch_queue_t
*video_queue
;
113 switch_thread_t
*video_thread
;
116 switch_file_handle_t
*fh
;
117 switch_time_t record_timer_paused
;
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
;
137 MediaStream video_st
;
138 MediaStream audio_st
[2];
140 AVCodec
*audio_codec
;
141 AVCodec
*video_codec
;
142 enum AVColorSpace colorspace
;
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
;
154 switch_time_t last_vid_push
;
156 switch_bool_t read_paused
;
158 switch_file_handle_t
*handle
;
160 switch_size_t mux_buf_len
;
162 switch_time_t last_vid_write
;
165 switch_bool_t no_video_decode
;
166 switch_queue_t
*video_pkt_queue
;
167 switch_packetizer_t
*packetizer
;
168 AVPacket
*last_read_pkt
;
171 typedef struct av_file_context av_file_context_t
;
175 * Fill the provided buffer with a string containing a timestamp
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
182 static inline char *av_ts_make_string(char *buf
, int64_t ts
)
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
);
190 * Convenience macro, the return value should be used only directly in
191 * function arguments but never stand-alone.
193 #define av_ts2str(ts) av_ts_make_string((char[AV_TS_MAX_STRING_SIZE]){0}, ts)
196 * Fill the provided buffer with a string containing a timestamp time
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
204 static inline char *av_ts_make_time_string(char *buf
, int64_t ts
, AVRational
*tb
)
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
);
212 * Convenience macro, the return value should be used only directly in
213 * function arguments but never stand-alone.
215 #define av_ts2timestr(ts, tb) av_ts_make_time_string((char[AV_TS_MAX_STRING_SIZE]){0}, ts, tb)
217 #endif /* AVUTIL_TIMESTAMP_H */
220 static switch_status_t
av_file_close(switch_file_handle_t
*handle
);
221 SWITCH_MODULE_LOAD_FUNCTION(mod_avformat_load
);
223 static char *const get_error_text(const int error
, char *error_buffer
, switch_size_t error_buflen
)
225 av_strerror(error
, error_buffer
, error_buflen
);
229 static void av_unused
fill_avframe(AVFrame
*pict
, switch_image_t
*img
)
232 uint8_t *y
= img
->planes
[0];
233 uint8_t *u
= img
->planes
[1];
234 uint8_t *v
= img
->planes
[2];
237 for (i
= 0; i
< pict
->height
; i
++) {
238 memcpy(&pict
->data
[0][i
* pict
->linesize
[0]], y
+ i
* img
->stride
[0], pict
->width
);
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);
248 static void av_unused
avframe2img(AVFrame
*pict
, switch_image_t
*img
)
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
) {
257 linesize
[0] = pict
->linesize
[0];
258 linesize
[1] = pict
->linesize
[1];
259 linesize
[2] = pict
->linesize
[2] + pict
->linesize
[0];
261 switch_I420_copy2(pict
->data
, linesize
, img
->planes
, img
->stride
, img
->d_w
, img
->d_h
);
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];
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
],
277 for (j
= 0; j
< img
->d_h
; j
++) {
278 for (i
= 0; i
< img
->d_w
; i
++) {
282 color
= (switch_rgb_color_t
*)(img
->planes
[SWITCH_PLANE_PACKED
] + img
->stride
[SWITCH_PLANE_PACKED
] * j
);
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
],
290 switch_ABGRToARGB(pict
->data
[0], pict
->linesize
[0],
291 img
->planes
[SWITCH_PLANE_PACKED
], img
->stride
[SWITCH_PLANE_PACKED
],
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
);
300 switch_ARGBToARGB(pict
->data
[0], pict
->linesize
[0],
301 img
->planes
[SWITCH_PLANE_PACKED
], img
->stride
[SWITCH_PLANE_PACKED
],
308 static void av_unused
avframe2fd(AVFrame
*pict
, int fd
)
311 uint8_t *y
= pict
->data
[0];
312 uint8_t *u
= pict
->data
[1];
313 uint8_t *v
= pict
->data
[2];
316 for (i
= 0; i
< pict
->height
; i
++) {
317 write(fd
, y
+ i
* pict
->linesize
[0], pict
->width
);
321 for(i
= 0; i
< pict
->height
/ 2; i
++) {
322 write(fd
, u
+ i
* pict
->linesize
[1], pict
->width
/ 2);
325 for(i
= 0; i
< pict
->height
/ 2; i
++) {
326 write(fd
, v
+ i
* pict
->linesize
[2], pict
->width
/ 2);
330 static void log_packet(const AVFormatContext
*fmt_ctx
, const AVPacket
*pkt
)
332 if (mod_av_globals
.debug
< 2) return;
335 AVRational
*time_base
= &fmt_ctx
->streams
[pkt
->stream_index
]->time_base
;
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
),
345 static int interrupt_cb(void *cp
)
347 av_file_context_t
*context
= (av_file_context_t
*) cp
;
349 if (context
->closed
) {
357 static int mod_avformat_alloc_output_context2(AVFormatContext
**avctx
, AVOutputFormat
*oformat
,
358 const char *format
, const char *filename
, av_file_context_t
*context
)
360 AVFormatContext
*s
= avformat_alloc_context();
363 s
->interrupt_callback
.callback
= interrupt_cb
;
364 s
->interrupt_callback
.opaque
= context
;
372 oformat
= av_guess_format(format
, NULL
, NULL
);
374 av_log(s
, AV_LOG_ERROR
, "Requested output format '%s' is not a suitable output format\n", format
);
375 ret
= AVERROR(EINVAL
);
379 oformat
= av_guess_format(NULL
, filename
, NULL
);
381 ret
= AVERROR(EINVAL
);
382 av_log(s
, AV_LOG_ERROR
, "Unable to find a suitable output format for '%s'\n",
389 s
->oformat
= oformat
;
390 if (s
->oformat
->priv_data_size
> 0) {
391 s
->priv_data
= av_mallocz(s
->oformat
->priv_data_size
);
394 if (s
->oformat
->priv_class
) {
395 *(const AVClass
**)s
->priv_data
= s
->oformat
->priv_class
;
396 av_opt_set_defaults(s
->priv_data
);
402 #if (LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58,7,100))
403 av_strlcpy(s
->filename
, filename
, sizeof(s
->filename
));
405 s
->url
= av_strdup(filename
);
406 switch_assert(s
->url
);
413 av_log(s
, AV_LOG_ERROR
, "Out of memory\n");
414 ret
= AVERROR(ENOMEM
);
416 avformat_free_context(s
);
420 static int write_frame(AVFormatContext
*fmt_ctx
, const AVRational
*time_base
, AVStream
*st
, AVPacket
*pkt
)
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
;
426 /* Write the compressed frame to the media file. */
427 log_packet(fmt_ctx
, pkt
);
428 return av_interleaved_write_frame(fmt_ctx
, pkt
);
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
)
435 switch_status_t status
= SWITCH_STATUS_FALSE
;
436 //int threads = switch_core_cpu_count();
437 int buffer_bytes
= 2097152; /* 2 mb */
440 //if (mm->try_hardware_encoder && codec_id == AV_CODEC_ID_H264) {
441 // *codec = avcodec_find_encoder_by_name("nvenc_h264");
445 /* find the encoder */
446 *codec
= avcodec_find_encoder(codec_id
);
450 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_ERROR
, "Could not find encoder\n");
454 mst
->st
= avformat_new_stream(fc
, *codec
);
456 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_ERROR
, "Could not allocate stream\n");
459 mst
->st
->id
= fc
->nb_streams
- 1;
460 GCC_DIAG_OFF(deprecated
-declarations
)
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);
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
);
479 c
->bit_rate
= mm
->ab
* 1024;
481 if (mm
->samplerate
) {
482 c
->sample_rate
= mst
->sample_rate
= mm
->samplerate
;
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;
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);
499 case AVMEDIA_TYPE_VIDEO
:
504 buffer_bytes
= mm
->vbuf
;
512 if (mm
->vw
&& mm
->vh
) {
514 mst
->height
= mm
->vh
;
517 c
->codec_id
= codec_id
;
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;
532 if (codec_id
== AV_CODEC_ID_H264
) {
533 c
->ticks_per_frame
= 2;
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
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);
546 switch (mm
->vprofile
) {
547 case SWITCH_VIDEO_PROFILE_BASELINE
:
548 av_opt_set(c
->priv_data
, "profile", "baseline", 0);
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);
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);
563 switch (mm
->vencspd
) {
564 case SWITCH_VIDEO_ENCODE_SPEED_SLOW
:
565 av_opt_set(c
->priv_data
, "preset", "veryslow", 0);
567 case SWITCH_VIDEO_ENCODE_SPEED_MEDIUM
:
568 av_opt_set(c
->priv_data
, "preset", "medium", 0);
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);
582 c
->rc_min_rate
= c
->bit_rate
;
583 c
->rc_max_rate
= c
->bit_rate
;
584 c
->rc_buffer_size
= c
->bit_rate
;
586 c
->gop_size
= fps
* 2;
587 c
->keyint_min
= fps
* 2;
589 c
->gop_size
= fps
* 10;
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);
600 c
->bit_rate
= mm
->vb
* 1024;
604 c
->gop_size
= mm
->keyint
;
607 if (codec_id
== AV_CODEC_ID_VP8
) {
608 av_set_options_string(c
, "quality=realtime", "=", ":");
611 // av_opt_set_int(c->priv_data, "slice-max-size", SWITCH_DEFAULT_VIDEO_SIZE, 0);
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
);
622 /* Some formats want stream headers to be separate. */
623 if (fc
->oformat
->flags
& AVFMT_GLOBALHEADER
) {
624 c
->flags
|= AV_CODEC_FLAG_GLOBAL_HEADER
;
629 return SWITCH_STATUS_SUCCESS
;
632 static AVFrame
*alloc_picture(enum AVPixelFormat pix_fmt
, int width
, int height
)
637 picture
= av_frame_alloc();
638 if (!picture
) return NULL
;
640 picture
->format
= pix_fmt
;
641 picture
->width
= width
;
642 picture
->height
= height
;
644 /* allocate the buffers for the frame data */
645 ret
= av_frame_get_buffer(picture
, 32);
647 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_ERROR
, "Could not allocate frame data.\n");
654 static switch_status_t
open_video(AVFormatContext
*fc
, AVCodec
*codec
, MediaStream
*mst
)
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();
663 // if (threads > 4) threads = 4;
664 // c->thread_count = threads;
667 ret
= avcodec_open2(c
, codec
, NULL
);
670 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_ERROR
, "Could not open video codec: %s\n", get_error_text(ret
, ebuf
, sizeof(ebuf
)));
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
);
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
682 return SWITCH_STATUS_SUCCESS
;
685 static switch_status_t
open_audio(AVFormatContext
*fc
, AVCodec
*codec
, MediaStream
*mst
)
689 switch_status_t status
= SWITCH_STATUS_FALSE
;
690 GCC_DIAG_OFF(deprecated
-declarations
)
692 GCC_DIAG_ON(deprecated
-declarations
)
693 ret
= avcodec_open2(c
, codec
, NULL
);
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
);
703 const AVCodecDescriptor
*desc
= avcodec_descriptor_get(c
->codec_id
);
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
)));
709 mst
->frame
= av_frame_alloc();
710 switch_assert(mst
->frame
);
712 mst
->frame
->sample_rate
= c
->sample_rate
;
713 mst
->frame
->format
= AV_SAMPLE_FMT_S16
;
714 mst
->frame
->channel_layout
= c
->channel_layout
;
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
;
720 mst
->frame
->nb_samples
= c
->frame_size
;
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
);
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
);
728 mst
->resample_ctx
= swr_alloc();
730 if (!mst
->resample_ctx
) {
731 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_ERROR
, "Could not allocate resampler context\n");
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);
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
;
753 ret
= av_frame_get_buffer(mst
->frame
, 0);
755 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_ERROR
, "Could not allocate audio frame.\n");
759 if (mst
->resample_ctx
) {
760 mst
->tmp_frame
= av_frame_alloc();
761 switch_assert(mst
->tmp_frame
);
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
;
768 ret
= av_frame_get_buffer(mst
->tmp_frame
, 0);
770 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_ERROR
, "Could not allocate audio frame.\n");
775 return SWITCH_STATUS_SUCCESS
;
778 static int flush_video_queue(switch_queue_t
*q
, int min
)
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
) {
792 return switch_queue_size(q
);
795 static void flush_video_pkt_queue(switch_queue_t
*q
)
799 while (switch_queue_trypop(q
, (void **)&pkt
) == SWITCH_STATUS_SUCCESS
) {
800 av_packet_unref(pkt
);
805 static void *SWITCH_THREAD_FUNC
video_thread_run(switch_thread_t
*thread
, void *obj
)
807 av_file_context_t
*context
= (av_file_context_t
*) obj
;
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;
815 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_NOTICE
, "video thread start\n");
816 switch_assert(context
->eh
.video_queue
);
818 AVPacket pkt
= { 0 };
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
);
831 if (switch_queue_pop(context
->eh
.video_queue
, &pop
) == SWITCH_STATUS_SUCCESS
) {
832 switch_img_free(&img
);
838 img
= (switch_image_t
*) pop
;
840 if (!d_w
) d_w
= img
->d_w
;
841 if (!d_h
) d_h
= img
->d_h
;
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
);
852 if ((skip_total_count
> 0 && !--skip_total_count
) || ++skip_count
>= skip_freq
) {
853 skip_total_count
= skip_total
;
861 size
= switch_queue_size(context
->eh
.video_queue
);
863 if (size
> 5 && !context
->eh
.finalize
) {
876 //switch_mutex_lock(context->eh.mutex);
878 context
->eh
.in_callback
= 1;
880 GCC_DIAG_OFF(deprecated
-declarations
)
881 av_init_packet(&pkt
);
882 GCC_DIAG_ON(deprecated
-declarations
)
884 if (context
->eh
.video_st
->frame
) {
885 ret
= av_frame_make_writable(context
->eh
.video_st
->frame
);
892 if (context
->eh
.record_timer_paused
) {
893 context
->eh
.last_ts
= 0;
897 fill_avframe(context
->eh
.video_st
->frame
, img
);
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
);
905 delta_sum
= delta_avg
;
910 } else if (context
->eh
.mm
->fps
) {
911 delta
= 1000 / context
->eh
.mm
->fps
;
916 context
->eh
.video_st
->frame
->pts
+= delta
* 90;
920 switch_core_timer_next(context
->eh
.video_timer
);
921 delta_tmp
= (context
->eh
.video_timer
->samplecount
* 90) - context
->eh
.last_ts
;
923 if (delta_tmp
!= 0) {
924 delta_sum
+= delta_tmp
;
927 if (delta_i
== UINT64_MAX
) {
929 delta_sum
= delta_avg
;
932 if ((delta_i
% 10) == 0) {
933 delta_avg
= (int)(double)(delta_sum
/ delta_i
);
936 context
->eh
.video_st
->frame
->pts
= context
->eh
.video_timer
->samplecount
* 90;
938 context
->eh
.video_st
->frame
->pts
= ((context
->eh
.video_timer
->samplecount
) * 90) + 1;
942 context
->eh
.last_ts
= context
->eh
.video_st
->frame
->pts
;
944 // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "pts: %" SWITCH_INT64_T_FMT "\n", context->eh.video_st->frame->pts);
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
)
952 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_ERROR
, "Encoding Error %d\n", ret
);
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
);
965 context
->eh
.in_callback
= 0;
966 //switch_mutex_unlock(context->eh.mutex);
972 AVPacket pkt
= { 0 };
976 GCC_DIAG_OFF(deprecated
-declarations
)
977 av_init_packet(&pkt
);
978 GCC_DIAG_ON(deprecated
-declarations
)
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
)
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
);
999 while(switch_queue_trypop(context
->eh
.video_queue
, &pop
) == SWITCH_STATUS_SUCCESS
) {
1001 img
= (switch_image_t
*) pop
;
1002 switch_img_free(&img
);
1005 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_NOTICE
, "video thread done\n");
1011 static void close_stream(AVFormatContext
*fc
, MediaStream
*mst
)
1013 if (!mst
->active
) return;
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
);
1020 GCC_DIAG_OFF(deprecated
-declarations
)
1021 if (mst
->st
&& mst
->st
->codec
) {
1022 avcodec_close(mst
->st
->codec
);
1024 GCC_DIAG_ON(deprecated
-declarations
)
1030 static int is_device(const AVClass
*avclass
)
1032 #if defined (AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT)
1033 if (!avclass
) return 0;
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
;
1048 void show_formats(switch_stream_handle_t
*stream
) {
1049 const AVInputFormat
*ifmt
= NULL
;
1050 const AVOutputFormat
*ofmt
= NULL
;
1051 const char *last_name
;
1054 stream
->write_function(stream
, "============= File Formats ==============================:\n"
1055 " D. = Demuxing supported\n"
1056 " .M = Muxing supported\n"
1057 "----------------------\n");
1065 const char *name
= NULL
;
1066 const char *long_name
= NULL
;
1068 #if (LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58,9,100))
1069 while ((ofmt
= av_oformat_next(ofmt
))) {
1073 while ((ofmt
= av_muxer_iterate(&i
))) {
1076 is_dev
= is_device(ofmt
->priv_class
);
1078 if ((name
== NULL
|| strcmp(ofmt
->name
, name
) < 0) &&
1079 strcmp(ofmt
->name
, last_name
) > 0) {
1081 long_name
= ofmt
->long_name
;
1086 #if (LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58,9,100))
1087 while ((ifmt
= av_iformat_next(ifmt
))) {
1090 while ((ifmt
= av_demuxer_iterate(&i
))) {
1092 is_dev
= is_device(ifmt
->priv_class
);
1094 if ((name
== NULL
|| strcmp(ifmt
->name
, name
) < 0) &&
1095 strcmp(ifmt
->name
, last_name
) > 0) {
1097 long_name
= ifmt
->long_name
;
1101 if (name
&& strcmp(ifmt
->name
, name
) == 0) decode
= 1;
1104 if (name
== NULL
) break;
1108 stream
->write_function(stream
, "%s%s%s %-15s %s\n",
1112 name
, long_name
? long_name
:" ");
1117 static void mod_avformat_destroy_output_context(av_file_context_t
*context
)
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]);
1124 if (context
->audio_st
[0].resample_ctx
) {
1125 swr_free(&context
->audio_st
[0].resample_ctx
);
1128 if (context
->audio_st
[1].resample_ctx
) {
1129 swr_free(&context
->audio_st
[1].resample_ctx
);
1132 avformat_close_input(&context
->fc
);
1135 context
->audio_st
[0].st
= NULL
;
1136 context
->audio_st
[1].st
= NULL
;
1137 context
->video_st
.st
= NULL
;
1141 static switch_status_t
open_input_file(av_file_context_t
*context
, switch_file_handle_t
*handle
, const char *filename
)
1143 AVCodec
*audio_codec
= NULL
;
1144 AVCodec
*video_codec
= NULL
;
1145 AVDictionary
*opts
= NULL
;
1148 switch_status_t status
= SWITCH_STATUS_SUCCESS
;
1150 // av_dict_set(&opts, "c:v", "libvpx", 0);
1152 /** Open the input file to read from it. */
1155 context
->fc
= avformat_alloc_context();
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
);
1163 context
->fc
->interrupt_callback
.callback
= interrupt_cb
;
1164 context
->fc
->interrupt_callback
.opaque
= context
;
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
);
1171 switch_goto_status(SWITCH_STATUS_FALSE
, err
);
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 ");
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
);
1185 if (opts
) av_dict_free(&opts
);
1187 av_dump_format(context
->fc
, 0, filename
, 0);
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
);
1203 if (context
->fc
->bit_rate
) {
1204 handle
->mm
.source_kps
= context
->fc
->bit_rate
/ 1024;
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
));
1210 handle
->mm
.source_fps
= 25;
1213 context
->read_fps
= (int)handle
->mm
.source_fps
;
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;
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;
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;
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
);
1241 context
->has_audio
= 0;
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;
1249 GCC_DIAG_ON(deprecated
-declarations
)
1251 context
->video_st
.active
= 1;
1253 // printf("has audio:%d has_video:%d\n", context->has_audio, context->has_video);
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
);
1260 if (context
->has_audio
) {
1261 GCC_DIAG_OFF(deprecated
-declarations
)
1262 AVCodecContext
*c
[2] = { NULL
};
1264 c
[0] = context
->audio_st
[0].st
->codec
;
1266 if (context
->audio_st
[1].st
&& context
->audio_st
[1].st
->codec
) {
1267 c
[1] = context
->audio_st
[1].st
->codec
;
1269 GCC_DIAG_ON(deprecated
-declarations
)
1271 context
->audio_st
[0].frame
= av_frame_alloc();
1272 switch_assert(context
->audio_st
[0].frame
);
1274 context
->audio_st
[0].active
= 1;
1277 context
->audio_st
[1].frame
= av_frame_alloc();
1278 switch_assert(context
->audio_st
[1].frame
);
1282 context
->audio_st
[0].channels
= 1;
1283 context
->audio_st
[1].channels
= 1;
1285 handle
->channels
= c
[0]->channels
> 2 ? 2 : c
[0]->channels
;
1286 context
->audio_st
[0].channels
= handle
->channels
;
1289 context
->audio_st
[0].sample_rate
= handle
->samplerate
;
1290 context
->audio_st
[1].sample_rate
= handle
->samplerate
;
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
)
1296 for (x
= 0; x
< context
->has_audio
&& x
< 2 && c
[x
]; x
++) {
1297 struct SwrContext
*resample_ctx
= swr_alloc();
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);
1312 if ((ret
= swr_init(resample_ctx
)) < 0) {
1314 av_strerror(ret
, errbuf
, 1024);
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
);
1321 context
->audio_st
[x
].resample_ctx
= resample_ctx
;
1327 if (!context
->has_video
) {
1328 switch_clear_flag(handle
, SWITCH_FILE_FLAG_VIDEO
);
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
;
1339 context
->handle
->mm
.fmt
= SWITCH_IMG_FMT_I420
;
1342 GCC_DIAG_ON(deprecated
-declarations
)
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");
1352 int nb_streams
= context
->fc
->nb_streams
;
1354 if (nb_streams
> 2) nb_streams
= 2;
1356 if (context
->has_video
) close_stream(context
->fc
, &context
->video_st
);
1358 for (i
= 0; i
< nb_streams
; i
++) {
1359 close_stream(context
->fc
, &context
->audio_st
[i
]);
1362 avformat_free_context(context
->fc
);
1370 #define AUDIO_BUF_SEC 5
1372 static void *SWITCH_THREAD_FUNC
file_read_thread_run(switch_thread_t
*thread
, void *obj
)
1374 av_file_context_t
*context
= (av_file_context_t
*) obj
;
1375 AVPacket pkt
= { 0 };
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
);
1387 while (context
->file_read_thread_running
&& !context
->closed
) {
1390 if (context
->seek_ts
>= 0) {
1393 switch_mutex_lock(context
->mutex
);
1394 switch_buffer_zero(context
->audio_buffer
);
1395 switch_mutex_unlock(context
->mutex
);
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;
1404 if (context
->has_video
) {
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
)
1413 while(switch_queue_trypop(context
->eh
.video_queue
, &pop
) == SWITCH_STATUS_SUCCESS
) {
1414 switch_image_t
*img
;
1416 img
= (switch_image_t
*) pop
;
1417 switch_img_free(&img
);
1422 if (context
->has_video
) {
1423 vid_frames
= switch_queue_size(context
->eh
.video_queue
);
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);
1434 GCC_DIAG_OFF(deprecated
-declarations
)
1435 av_init_packet(&pkt
);
1436 GCC_DIAG_ON(deprecated
-declarations
)
1440 if ((error
= av_read_frame(context
->fc
, &pkt
)) < 0) {
1441 if (error
== AVERROR_EOF
) {
1442 if (!context
->has_video
) break;
1448 pkt
.stream_index
= context
->video_st
.st
->index
;
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
)));
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
) {
1459 switch_image_t
*img
;
1461 if (context
->no_video_decode
) {
1465 switch_status_t status
;
1466 AVPacket
*new_pkt
= malloc(sizeof(AVPacket
));
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));
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);
1480 context
->vid_ready
= 1;
1481 if (status
!= SWITCH_STATUS_SUCCESS
) {
1482 av_packet_unref(new_pkt
);
1485 av_packet_unref(&pkt
);
1491 switch_buffer_zero(context
->audio_buffer
);
1496 vframe
= av_frame_alloc();
1497 switch_assert(vframe
);
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
);
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
);
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);
1517 // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "got_data=%d, error=%d\n", got_data, error);
1519 if (got_data
&& error
>= 0) {
1520 switch_img_fmt_t fmt
= SWITCH_IMG_FMT_I420
;
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
;
1531 if (!context
->video_st
.sws_ctx
) {
1532 context
->video_st
.sws_ctx
=
1533 sws_getContext(frm
->width
, frm
->height
,
1535 frm
->width
, frm
->height
,
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
);
1545 vframe
= av_frame_alloc();
1546 switch_assert(vframe
);
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);
1558 switch_assert(ret
>= 0);
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
);
1563 av_frame_free(&frm
);
1566 av_frame_free(&vframe
);
1571 context
->handle
->mm
.fmt
= fmt
;
1573 img
= switch_img_alloc(NULL
, fmt
, vframe
->width
, vframe
->height
, 1);
1576 int64_t *pts
= malloc(sizeof(int64_t));
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
;
1590 diff
= sleep
- (switch_time_now() - context
->last_vid_push
);
1592 if (diff
> 0 && diff
<= sleep
) {
1593 switch_core_timer_next(&context
->video_timer
);
1595 switch_core_timer_sync(&context
->video_timer
);
1599 context
->vid_ready
= 1;
1600 switch_queue_push(context
->eh
.video_queue
, img
);
1601 context
->last_vid_push
= switch_time_now();
1603 switch_img_free(&img
);
1608 av_frame_free(&vframe
);
1612 goto again
; // to get all delayed video frames in decoder
1618 } else if (context
->has_audio
&& pkt
.stream_index
== context
->audio_st
[0].st
->index
) {
1619 AVFrame in_frame
= { { 0 } };
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
);
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
);
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);
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
);
1639 uint8_t *data
[2] = { 0 };
1641 data
[0] = malloc(out_samples
* context
->audio_st
[0].channels
* 2);
1642 switch_assert(data
[0]);
1644 ret
= swr_convert(context
->audio_st
[0].resample_ctx
, data
, out_samples
,
1645 (const uint8_t **)in_frame
.data
, in_frame
.nb_samples
);
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));
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
);
1655 // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "decoded samples: %d\n", ret);
1659 // if (ret == 0 && avresample_get_delay(context->audio_st[0].resample_ctx)) {
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
);
1674 av_packet_unref(&pkt
);
1678 if (context
->has_video
) switch_queue_push(context
->eh
.video_queue
, NULL
);
1680 context
->file_read_thread_running
= 0;
1685 static switch_status_t
av_file_open(switch_file_handle_t
*handle
, const char *path
)
1687 av_file_context_t
*context
= NULL
;
1689 const char *tmp
= NULL
;
1690 AVOutputFormat
*fmt
;
1691 const char *format
= NULL
;
1694 int disable_write_buffer
= 0;
1695 switch_status_t status
= SWITCH_STATUS_SUCCESS
;
1697 switch_set_string(file
, path
);
1699 if (handle
->stream_name
) {
1700 disable_write_buffer
= 1;
1703 if (handle
->stream_name
&& (!strcasecmp(handle
->stream_name
, "rtmp") || !strcasecmp(handle
->stream_name
, "rtmps") || !strcasecmp(handle
->stream_name
, "youtube"))) {
1707 if ((ext
= strrchr((char *)path
, '.')) == 0) {
1711 if (!strcasecmp(handle
->stream_name
, "rtmps")) secure
= "s";
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
);
1717 switch_snprintf(file
, sizeof(file
), "rtmp%s://%s", secure
, path
);
1720 } else if (handle
->stream_name
&& !strcasecmp(handle
->stream_name
, "rtsp")) {
1722 if ((ext
= strrchr((char *)path
, '.')) == 0) {
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
;
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
);
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
;
1748 if (handle
->params
) {
1749 if ((tmp
= switch_event_get_header(handle
->params
, "av_video_offset"))) {
1750 context
->offset
= atoi(tmp
);
1752 if ((tmp
= switch_event_get_header(handle
->params
, "video_time_audio"))) {
1753 if (switch_false(tmp
)) {
1754 context
->audio_timer
= 0;
1757 if ((tmp
= switch_event_get_header(handle
->params
, "colorspace"))) {
1758 int value
= atoi(tmp
);
1759 enum AVColorSpace colorspace
= UINTVAL(value
);
1761 if (colorspace
<= AVCOL_SPC_NB
) {
1762 context
->colorspace
= colorspace
;
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);
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
);
1776 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_DEBUG
, "sample rate: %d, channels: %d\n", handle
->samplerate
, handle
->channels
);
1778 if (switch_test_flag(handle
, SWITCH_FILE_FLAG_READ
)) {
1779 if (open_input_file(context
, handle
, path
) != SWITCH_STATUS_SUCCESS
) {
1781 switch_goto_status(SWITCH_STATUS_GENERR
, end
);
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
);
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
);
1798 switch_threadattr_t
*thd_attr
= NULL
;
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
);
1805 return SWITCH_STATUS_SUCCESS
;
1808 mod_avformat_alloc_output_context2(&context
->fc
, NULL
, format
, (char *)file
, context
);
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
);
1815 fmt
= context
->fc
->oformat
;
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
);
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;
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;
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
);
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
);
1851 /* open the output file, if needed */
1852 if (!(fmt
->flags
& AVFMT_NOFILE
)) {
1853 ret
= avio_open(&context
->fc
->pb
, file
, AVIO_FLAG_WRITE
);
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
);
1860 avformat_network_init();
1863 if (handle
->mm
.samplerate
) {
1864 handle
->samplerate
= handle
->mm
.samplerate
;
1866 handle
->mm
.samplerate
= handle
->samplerate
;
1869 if (!handle
->mm
.ab
) {
1870 handle
->mm
.ab
= 128;
1873 if (!handle
->mm
.vb
) {
1874 handle
->mm
.vb
= switch_calc_bitrate(handle
->mm
.vw
, handle
->mm
.vh
, 1, handle
->mm
.fps
);
1877 if (switch_test_flag(handle
, SWITCH_FILE_FLAG_VIDEO
) && fmt
->video_codec
!= AV_CODEC_ID_NONE
) {
1878 const AVCodecDescriptor
*desc
;
1880 if ((handle
->stream_name
&& (!strcasecmp(handle
->stream_name
, "rtmp") || !strcasecmp(handle
->stream_name
, "rtmps") || !strcasecmp(handle
->stream_name
, "youtube")))) {
1882 if (fmt
->video_codec
!= AV_CODEC_ID_H264
) {
1883 fmt
->video_codec
= AV_CODEC_ID_H264
; // force H264
1886 fmt
->audio_codec
= AV_CODEC_ID_AAC
;
1887 handle
->samplerate
= 44100;
1888 handle
->mm
.samplerate
= 44100;
1889 handle
->mm
.ab
= 128;
1891 handle
->mm
.vencspd
= SWITCH_VIDEO_ENCODE_SPEED_FAST
;
1892 handle
->mm
.vprofile
= SWITCH_VIDEO_PROFILE_BASELINE
;
1894 if (!handle
->mm
.vb
&& handle
->mm
.vw
&& handle
->mm
.vh
) {
1895 switch(handle
->mm
.vh
) {
1897 handle
->mm
.vb
= 400;
1900 handle
->mm
.vb
= 750;
1903 handle
->mm
.vb
= 1000;
1906 handle
->mm
.vb
= 2500;
1909 handle
->mm
.vb
= 4500;
1912 handle
->mm
.vb
= switch_calc_bitrate(handle
->mm
.vw
, handle
->mm
.vh
, 1, handle
->mm
.fps
);
1917 if (handle
->mm
.fps
> 0.0f
) {
1918 handle
->mm
.keyint
= (int) 2.0f
* handle
->mm
.fps
;
1922 desc
= avcodec_descriptor_get(fmt
->video_codec
);
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
);
1927 if (fmt
->audio_codec
!= AV_CODEC_ID_NONE
) {
1928 const char *issplit
= 0;
1930 context
->audio_st
[0].channels
= handle
->channels
;
1931 context
->audio_st
[1].sample_rate
= handle
->samplerate
;
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");
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
);
1945 context
->audio_st
[0].r
= 1;
1947 context
->audio_st
[1].r
= 1;
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
);
1955 if (open_audio(context
->fc
, context
->audio_codec
, &context
->audio_st
[0]) != SWITCH_STATUS_SUCCESS
) {
1956 switch_goto_status(SWITCH_STATUS_GENERR
, end
);
1959 context
->has_audio
= 1;
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
);
1966 context
->has_audio
++;
1970 av_dump_format(context
->fc
, 0, file
, 1);
1973 handle
->sections
= 0;
1974 handle
->seekable
= 0;
1978 if (disable_write_buffer
) {
1979 handle
->pre_buffer_datalen
= 0;
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" : "");
1985 return SWITCH_STATUS_SUCCESS
;
1994 mod_avformat_destroy_output_context(context
);
1997 if (context
->video_timer
.interval
) {
1998 switch_core_timer_destroy(&context
->video_timer
);
2001 if (context
->audio_buffer
) {
2002 switch_buffer_destroy(&context
->audio_buffer
);
2008 static switch_status_t
av_file_truncate(switch_file_handle_t
*handle
, int64_t offset
)
2010 return SWITCH_STATUS_FALSE
;
2014 static switch_status_t
av_file_write(switch_file_handle_t
*handle
, void *data
, size_t *len
)
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;
2024 int sample_start
= 0;
2026 if (!switch_test_flag(handle
, SWITCH_FILE_FLAG_WRITE
)) {
2027 return SWITCH_STATUS_FALSE
;
2030 if (!context
->vid_ready
) {
2031 if (switch_test_flag(handle
, SWITCH_FILE_FLAG_VIDEO
)) {
2032 switch_buffer_zero(context
->audio_buffer
);
2034 } else if (!context
->aud_ready
) { // audio only recording
2035 int ret
= avformat_write_header(context
->fc
, NULL
);
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
;
2041 context
->aud_ready
= 1;
2046 datalen
= *len
* 2 * handle
->channels
;
2048 if (context
->offset
) {
2049 switch_size_t samples
= *len
;
2050 int fps
= handle
->samplerate
/ samples
;
2051 int lead_frames
= (context
->offset
* fps
) / 1000;
2053 for (int x
= 0; x
< lead_frames
; x
++) {
2054 switch_buffer_zero_fill(context
->audio_buffer
, datalen
);
2056 context
->offset
= 0;
2059 switch_buffer_write(context
->audio_buffer
, data
, datalen
);
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
)
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);
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
);
2079 if (context
->video_timer
.interval
) {
2081 switch_core_timer_sync(&context
->video_timer
);
2083 delta
= context
->video_timer
.samplecount
- context
->last_vid_write
;
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
);
2090 sample_start
= new_pts
;
2093 context
->last_vid_write
= context
->video_timer
.samplecount
;
2100 for (j
= 0; j
< 2; j
++) {
2101 if (context
->audio_st
[j
].active
) {
2102 context
->audio_st
[j
].next_pts
= sample_start
;
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
;
2113 GCC_DIAG_OFF(deprecated
-declarations
)
2114 av_init_packet(&pkt
[0]);
2115 av_init_packet(&pkt
[1]);
2116 GCC_DIAG_ON(deprecated
-declarations
)
2118 if (context
->audio_st
[1].active
) {
2119 switch_size_t len
= 0;
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);
2128 audio_stream_count
= 2;
2129 len
= switch_buffer_read(context
->audio_buffer
, (uint8_t *)context
->mux_buf
, bytes
);
2131 if (context
->audio_st
[0].r
) {
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
++];
2141 switch_buffer_read(context
->audio_buffer
, context
->audio_st
[0].frame
->data
[0], bytes
);
2144 for (j
= 0; j
< audio_stream_count
; j
++) {
2146 av_frame_make_writable(context
->audio_st
[j
].frame
);
2147 use_frame
= context
->audio_st
[j
].frame
;
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
);
2152 av_frame_make_writable(context
->audio_st
[j
].tmp_frame
);
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
);
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
)));
2166 use_frame
= context
->audio_st
[j
].tmp_frame
;
2169 use_frame
->pts
= context
->audio_st
[j
].next_pts
;
2171 // context->audio_st[j].next_pts = use_frame->pts + use_frame->nb_samples;
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
)
2177 context
->audio_st
[j
].next_pts
+= use_frame
->nb_samples
;
2181 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_WARNING
, "Error encoding audio frame: %d\n", ret
);
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
);
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
)));
2199 //switch_goto_status(SWITCH_STATUS_FALSE, end);
2204 if (context
->errs
> 1000) {
2205 status
= SWITCH_STATUS_FALSE
;
2217 static switch_status_t
av_file_command(switch_file_handle_t
*handle
, switch_file_command_t command
)
2219 av_file_context_t
*context
= (av_file_context_t
*)handle
->private_info
;
2220 uint32_t offset
= 0;
2223 case SCFC_FLUSH_AUDIO
:
2224 switch_mutex_lock(context
->mutex
);
2225 switch_buffer_zero(context
->audio_buffer
);
2226 switch_mutex_unlock(context
->mutex
);
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;
2234 context
->read_paused
= SWITCH_TRUE
;
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
);
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;
2256 return SWITCH_STATUS_SUCCESS
;
2259 static switch_status_t
av_file_close(switch_file_handle_t
*handle
)
2261 av_file_context_t
*context
= (av_file_context_t
*)handle
->private_info
;
2262 switch_status_t status
;
2264 context
->closed
= 1;
2265 context
->eh
.finalize
= 1;
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
);
2273 switch_queue_push(context
->eh
.video_queue
, NULL
);
2277 if (context
->eh
.video_thread
) {
2278 switch_thread_join(&status
, context
->eh
.video_thread
);
2281 if (switch_test_flag(handle
, SWITCH_FILE_FLAG_WRITE
)) {
2282 av_file_write(handle
, NULL
, NULL
);
2285 if (context
->file_read_thread_running
) {
2286 context
->file_read_thread_running
= 0;
2289 if (context
->video_pkt_queue
) {
2290 flush_video_pkt_queue(context
->video_pkt_queue
);
2291 switch_queue_term(context
->video_pkt_queue
);
2294 if (context
->packetizer
) {
2295 switch_packetizer_close(&context
->packetizer
);
2298 if (context
->file_read_thread
) {
2299 switch_thread_join(&status
, context
->file_read_thread
);
2300 context
->file_read_thread
= NULL
;
2303 if (context
->eh
.video_queue
) {
2304 flush_video_queue(context
->eh
.video_queue
, 0);
2308 if ((context
->aud_ready
|| context
->has_video
) && switch_test_flag(handle
, SWITCH_FILE_FLAG_WRITE
)) {
2309 av_write_trailer(context
->fc
);
2312 mod_avformat_destroy_output_context(context
);
2315 if (context
->video_timer
.interval
) {
2316 switch_core_timer_destroy(&context
->video_timer
);
2319 switch_img_free(&context
->last_img
);
2321 switch_buffer_destroy(&context
->audio_buffer
);
2323 switch_safe_free(context
->mux_buf
);
2325 return SWITCH_STATUS_SUCCESS
;
2328 static switch_status_t
av_file_seek(switch_file_handle_t
*handle
, unsigned int *cur_sample
, int64_t samples
, int whence
)
2330 av_file_context_t
*context
= (av_file_context_t
*)handle
->private_info
;
2332 if (whence
== SEEK_SET
) {
2333 handle
->pos
= handle
->offset_pos
= samples
;
2336 context
->seek_ts
= samples
/ handle
->native_rate
* AV_TIME_BASE
;
2337 *cur_sample
= context
->seek_ts
;
2339 context
->closed
= 0;
2341 if (!context
->file_read_thread_running
) {
2342 switch_threadattr_t
*thd_attr
= NULL
;
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
;
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
);
2355 return SWITCH_STATUS_FALSE
;
2358 static switch_status_t
av_file_read(switch_file_handle_t
*handle
, void *data
, size_t *len
)
2360 av_file_context_t
*context
= (av_file_context_t
*)handle
->private_info
;
2362 size_t need
= *len
* 2 * context
->audio_st
[0].channels
;
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
;
2369 switch_mutex_lock(context
->mutex
);
2371 while (!context
->file_read_thread_started
) {
2372 switch_thread_cond_wait(context
->cond
, context
->mutex
);
2374 switch_mutex_unlock(context
->mutex
);
2376 if (context
->closed
|| (!context
->file_read_thread_running
&& switch_buffer_inuse(context
->audio_buffer
) == 0)) {
2378 return SWITCH_STATUS_FALSE
;
2381 while (context
->has_video
&& !context
->vid_ready
&& !context
->closed
) {
2385 switch_mutex_lock(context
->mutex
);
2386 size
= switch_buffer_read(context
->audio_buffer
, data
, need
);
2387 switch_mutex_unlock(context
->mutex
);
2390 size_t blank
= (handle
->samplerate
/ 20) * 2 * handle
->real_channels
;
2395 memset(data
, 0, need
);
2396 *len
= need
/ 2 / handle
->real_channels
;
2398 *len
= size
/ context
->audio_st
[0].channels
/ 2;
2401 handle
->pos
+= *len
;
2402 handle
->sample_count
+= *len
;
2404 return *len
== 0 ? SWITCH_STATUS_FALSE
: SWITCH_STATUS_SUCCESS
;
2409 static switch_status_t
av_file_read_video(switch_file_handle_t
*handle
, switch_frame_t
*frame
, switch_video_read_flag_t flags
)
2412 av_file_context_t
*context
= (av_file_context_t
*)handle
->private_info
;
2413 switch_status_t status
;
2416 if (!context
->has_video
|| context
->closed
) return SWITCH_STATUS_FALSE
;
2417 if ((flags
& SVR_CHECK
)) {
2418 return SWITCH_STATUS_BREAK
;
2421 if ((flags
& SVR_FLUSH
)) {
2422 flush_video_queue(context
->eh
.video_queue
, 1);
2425 if ((flags
& SVR_BLOCK
)) {
2426 status
= switch_queue_pop(context
->eh
.video_queue
, &pop
);
2428 status
= switch_queue_trypop(context
->eh
.video_queue
, &pop
);
2431 if (status
== SWITCH_STATUS_SUCCESS
) {
2433 return SWITCH_STATUS_FALSE
;
2436 context
->vid_ready
= 1;
2438 frame
->img
= (switch_image_t
*) pop
;
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
);
2446 context
->vid_ready
= 1;
2449 return SWITCH_STATUS_SUCCESS
;
2452 return (flags
& SVR_FLUSH
) ? SWITCH_STATUS_BREAK
: status
;
2456 static switch_status_t
no_video_decode_packets(switch_file_handle_t
*handle
, switch_frame_t
*frame
, switch_video_read_flag_t flags
)
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;
2463 // int64_t max_delta = 1 * AV_TIME_BASE; // 1 second
2464 switch_status_t status
= SWITCH_STATUS_SUCCESS
;
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));
2473 context
->packetizer
= switch_packetizer_create(SPT_H264_SIZED_BITSTREAM
, SLICE_SIZE
);
2474 if (!context
->packetizer
) return SWITCH_STATUS_FALSE
;
2476 switch_packetizer_feed_extradata(context
->packetizer
, st
->codecpar
->extradata
, st
->codecpar
->extradata_size
);
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
;
2489 status
= switch_queue_trypop(context
->video_pkt_queue
, (void **)&pkt
);
2491 if (status
!= SWITCH_STATUS_SUCCESS
|| !pkt
) {
2493 return SWITCH_STATUS_BREAK
;
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);
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
;
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
);
2517 // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "zzZ... %" SWITCH_INT64_T_FMT "\n", sleep);
2518 if (sleep
> 1000000) {
2520 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_DEBUG
, "but zzZ... %" SWITCH_INT64_T_FMT
" at most\n", sleep
);
2522 switch_yield(sleep
);
2524 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_WARNING
, "video is late %" SWITCH_INT64_T_FMT
"\n", sleep
);
2532 static switch_status_t
av_file_read_video(switch_file_handle_t
*handle
, switch_frame_t
*frame
, switch_video_read_flag_t flags
)
2534 av_file_context_t
*context
= (av_file_context_t
*)handle
->private_info
;
2536 MediaStream
*mst
= &context
->video_st
;
2537 AVStream
*st
= mst
->st
;
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;
2543 int smaller_ts
= context
->read_fps
;
2545 if (!context
->has_video
) return SWITCH_STATUS_FALSE
;
2547 if ((flags
& SVR_CHECK
)) {
2548 return SWITCH_STATUS_BREAK
;
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);
2558 if (handle
->mm
.fps
> 0 && handle
->mm
.fps
< smaller_ts
) {
2559 smaller_ts
= handle
->mm
.fps
;
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
) {
2569 if (!context
->file_read_thread_running
&& switch_queue_size(context
->eh
.video_queue
) == 0) {
2570 return SWITCH_STATUS_FALSE
;
2573 if (context
->read_paused
|| context
->seek_ts
== -2) {
2576 if (context
->seek_ts
== -2) { // just seeked, try read a new img
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;
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;
2595 if ((flags
& SVR_BLOCK
) && sanity
-- > 0) {
2596 switch_yield(10000);
2600 return SWITCH_STATUS_BREAK
;
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;
2610 if ((flags
& SVR_BLOCK
)) {
2611 status
= switch_queue_pop(context
->eh
.video_queue
, &pop
);
2613 status
= switch_queue_trypop(context
->eh
.video_queue
, &pop
);
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;
2624 return SWITCH_STATUS_BREAK
;
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
;
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
;
2646 return SWITCH_STATUS_BREAK
;
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;
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
));
2662 GCC_DIAG_ON(deprecated
-declarations
)
2666 if (context
->last_img
) {
2667 pop
= (void *) context
->last_img
;
2668 context
->last_img
= NULL
;
2669 status
= SWITCH_STATUS_SUCCESS
;
2671 if ((flags
& SVR_BLOCK
)) {
2672 status
= switch_queue_pop(context
->eh
.video_queue
, &pop
);
2674 status
= switch_queue_trypop(context
->eh
.video_queue
, &pop
);
2678 if (pop
&& status
== SWITCH_STATUS_SUCCESS
) {
2679 switch_image_t
*img
= (switch_image_t
*)pop
;
2681 int64_t now
= switch_time_now();
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));
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
);
2692 if (st
->time_base
.num
== 0) {
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);
2701 if (pts
== 0 || context
->video_start_time
== 0) mst
->next_pts
= 0;
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;
2708 if (switch_queue_size(context
->eh
.video_queue
) > 0) {
2709 // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "WTF again\n");
2711 } else if (!(flags
& SVR_BLOCK
) && !do_fl
) {
2713 context
->video_start_time
= 0;
2714 return SWITCH_STATUS_BREAK
;
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);
2725 if (switch_micro_time_now() - mst
->next_pts
> -10000) {
2728 switch_img_free(&context
->last_img
);
2729 context
->last_img
= img
;
2730 return SWITCH_STATUS_BREAK
;
2735 return SWITCH_STATUS_BREAK
;
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
);
2746 context
->vid_ready
= 1;
2749 if ((flags
& SVR_BLOCK
)) {
2750 if (!frame
->img
) context
->closed
= 1;
2751 return frame
->img
? SWITCH_STATUS_SUCCESS
: SWITCH_STATUS_FALSE
;
2753 return frame
->img
? SWITCH_STATUS_SUCCESS
: SWITCH_STATUS_BREAK
;
2758 static switch_status_t
av_file_write_video(switch_file_handle_t
*handle
, switch_frame_t
*frame
)
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
;
2764 if (!switch_test_flag(handle
, SWITCH_FILE_FLAG_VIDEO
)) {
2765 return SWITCH_STATUS_FALSE
;
2769 switch_goto_status(SWITCH_STATUS_FALSE
, end
);
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
) {
2779 char codec_str
[256];
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;
2788 // av_dump_format(context->fc, 0, "/tmp/av.mp4", 1);
2790 ret
= avformat_write_header(context
->fc
, NULL
);
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
);
2798 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_ERROR
, "Error adding video stream\n");
2799 switch_goto_status(SWITCH_STATUS_FALSE
, end
);
2803 if (!context
->eh
.video_thread
) {
2804 switch_threadattr_t
*thd_attr
= NULL
;
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
);
2822 switch_img_copy(frame
->img
, &img
);
2823 switch_queue_push(context
->eh
.video_queue
, img
);
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;
2837 static switch_status_t
av_file_set_string(switch_file_handle_t
*handle
, switch_audio_col_t col
, const char *string
)
2839 av_file_context_t
*context
= (av_file_context_t
*)handle
->private_info
;
2842 const char *field
= switch_parse_audio_col(col
);
2845 av_dict_set(&context
->fc
->metadata
, field
, string
, 0);
2846 return SWITCH_STATUS_SUCCESS
;
2850 return SWITCH_STATUS_FALSE
;
2853 static switch_status_t
av_file_get_string(switch_file_handle_t
*handle
, switch_audio_col_t col
, const char **string
)
2855 av_file_context_t
*context
= (av_file_context_t
*)handle
->private_info
;
2858 AVDictionaryEntry
*tag
= NULL
;
2859 const char *field
= switch_parse_audio_col(col
);
2861 if (field
&& (tag
= av_dict_get(context
->fc
->metadata
, field
, tag
, 0))) {
2862 *string
= tag
->value
;
2863 return SWITCH_STATUS_SUCCESS
;
2867 return SWITCH_STATUS_FALSE
;
2870 static char *supported_formats
[SWITCH_MAX_CODECS
] = { 0 };
2872 static const char modname
[] = "mod_av";
2874 static switch_status_t
load_config(void)
2876 char *cf
= "avformat.conf";
2877 switch_xml_t cfg
, xml
, param
, settings
;
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
;
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");
2889 if (!strcasecmp(var
, "colorspace")) {
2890 int value
= atoi(val
);
2892 avformat_globals
.colorspace
= UINTVAL(value
);
2894 if (avformat_globals
.colorspace
> AVCOL_SPC_NB
) {
2895 avformat_globals
.colorspace
= AVCOL_SPC_RGB
;
2901 switch_xml_free(xml
);
2902 return SWITCH_STATUS_SUCCESS
;
2905 SWITCH_MODULE_LOAD_FUNCTION(mod_avformat_load
)
2907 switch_file_interface_t
*file_interface
;
2910 memset(&avformat_globals
, 0, sizeof(struct avformat_globals
));
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";
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
;
2939 /* indicate that the module should continue to be loaded */
2940 return SWITCH_STATUS_SUCCESS
;
2946 * indent-tabs-mode:t
2951 * vim:set softtabstop=4 shiftwidth=4 tabstop=4: