FreeSWITCH API Documentation  1.7.0
switch_core_codec.c
Go to the documentation of this file.
1 /*
2  * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
3  * Copyright (C) 2005-2014, 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  * Anthony Minessale II <anthm@freeswitch.org>
21  * Portions created by the Initial Developer are Copyright (C)
22  * the Initial Developer. All Rights Reserved.
23  *
24  * Contributor(s):
25  *
26  * Anthony Minessale II <anthm@freeswitch.org>
27  * Michael Jerris <mike@jerris.com>
28  * Paul D. Tinsley <pdt at jackhammer.org>
29  * Christopher M. Rienzo <chris@rienzo.com>
30  *
31  *
32  * switch_core_codec.c -- Main Core Library (codec functions)
33  *
34  */
35 
36 #include <switch.h>
38 
39 static uint32_t CODEC_ID = 1;
40 
42 {
43  return CODEC_ID++;
44 }
45 
47 {
48  switch_mutex_t *mutex = NULL;
49 
50  switch_mutex_lock(session->codec_read_mutex);
51  if (session->read_codec) mutex = session->read_codec->mutex;
52  if (mutex) switch_mutex_lock(mutex);
53  session->real_read_codec = session->read_codec = NULL;
54  session->raw_read_frame.codec = session->read_codec;
55  session->raw_write_frame.codec = session->read_codec;
56  session->enc_read_frame.codec = session->read_codec;
57  session->enc_write_frame.codec = session->read_codec;
58  if (mutex) switch_mutex_unlock(mutex);
59  switch_mutex_unlock(session->codec_read_mutex);
60 }
61 
63 {
64  switch_mutex_lock(session->codec_write_mutex);
65 }
66 
68 {
69  switch_mutex_unlock(session->codec_write_mutex);
70 }
71 
73 {
74  switch_mutex_lock(session->codec_read_mutex);
75 }
76 
78 {
79  switch_mutex_unlock(session->codec_read_mutex);
80 }
81 
83 {
84  switch_mutex_t *mutex = NULL;
85 
86  switch_mutex_lock(session->codec_write_mutex);
87  if (session->write_codec) mutex = session->write_codec->mutex;
88  if (mutex) switch_mutex_lock(mutex);
89  session->real_write_codec = session->write_codec = NULL;
90  if (mutex) switch_mutex_unlock(mutex);
91  switch_mutex_unlock(session->codec_write_mutex);
92 }
93 
95 {
96  switch_event_t *event;
98  char tmp[30];
100  int changed_read_codec = 0;
101 
102  switch_mutex_lock(session->codec_read_mutex);
103 
104  if (codec && (!codec->implementation || !switch_core_codec_ready(codec))) {
105  codec = NULL;
106  }
107 
108  if (codec) {
109  /* set real_read_codec and read_codec */
110  if (!session->real_read_codec) {
111  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Original read codec set to %s:%d\n",
112  switch_channel_get_name(session->channel), codec->implementation->iananame, codec->implementation->ianacode);
113  session->read_codec = session->real_read_codec = codec;
114  changed_read_codec = 1;
115  if (codec->implementation) {
116  session->read_impl = *codec->implementation;
117  session->real_read_impl = *codec->implementation;
118  } else {
119  memset(&session->read_impl, 0, sizeof(session->read_impl));
120  }
121  } else { /* replace real_read_codec */
122  switch_codec_t *cur_codec;
123  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Original read codec replaced with %s:%d\n",
124  switch_channel_get_name(session->channel), codec->implementation->iananame, codec->implementation->ianacode);
125  /* Set real_read_codec to front of the list of read_codecs */
126  cur_codec = session->read_codec;
127  while (cur_codec != NULL) {
128  if (cur_codec->next == session->real_read_codec) {
129  cur_codec->next = codec;
130  break;
131  }
132  cur_codec = cur_codec->next;
133  }
134  session->real_read_codec = codec;
135  /* set read_codec with real_read_codec if it no longer is ready */
136  if (!switch_core_codec_ready(session->read_codec)) {
137  session->read_codec = codec;
138  changed_read_codec = 1;
139  if (codec->implementation) {
140  session->read_impl = *codec->implementation;
141  session->real_read_impl = *codec->implementation;
142  } else {
143  memset(&session->read_impl, 0, sizeof(session->read_impl));
144  }
145  }
146  }
147 
148  /* force media bugs to copy the read codec from the next frame */
149  switch_thread_rwlock_wrlock(session->bug_rwlock);
150  if (switch_core_codec_ready(&session->bug_codec)) {
151  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Destroying BUG Codec %s:%d\n",
152  session->bug_codec.implementation->iananame, session->bug_codec.implementation->ianacode);
153  switch_core_codec_destroy(&session->bug_codec);
154  }
155  switch_thread_rwlock_unlock(session->bug_rwlock);
156  } else {
157  status = SWITCH_STATUS_FALSE;
158  goto end;
159  }
160 
161  if (changed_read_codec && session->read_codec && session->read_impl.decoded_bytes_per_packet) {
163  switch_channel_event_set_data(session->channel, event);
164  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "channel-read-codec-name", session->read_impl.iananame);
165  switch_event_add_header(event, SWITCH_STACK_BOTTOM, "channel-read-codec-rate", "%d", session->read_impl.actual_samples_per_second);
166  switch_event_add_header(event, SWITCH_STACK_BOTTOM, "channel-read-codec-bit-rate", "%d", session->read_impl.bits_per_second);
167  if (session->read_impl.actual_samples_per_second != session->read_impl.samples_per_second) {
168  switch_event_add_header(event, SWITCH_STACK_BOTTOM, "channel-reported-read-codec-rate", "%d", session->read_impl.samples_per_second);
169  }
170  switch_event_fire(&event);
171  }
172 
173  switch_channel_set_variable(channel, "read_codec", session->read_impl.iananame);
174  switch_channel_set_variable(channel, "original_read_codec", session->read_impl.iananame);
175  switch_snprintf(tmp, sizeof(tmp), "%d", session->read_impl.actual_samples_per_second);
176  switch_channel_set_variable(channel, "read_rate", tmp);
177  switch_channel_set_variable(channel, "original_read_rate", tmp);
178 
179  session->raw_read_frame.codec = session->read_codec;
180  session->raw_write_frame.codec = session->read_codec;
181  session->enc_read_frame.codec = session->read_codec;
182  session->enc_write_frame.codec = session->read_codec;
183  }
184 
185  end:
186 
187  if (session->read_codec) {
189  }
190 
191  switch_mutex_unlock(session->codec_read_mutex);
192  return status;
193 }
194 
196 {
197  switch_event_t *event;
199  char tmp[30];
201 
202  switch_mutex_lock(session->codec_read_mutex);
203 
204  if (codec && (!codec->implementation || !switch_core_codec_ready(codec))) {
205  codec = NULL;
206  }
207 
208  if (codec) {
209  if (!session->real_read_codec) {
210  session->read_codec = session->real_read_codec = codec;
211  if (codec->implementation) {
212  session->read_impl = *codec->implementation;
213  session->real_read_impl = *codec->implementation;
214  } else {
215  memset(&session->read_impl, 0, sizeof(session->read_impl));
216  }
217  } else {
218  if (codec == session->read_codec) {
219  goto end;
220  }
221  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Push codec %s:%d\n",
222  switch_channel_get_name(session->channel), codec->implementation->iananame, codec->implementation->ianacode);
223  codec->next = session->read_codec;
224  session->read_codec = codec;
225  if (codec->implementation) {
226  session->read_impl = *codec->implementation;
227  } else {
228  memset(&session->read_impl, 0, sizeof(session->read_impl));
229  }
230  }
231  } else {
232  if (session->read_codec == session->real_read_codec) {
233  goto end;
234  }
235 
236  if (session->read_codec->next) {
237  switch_codec_t *old = session->read_codec;
238  session->read_codec = session->read_codec->next;
239  if (session->read_codec->implementation) {
240  session->read_impl = *session->read_codec->implementation;
241  } else {
242  memset(&session->read_impl, 0, sizeof(session->read_impl));
243  }
244  old->next = NULL;
245 
246  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Restore previous codec %s:%d.\n",
247  switch_channel_get_name(session->channel),
248  session->read_impl.iananame ? session->read_impl.iananame : "N/A", session->read_impl.ianacode);
249 
250 
251  } else if (session->real_read_codec) {
252  session->read_codec = session->real_read_codec;
253  if (session->real_read_codec->implementation) {
254  session->read_impl = *session->real_read_codec->implementation;
255  } else {
256  memset(&session->read_impl, 0, sizeof(session->read_impl));
257  }
258  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Restore original codec.\n");
259  } else {
260  status = SWITCH_STATUS_FALSE;
261  goto end;
262  }
263  }
264 
265  if (!session->read_codec) {
266  status = SWITCH_STATUS_FALSE;
267  goto end;
268  }
269 
270  if (session->read_codec && session->read_impl.decoded_bytes_per_packet) {
272  switch_channel_event_set_data(session->channel, event);
273  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "channel-read-codec-name", session->read_impl.iananame);
274  switch_event_add_header(event, SWITCH_STACK_BOTTOM, "channel-read-codec-rate", "%d", session->read_impl.actual_samples_per_second);
275  switch_event_add_header(event, SWITCH_STACK_BOTTOM, "channel-read-codec-bit-rate", "%d", session->read_impl.bits_per_second);
276  if (session->read_impl.actual_samples_per_second != session->read_impl.samples_per_second) {
277  switch_event_add_header(event, SWITCH_STACK_BOTTOM, "channel-reported-read-codec-rate", "%d", session->read_impl.samples_per_second);
278  }
279  switch_event_fire(&event);
280  }
281 
282  switch_channel_set_variable(channel, "read_codec", session->read_impl.iananame);
283  switch_snprintf(tmp, sizeof(tmp), "%d", session->read_impl.actual_samples_per_second);
284  switch_channel_set_variable(channel, "read_rate", tmp);
285 
286  session->raw_read_frame.codec = session->read_codec;
287  session->raw_write_frame.codec = session->read_codec;
288  session->enc_read_frame.codec = session->read_codec;
289  session->enc_write_frame.codec = session->read_codec;
290  }
291 
292  end:
293 
294  if (session->read_codec) {
296  }
297 
298  switch_mutex_unlock(session->codec_read_mutex);
299  return status;
300 
301 }
302 
304 {
305  switch_codec_t *codec;
306  codec = session->read_codec;
307  return codec;
308 }
309 
311 {
312  switch_codec_t *codec;
313  codec = session->real_read_codec ? session->real_read_codec : session->read_codec;
314  return codec;
315 }
316 
318 {
319  if (session->read_impl.codec_id) {
320  *impp = session->read_impl;
321  return SWITCH_STATUS_SUCCESS;
322  }
323 
324  memset(impp, 0, sizeof(*impp));
325  impp->number_of_channels = 1;
326  return SWITCH_STATUS_FALSE;
327 }
328 
330 {
331  if (session->real_read_impl.codec_id) {
332  *impp = session->real_read_impl;
333  return SWITCH_STATUS_SUCCESS;
334  }
335 
336  return switch_core_session_get_read_impl(session, impp);
337 }
338 
340 {
341  if (session->write_impl.codec_id) {
342  *impp = session->write_impl;
343  return SWITCH_STATUS_SUCCESS;
344  }
345 
346  memset(impp, 0, sizeof(*impp));
347  impp->number_of_channels = 1;
348  return SWITCH_STATUS_FALSE;
349 }
350 
352 {
353  if (session->video_read_impl.codec_id) {
354  *impp = session->video_read_impl;
355  return SWITCH_STATUS_SUCCESS;
356  }
357 
358  memset(impp, 0, sizeof(*impp));
359  impp->number_of_channels = 1;
360  return SWITCH_STATUS_FALSE;
361 }
362 
364 {
365  if (session->video_write_impl.codec_id) {
366  *impp = session->video_write_impl;
367  return SWITCH_STATUS_SUCCESS;
368  }
369 
370  memset(impp, 0, sizeof(*impp));
371  impp->number_of_channels = 1;
372  return SWITCH_STATUS_FALSE;
373 }
374 
375 
377 {
378  session->read_impl = *impp;
379  return SWITCH_STATUS_SUCCESS;
380 }
381 
383 {
384  session->write_impl = *impp;
385  return SWITCH_STATUS_SUCCESS;
386 }
387 
389 {
390  session->video_read_impl = *impp;
391  return SWITCH_STATUS_SUCCESS;
392 }
393 
395 {
396  session->video_write_impl = *impp;
397  return SWITCH_STATUS_SUCCESS;
398 }
399 
400 
402 {
403  switch_event_t *event;
405  char tmp[30];
407 
408  switch_mutex_lock(session->codec_write_mutex);
409 
410  if (!codec || !codec->implementation || !switch_core_codec_ready(codec)) {
411  if (session->real_write_codec) {
412  session->write_codec = session->real_write_codec;
413  session->write_impl = *session->real_write_codec->implementation;
414  session->real_write_codec = NULL;
415  } else {
416  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot set NULL codec!\n");
417  status = SWITCH_STATUS_FALSE;
418  goto end;
419  }
420  } else if (session->write_codec) {
421  if (session->real_write_codec) {
422  if (codec == session->real_write_codec) {
423  session->write_codec = codec;
424  session->write_impl = *codec->implementation;
425  session->real_write_codec = NULL;
426  } else {
427  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot double-set codec!\n");
428  status = SWITCH_STATUS_FALSE;
429  goto end;
430  }
431  } else {
432  session->real_write_codec = session->write_codec;
433  session->write_codec = codec;
434  session->write_impl = *codec->implementation;
435  }
436  } else {
437  session->write_codec = codec;
438  session->write_impl = *codec->implementation;
439  }
440 
441  if (session->write_codec && codec && session->write_impl.codec_id) {
443  switch_channel_event_set_data(session->channel, event);
444  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-Write-Codec-Name", session->write_impl.iananame);
445  switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Channel-Write-Codec-Rate", "%d", session->write_impl.actual_samples_per_second);
446  switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Channel-Write-codec-bit-rate", "%d", session->write_impl.bits_per_second);
447  if (session->write_impl.actual_samples_per_second != session->write_impl.samples_per_second) {
448  switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Channel-Reported-Write-Codec-Rate", "%d",
449  session->write_impl.actual_samples_per_second);
450  }
451  switch_event_fire(&event);
452  }
453 
454  switch_channel_set_variable(channel, "write_codec", session->write_impl.iananame);
455  switch_snprintf(tmp, sizeof(tmp), "%d", session->write_impl.actual_samples_per_second);
456  switch_channel_set_variable(channel, "write_rate", tmp);
457  }
458 
459  end:
460  switch_mutex_unlock(session->codec_write_mutex);
461 
462  return status;
463 }
464 
465 
467 {
468  switch_codec_t *codec;
469  codec = session->write_codec;
470 
471  return codec;
472 }
473 
475 {
476  switch_codec_t *codec;
477  codec = session->real_write_codec ? session->real_write_codec : session->write_codec;
478 
479  return codec;
480 }
481 
482 
483 
485 {
486  switch_event_t *event;
488  char tmp[30];
490 
491  if (!codec || !codec->implementation || !switch_core_codec_ready(codec)) {
492  if (session->video_read_codec) {
493  session->video_read_codec = NULL;
494  status = SWITCH_STATUS_SUCCESS;
495  goto end;
496  }
497  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot set NULL codec!\n");
498  status = SWITCH_STATUS_FALSE;
499  goto end;
500  }
501 
503  switch_channel_event_set_data(session->channel, event);
504  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "channel-video-read-codec-name", codec->implementation->iananame);
505  switch_event_add_header(event, SWITCH_STACK_BOTTOM, "channel-video-read-codec-rate", "%d", codec->implementation->actual_samples_per_second);
506  switch_event_fire(&event);
507  }
508 
509  switch_channel_set_variable(channel, "video_read_codec", codec->implementation->iananame);
510  switch_snprintf(tmp, sizeof(tmp), "%d", codec->implementation->actual_samples_per_second);
511  switch_channel_set_variable(channel, "video_read_rate", tmp);
512 
513  session->video_read_codec = codec;
514  if (codec->implementation) {
515  session->video_read_impl = *codec->implementation;
516  } else {
517  memset(&session->video_read_impl, 0, sizeof(session->video_read_impl));
518  }
519  end:
520 
521  return status;
522 }
523 
525 {
526  switch_codec_t *codec;
527  codec = session->video_read_codec;
528 
529  return codec;
530 
531 }
532 
534 {
535  switch_event_t *event;
537  char tmp[30];
539  if (!codec || !codec->implementation || !switch_core_codec_ready(codec)) {
540  if (session->video_write_codec) {
541  session->video_write_codec = NULL;
542  status = SWITCH_STATUS_SUCCESS;
543  goto end;
544  }
545  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot set NULL codec!\n");
546  status = SWITCH_STATUS_FALSE;
547  goto end;
548  }
549 
551  switch_channel_event_set_data(session->channel, event);
552  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "channel-video-write-codec-name", codec->implementation->iananame);
553  switch_event_add_header(event, SWITCH_STACK_BOTTOM, "channel-video-write-codec-rate", "%d", codec->implementation->actual_samples_per_second);
554  switch_event_fire(&event);
555  }
556 
557  switch_channel_set_variable(channel, "video_write_codec", codec->implementation->iananame);
558  switch_snprintf(tmp, sizeof(tmp), "%d", codec->implementation->actual_samples_per_second);
559  switch_channel_set_variable(channel, "video_write_rate", tmp);
560 
561  session->video_write_codec = codec;
562  session->video_write_impl = *codec->implementation;
563 
564  end:
565 
566  return status;
567 }
568 
570 {
571  switch_codec_t *codec;
572  codec = session->video_write_codec;
573 
574  return codec;
575 
576 }
577 
578 SWITCH_DECLARE(switch_status_t) switch_core_codec_parse_fmtp(const char *codec_name, const char *fmtp, uint32_t rate, switch_codec_fmtp_t *codec_fmtp)
579 {
580  switch_codec_interface_t *codec_interface;
582 
583  if (zstr(codec_name) || zstr(fmtp) || !codec_fmtp) {
584  return SWITCH_STATUS_FALSE;
585  }
586 
587  memset(codec_fmtp, 0, sizeof(*codec_fmtp));
588 
589  if ((codec_interface = switch_loadable_module_get_codec_interface(codec_name, NULL))) {
590  if (codec_interface->parse_fmtp) {
591  codec_fmtp->actual_samples_per_second = rate;
592  status = codec_interface->parse_fmtp(fmtp, codec_fmtp);
593  }
594 
595  UNPROTECT_INTERFACE(codec_interface);
596  }
597 
598  return status;
599 }
600 
602 {
603  switch_assert(codec != NULL);
604 
605  codec->implementation->destroy(codec);
606  codec->implementation->init(codec, codec->flags, NULL);
607 
608  return SWITCH_STATUS_SUCCESS;
609 }
610 
611 
613  const switch_codec_settings_t *codec_settings, switch_memory_pool_t *pool)
614 {
615  switch_assert(codec != NULL);
616  switch_assert(new_codec != NULL);
617 
618  return switch_core_codec_init(new_codec,
619  codec->implementation->iananame,
620  codec->implementation->modname,
621  codec->fmtp_in,
622  codec->implementation->samples_per_second,
623  codec->implementation->microseconds_per_packet / 1000,
624  codec->implementation->number_of_channels,
625  codec->flags,
626  codec_settings,
627  pool);
628 
629 }
630 
631 SWITCH_DECLARE(switch_status_t) switch_core_codec_init_with_bitrate(switch_codec_t *codec, const char *codec_name, const char *modname, const char *fmtp,
632  uint32_t rate, int ms, int channels, uint32_t bitrate, uint32_t flags,
633  const switch_codec_settings_t *codec_settings, switch_memory_pool_t *pool)
634 {
635  switch_codec_interface_t *codec_interface;
636  const switch_codec_implementation_t *iptr, *implementation = NULL;
637 
638  switch_assert(codec != NULL);
639  switch_assert(codec_name != NULL);
640 
641  memset(codec, 0, sizeof(*codec));
642 
643  if (pool) {
644  codec->session = switch_core_memory_pool_get_data(pool, "__session");
645  }
646 
647  if (strchr(codec_name, '.')) {
648  char *p = NULL;
649  codec_name = switch_core_strdup(pool, codec_name);
650  if ((p = strchr(codec_name, '.'))) {
651  *p++ = '\0';
652  modname = codec_name;
653  codec_name = p;
654  }
655  }
656 
657  if ((codec_interface = switch_loadable_module_get_codec_interface(codec_name, modname)) == 0) {
658  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid codec %s!\n", codec_name);
659  return SWITCH_STATUS_GENERR;
660  }
661 
662  if (!strncasecmp(codec_name, "PROXY", 5)) {
663  for (iptr = codec_interface->implementations; iptr; iptr = iptr->next) {
664  if ((!channels || channels == iptr->number_of_channels)) {
665  implementation = iptr;
666  break;
667  }
668  }
669 
670  goto found;
671  }
672 
673  /* If no specific codec interval is requested opt for 20ms above all else because lots of stuff assumes it */
674  if (!ms) {
675  for (iptr = codec_interface->implementations; iptr; iptr = iptr->next) {
676  uint32_t crate = !strcasecmp(codec_name, "g722") ? iptr->samples_per_second : iptr->actual_samples_per_second;
677  if ((!rate || rate == crate) && (!bitrate || bitrate == (uint32_t)iptr->bits_per_second) &&
678  (20 == (iptr->microseconds_per_packet / 1000)) && (!channels || channels == iptr->number_of_channels)) {
679  implementation = iptr;
680  goto found;
681  }
682  }
683  }
684 
685  /* Either looking for a specific interval or there was no interval specified and there wasn't one @20ms available */
686  for (iptr = codec_interface->implementations; iptr; iptr = iptr->next) {
687  uint32_t crate = !strcasecmp(codec_name, "g722") ? iptr->samples_per_second : iptr->actual_samples_per_second;
688  if ((!rate || rate == crate) && (!bitrate || bitrate == (uint32_t)iptr->bits_per_second) &&
689  (!ms || ms == (iptr->microseconds_per_packet / 1000)) && (!channels || channels == iptr->number_of_channels)) {
690  implementation = iptr;
691  break;
692  }
693  }
694 
695  found:
696 
697  if (implementation) {
698  switch_status_t status;
699  codec->codec_interface = codec_interface;
700  codec->implementation = implementation;
701  codec->flags = flags;
702 
703  if (pool) {
704  codec->memory_pool = pool;
705  } else {
706  if ((status = switch_core_new_memory_pool(&codec->memory_pool)) != SWITCH_STATUS_SUCCESS) {
707  return status;
708  }
710  }
711 
712  if (fmtp) {
713  codec->fmtp_in = switch_core_strdup(codec->memory_pool, fmtp);
714  }
715 
716  implementation->init(codec, flags, codec_settings);
717  switch_mutex_init(&codec->mutex, SWITCH_MUTEX_NESTED, codec->memory_pool);
719  return SWITCH_STATUS_SUCCESS;
720  } else {
721  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Codec %s Exists but not at the desired implementation. %dhz %dms %dch\n",
722  codec_name, rate, ms, channels);
723 
724  }
725 
726  UNPROTECT_INTERFACE(codec_interface);
727 
728  return SWITCH_STATUS_NOTIMPL;
729 }
730 
732  switch_codec_t *other_codec,
733  void *decoded_data,
734  uint32_t decoded_data_len,
735  uint32_t decoded_rate,
736  void *encoded_data, uint32_t *encoded_data_len, uint32_t *encoded_rate, unsigned int *flag)
737 {
738  switch_status_t status;
739 
740  switch_assert(codec != NULL);
741  switch_assert(encoded_data != NULL);
742  switch_assert(decoded_data != NULL);
743 
744  if (!codec->implementation || !switch_core_codec_ready(codec)) {
745  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Codec is not initialized!\n");
747  }
748 
750  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Codec encoder is not initialized!\n");
752  }
753 
754  if (codec->mutex) switch_mutex_lock(codec->mutex);
755  status = codec->implementation->encode(codec, other_codec, decoded_data, decoded_data_len,
756  decoded_rate, encoded_data, encoded_data_len, encoded_rate, flag);
757  if (codec->mutex) switch_mutex_unlock(codec->mutex);
758 
759  return status;
760 
761 }
762 
764  switch_codec_t *other_codec,
765  void *encoded_data,
766  uint32_t encoded_data_len,
767  uint32_t encoded_rate,
768  void *decoded_data, uint32_t *decoded_data_len, uint32_t *decoded_rate, unsigned int *flag)
769 {
770  switch_status_t status;
771 
772  switch_assert(codec != NULL);
773  switch_assert(encoded_data != NULL);
774  switch_assert(decoded_data != NULL);
775 
776  if (!codec->implementation || !switch_core_codec_ready(codec)) {
777  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Decode Codec is not initialized!\n");
779  }
780 
782  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Codec decoder is not initialized!\n");
784  }
785 
786  if (codec->implementation->encoded_bytes_per_packet) {
787  uint32_t frames = encoded_data_len / codec->implementation->encoded_bytes_per_packet / codec->implementation->number_of_channels;
788 
789  if (frames && codec->implementation->decoded_bytes_per_packet * frames > *decoded_data_len) {
790  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Buffer size sanity check failed! edl:%u ebpp:%u fr:%u ddl:%u\n",
791  encoded_data_len, codec->implementation->encoded_bytes_per_packet, frames, *decoded_data_len);
792  *decoded_data_len = codec->implementation->decoded_bytes_per_packet;
793  memset(decoded_data, 255, *decoded_data_len);
794  return SWITCH_STATUS_SUCCESS;
795  }
796  }
797 
798  if (codec->mutex) switch_mutex_lock(codec->mutex);
799  status = codec->implementation->decode(codec, other_codec, encoded_data, encoded_data_len, encoded_rate,
800  decoded_data, decoded_data_len, decoded_rate, flag);
801  if (codec->mutex) switch_mutex_unlock(codec->mutex);
802 
803  return status;
804 }
805 
807 {
809 
810  switch_assert(codec != NULL);
811 
812  if (!codec->implementation || !switch_core_codec_ready(codec)) {
813  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Codec is not initialized!\n");
815  }
816 
818  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Codec encoder is not initialized!\n");
820  }
821 
822  if (codec->mutex) switch_mutex_lock(codec->mutex);
823 
824  if (codec->implementation->encode_video) {
825  status = codec->implementation->encode_video(codec, frame);
826 
827  if (status == SWITCH_STATUS_MORE_DATA) {
828  frame->flags |= SFF_SAME_IMAGE;
829  } else {
830  frame->flags &= ~SFF_SAME_IMAGE;
831  }
832 
833  frame->packetlen = frame->datalen + 12;
834  }
835 
836  if (codec->mutex) switch_mutex_unlock(codec->mutex);
837 
838  return status;
839 
840 }
841 
843 {
845 
846  switch_assert(codec != NULL);
847  switch_assert(frame != NULL);
848 
849  if (!codec->implementation || !switch_core_codec_ready(codec)) {
850  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Decode Codec is not initialized!\n");
852  }
853 
855  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Codec decoder is not initialized!\n");
857  }
858 
859  if (codec->mutex) switch_mutex_lock(codec->mutex);
860 
861  if (codec->implementation->decode_video) {
862  status = codec->implementation->decode_video(codec, frame);
863  }
864  if (codec->mutex) switch_mutex_unlock(codec->mutex);
865 
866  return status;
867 }
868 
869 
873  void *cmd_data,
875  void *cmd_arg,
877  void **ret_data)
878 {
879 
881 
882 
883  switch_assert(codec != NULL);
884 
885 
886  if (!codec->implementation || !switch_core_codec_ready(codec)) {
887  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Codec is not initialized!\n");
888  abort();
889  //return SWITCH_STATUS_NOT_INITALIZED;
890  }
891 
892 
893  if (codec->mutex) switch_mutex_lock(codec->mutex);
894 
895  if (codec->implementation->codec_control) {
896  status = codec->implementation->codec_control(codec, cmd, ctype, cmd_data, atype, cmd_arg, rtype, ret_data);
897  }
898 
899  if (codec->mutex) switch_mutex_unlock(codec->mutex);
900 
901 
902  return status;
903 }
904 
906 {
907  switch_mutex_t *mutex = codec->mutex;
908  switch_memory_pool_t *pool = codec->memory_pool;
909  int free_pool = 0;
910 
911  switch_assert(codec != NULL);
912 
913  if (mutex) switch_mutex_lock(mutex);
914 
915  if (switch_core_codec_ready(codec)) {
917  } else {
918  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Codec is not initialized!\n");
919  if (mutex) switch_mutex_unlock(mutex);
921  }
922 
924  free_pool = 1;
925  }
926 
927  codec->implementation->destroy(codec);
928 
929  UNPROTECT_INTERFACE(codec->codec_interface);
930 
931  if (mutex) switch_mutex_unlock(mutex);
932 
933  if (free_pool) {
935  }
936 
937  memset(codec, 0, sizeof(*codec));
938 
939  return SWITCH_STATUS_SUCCESS;
940 }
941 
942 /* For Emacs:
943  * Local Variables:
944  * mode:c
945  * indent-tabs-mode:t
946  * tab-width:4
947  * c-basic-offset:4
948  * End:
949  * For VIM:
950  * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
951  */
switch_status_t switch_core_codec_decode_video(switch_codec_t *codec, switch_frame_t *frame)
Decode video data using a codec handle.
#define switch_event_fire(event)
Fire an event filling in most of the arguements with obvious values.
Definition: switch_event.h:412
#define switch_core_new_memory_pool(p)
Create a new sub memory pool from the core's master pool.
Definition: switch_core.h:631
switch_status_t switch_thread_rwlock_unlock(switch_thread_rwlock_t *rwlock)
Definition: switch_apr.c:263
switch_status_t switch_core_session_set_video_write_codec(switch_core_session_t *session, switch_codec_t *codec)
#define SWITCH_CHANNEL_SESSION_LOG(x)
switch_status_t switch_core_codec_parse_fmtp(const char *codec_name, const char *fmtp, uint32_t rate, switch_codec_fmtp_t *codec_fmtp)
#define switch_set_flag(obj, flag)
Set a flag on an arbitrary object.
Definition: switch_utils.h:631
#define SWITCH_CHANNEL_LOG
void switch_core_session_unset_write_codec(switch_core_session_t *session)
void switch_channel_event_set_data(_In_ switch_channel_t *channel, _In_ switch_event_t *event)
Add information about a given channel to an event object.
#define switch_core_strdup(_pool, _todup)
Copy a string using memory allocation from a given pool.
Definition: switch_core.h:729
switch_status_t switch_core_codec_encode(switch_codec_t *codec, switch_codec_t *other_codec, void *decoded_data, uint32_t decoded_data_len, uint32_t decoded_rate, void *encoded_data, uint32_t *encoded_data_len, uint32_t *encoded_rate, unsigned int *flag)
Encode data using a codec handle.
switch_status_t switch_core_session_set_read_impl(switch_core_session_t *session, const switch_codec_implementation_t *impp)
#define switch_core_destroy_memory_pool(p)
Returns a subpool back to the main pool.
Definition: switch_core.h:640
switch_memory_pool_t * pool
switch_status_t switch_event_add_header(switch_event_t *event, switch_stack_t stack, const char *header_name, const char *fmt,...) PRINTF_FUNCTION(4
Add a header to an event.
Representation of an event.
Definition: switch_event.h:80
switch_codec_implementation_t * implementations
void * switch_core_memory_pool_get_data(switch_memory_pool_t *pool, const char *key)
switch_status_t switch_core_session_get_real_read_impl(switch_core_session_t *session, switch_codec_implementation_t *impp)
switch_status_t switch_core_codec_decode(switch_codec_t *codec, switch_codec_t *other_codec, void *encoded_data, uint32_t encoded_data_len, uint32_t encoded_rate, void *decoded_data, uint32_t *decoded_data_len, uint32_t *decoded_rate, unsigned int *flag)
Decode data using a codec handle.
switch_status_t switch_core_codec_destroy(switch_codec_t *codec)
Destroy an initalized codec handle.
switch_status_t switch_core_session_set_read_codec(switch_core_session_t *session, switch_codec_t *codec)
int switch_snprintf(_Out_z_cap_(len) char *buf, _In_ switch_size_t len, _In_z_ _Printf_format_string_ const char *format,...)
switch_status_t switch_core_session_set_write_codec(switch_core_session_t *session, switch_codec_t *codec)
switch_status_t switch_core_session_get_video_write_impl(switch_core_session_t *session, switch_codec_implementation_t *impp)
#define zstr(x)
Definition: switch_utils.h:281
switch_status_t switch_core_codec_reset(switch_codec_t *codec)
switch_status_t switch_mutex_unlock(switch_mutex_t *lock)
Definition: switch_apr.c:290
switch_codec_t * switch_core_session_get_effective_write_codec(switch_core_session_t *session)
switch_status_t switch_core_session_get_read_impl(switch_core_session_t *session, switch_codec_implementation_t *impp)
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
switch_codec_control_command_t
#define UNPROTECT_INTERFACE(_it)
#define switch_clear_flag(obj, flag)
Clear a flag on an arbitrary object while locked.
Definition: switch_utils.h:655
#define SWITCH_MUTEX_NESTED
Definition: switch_apr.h:318
switch_status_t switch_thread_rwlock_wrlock(switch_thread_rwlock_t *rwlock)
Definition: switch_apr.c:237
switch_codec_control_type_t
const switch_codec_implementation_t * implementation
void switch_core_session_lock_codec_write(switch_core_session_t *session)
switch_status_t switch_core_session_set_video_read_codec(switch_core_session_t *session, switch_codec_t *codec)
switch_status_t switch_mutex_lock(switch_mutex_t *lock)
Definition: switch_apr.c:285
switch_status_t switch_core_session_set_video_read_impl(switch_core_session_t *session, const switch_codec_implementation_t *impp)
switch_status_t switch_core_session_set_video_write_impl(switch_core_session_t *session, const switch_codec_implementation_t *impp)
switch_status_t switch_event_add_header_string(switch_event_t *event, switch_stack_t stack, const char *header_name, const char *data)
Add a string header to an event.
Top level module interface to implement a series of codec implementations.
switch_status_t switch_core_codec_copy(switch_codec_t *codec, switch_codec_t *new_codec, const switch_codec_settings_t *codec_settings, switch_memory_pool_t *pool)
switch_status_t switch_mutex_init(switch_mutex_t **lock, unsigned int flags, switch_memory_pool_t *pool)
Definition: switch_apr.c:270
An abstraction of a data frame.
Definition: switch_frame.h:43
struct switch_codec * next
#define switch_core_codec_init(_codec, _codec_name, _modname, _fmtp, _rate, _ms, _channels, _flags, _codec_settings, _pool)
Initialize a codec handle.
Definition: switch_core.h:1602
uint32_t switch_core_codec_next_id(void)
switch_status_t switch_core_session_get_write_impl(switch_core_session_t *session, switch_codec_implementation_t *impp)
switch_codec_t * switch_core_session_get_effective_read_codec(switch_core_session_t *session)
switch_codec_interface_t * switch_loadable_module_get_codec_interface(const char *name, const char *modname)
Retrieve the codec interface by it's registered name.
switch_mutex_t * mutex
switch_status_t switch_core_codec_encode_video(switch_codec_t *codec, switch_frame_t *frame)
Encode video data using a codec handle.
void switch_core_session_lock_codec_read(switch_core_session_t *session)
switch_codec_t * switch_core_session_get_video_read_codec(switch_core_session_t *session)
switch_status_t switch_core_codec_init_with_bitrate(switch_codec_t *codec, const char *codec_name, const char *modname, const char *fmtp, uint32_t rate, int ms, int channels, uint32_t bitrate, uint32_t flags, const switch_codec_settings_t *codec_settings, switch_memory_pool_t *pool)
struct apr_thread_mutex_t switch_mutex_t
Definition: switch_apr.h:314
switch_status_t
Common return values.
switch_core_codec_fmtp_parse_func_t parse_fmtp
Main Library Header.
#define switch_event_create(event, id)
Create a new event assuming it will not be custom event and therefore hiding the unused parameters...
Definition: switch_event.h:383
#define SWITCH_DECLARE(type)
#define switch_channel_set_flag(_c, _f)
switch_core_codec_init_func_t init
void switch_core_session_unlock_codec_read(switch_core_session_t *session)
static uint32_t CODEC_ID
struct switch_codec_implementation * next
struct apr_pool_t switch_memory_pool_t
#define switch_test_flag(obj, flag)
Test for the existance of a flag on an arbitary object.
Definition: switch_utils.h:624
static switch_bool_t switch_core_codec_ready(switch_codec_t *codec)
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
A table of settings and callbacks that define a paticular implementation of a codec.
switch_status_t switch_core_session_set_real_read_codec(switch_core_session_t *session, switch_codec_t *codec)
switch_codec_t * switch_core_session_get_read_codec(switch_core_session_t *session)
switch_status_t switch_core_session_get_video_read_impl(switch_core_session_t *session, switch_codec_implementation_t *impp)
#define switch_assert(expr)
#define switch_channel_set_variable(_channel, _var, _val)
char * switch_channel_get_name(switch_channel_t *channel)
Retrieve the name of a given channel.
void switch_core_session_unset_read_codec(switch_core_session_t *session)
switch_status_t switch_core_session_set_write_impl(switch_core_session_t *session, const switch_codec_implementation_t *impp)
memset(buf, 0, buflen)
void switch_core_session_unlock_codec_write(switch_core_session_t *session)
switch_codec_t * switch_core_session_get_video_write_codec(switch_core_session_t *session)
switch_status_t switch_core_codec_control(switch_codec_t *codec, switch_codec_control_command_t cmd, switch_codec_control_type_t ctype, void *cmd_data, switch_codec_control_type_t atype, void *cmd_arg, switch_codec_control_type_t *rtype, void **ret_data)
send control data using a codec handle
switch_codec_t * switch_core_session_get_write_codec(switch_core_session_t *session)