RTS API Documentation  1.10.11
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 
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);
60 }
61 
63 {
65 }
66 
68 {
70 }
71 
73 {
75 }
76 
78 {
80 }
81 
83 {
84  switch_mutex_t *mutex = NULL;
85 
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);
92 }
93 
95 {
96  switch_event_t *event;
98  char tmp[30];
100  int changed_read_codec = 0;
101 
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",
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 
124  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Original read codec replaced with %s:%d\n",
125  switch_channel_get_name(session->channel), codec->implementation ? codec->implementation->iananame : "undefined", codec->implementation ? codec->implementation->ianacode : -1);
126  /* Set real_read_codec to front of the list of read_codecs */
127  cur_codec = session->read_codec;
128  while (cur_codec != NULL) {
129  if (cur_codec->next == session->real_read_codec) {
130  cur_codec->next = codec;
131  break;
132  }
133 
134  cur_codec = cur_codec->next;
135  }
136 
137  session->real_read_codec = codec;
138  session->real_read_impl = *codec->implementation;
139 
140  /* set read_codec with real_read_codec if it no longer is ready */
141  if (!switch_core_codec_ready(session->read_codec)) {
142  session->read_codec = codec;
143  changed_read_codec = 1;
144  if (codec->implementation) {
145  session->read_impl = *codec->implementation;
146  session->real_read_impl = *codec->implementation;
147  } else {
148  memset(&session->read_impl, 0, sizeof(session->read_impl));
149  }
150  }
151  }
152 
153  /* force media bugs to copy the read codec from the next frame */
155  if (switch_core_codec_ready(&session->bug_codec)) {
156  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Destroying BUG Codec %s:%d\n",
159  }
160 
162  } else {
163  status = SWITCH_STATUS_FALSE;
164  goto end;
165  }
166 
167  if (changed_read_codec && session->read_codec && session->read_impl.decoded_bytes_per_packet) {
169  switch_channel_event_set_data(session->channel, event);
170  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "channel-read-codec-name", session->read_impl.iananame);
171  switch_event_add_header(event, SWITCH_STACK_BOTTOM, "channel-read-codec-rate", "%d", session->read_impl.actual_samples_per_second);
172  switch_event_add_header(event, SWITCH_STACK_BOTTOM, "channel-read-codec-bit-rate", "%d", session->read_impl.bits_per_second);
174  switch_event_add_header(event, SWITCH_STACK_BOTTOM, "channel-reported-read-codec-rate", "%d", session->read_impl.samples_per_second);
175  }
176 
177  switch_event_fire(&event);
178  }
179 
180  switch_channel_set_variable(channel, "read_codec", session->read_impl.iananame);
181  switch_channel_set_variable(channel, "original_read_codec", session->read_impl.iananame);
182  switch_snprintf(tmp, sizeof(tmp), "%d", session->read_impl.actual_samples_per_second);
183  switch_channel_set_variable(channel, "read_rate", tmp);
184  switch_channel_set_variable(channel, "original_read_rate", tmp);
185 
186  session->raw_read_frame.codec = session->read_codec;
187  session->raw_write_frame.codec = session->read_codec;
188  session->enc_read_frame.codec = session->read_codec;
189  session->enc_write_frame.codec = session->read_codec;
190  }
191 
192  end:
193 
194  if (session->read_codec) {
196  }
197 
199 
200  return status;
201 }
202 
204 {
205  switch_event_t *event;
207  char tmp[30];
209 
211 
212  if (codec && (!codec->implementation || !switch_core_codec_ready(codec))) {
213  codec = NULL;
214  }
215 
216  if (codec) {
217  if (!session->real_read_codec) {
218  session->read_codec = session->real_read_codec = codec;
219  if (codec->implementation) {
220  session->read_impl = *codec->implementation;
221  session->real_read_impl = *codec->implementation;
222  } else {
223  memset(&session->read_impl, 0, sizeof(session->read_impl));
224  }
225  } else {
226  if (codec == session->read_codec) {
227  goto end;
228  }
229  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Push codec %s:%d\n",
230  switch_channel_get_name(session->channel), codec->implementation ? codec->implementation->iananame : "undefined", codec->implementation ? codec->implementation->ianacode : -1);
231  codec->next = session->read_codec;
232  session->read_codec = codec;
233  if (codec->implementation) {
234  session->read_impl = *codec->implementation;
235  } else {
236  memset(&session->read_impl, 0, sizeof(session->read_impl));
237  }
238  }
239  } else {
240  if (session->read_codec == session->real_read_codec) {
241  goto end;
242  }
243 
244  if (session->read_codec->next && switch_core_codec_ready(session->read_codec->next)) {
245  switch_codec_t *old = session->read_codec;
246  session->read_codec = session->read_codec->next;
247  if (session->read_codec->implementation) {
248  session->read_impl = *session->read_codec->implementation;
249  } else {
250  memset(&session->read_impl, 0, sizeof(session->read_impl));
251  }
252  old->next = NULL;
253 
254  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Restore previous codec %s:%d.\n",
256  session->read_impl.iananame ? session->read_impl.iananame : "N/A", session->read_impl.ianacode);
257 
258 
259  } else if (session->real_read_codec) {
260  session->read_codec = session->real_read_codec;
261  if (session->real_read_codec->implementation) {
262  session->read_impl = *session->real_read_codec->implementation;
263  } else {
264  memset(&session->read_impl, 0, sizeof(session->read_impl));
265  }
266  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Restore original codec.\n");
267  } else {
268  status = SWITCH_STATUS_FALSE;
269  goto end;
270  }
271  }
272 
273  if (!session->read_codec) {
274  status = SWITCH_STATUS_FALSE;
275  goto end;
276  }
277 
278  if (session->read_impl.decoded_bytes_per_packet) {
280  switch_channel_event_set_data(session->channel, event);
281  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "channel-read-codec-name", session->read_impl.iananame);
282  switch_event_add_header(event, SWITCH_STACK_BOTTOM, "channel-read-codec-rate", "%d", session->read_impl.actual_samples_per_second);
283  switch_event_add_header(event, SWITCH_STACK_BOTTOM, "channel-read-codec-bit-rate", "%d", session->read_impl.bits_per_second);
285  switch_event_add_header(event, SWITCH_STACK_BOTTOM, "channel-reported-read-codec-rate", "%d", session->read_impl.samples_per_second);
286  }
287  switch_event_fire(&event);
288  }
289 
290  switch_channel_set_variable(channel, "read_codec", session->read_impl.iananame);
291  switch_snprintf(tmp, sizeof(tmp), "%d", session->read_impl.actual_samples_per_second);
292  switch_channel_set_variable(channel, "read_rate", tmp);
293 
294  session->raw_read_frame.codec = session->read_codec;
295  session->raw_write_frame.codec = session->read_codec;
296  session->enc_read_frame.codec = session->read_codec;
297  session->enc_write_frame.codec = session->read_codec;
298  }
299 
300  end:
301 
302  if (session->read_codec) {
304  }
305 
307  return status;
308 
309 }
310 
312 {
313  switch_codec_t *codec;
314  codec = session->read_codec;
315  return codec;
316 }
317 
319 {
320  switch_codec_t *codec;
321  codec = session->real_read_codec ? session->real_read_codec : session->read_codec;
322  return codec;
323 }
324 
326 {
327  if (session->read_impl.codec_id) {
328  *impp = session->read_impl;
329  return SWITCH_STATUS_SUCCESS;
330  }
331 
332  memset(impp, 0, sizeof(*impp));
333  impp->number_of_channels = 1;
334  return SWITCH_STATUS_FALSE;
335 }
336 
338 {
339  if (session->real_read_impl.codec_id) {
340  *impp = session->real_read_impl;
341  return SWITCH_STATUS_SUCCESS;
342  }
343 
344  return switch_core_session_get_read_impl(session, impp);
345 }
346 
348 {
349  if (session->write_impl.codec_id) {
350  *impp = session->write_impl;
351  return SWITCH_STATUS_SUCCESS;
352  }
353 
354  memset(impp, 0, sizeof(*impp));
355  impp->number_of_channels = 1;
356  return SWITCH_STATUS_FALSE;
357 }
358 
360 {
361  if (session->video_read_impl.codec_id) {
362  *impp = session->video_read_impl;
363  return SWITCH_STATUS_SUCCESS;
364  }
365 
366  memset(impp, 0, sizeof(*impp));
367  impp->number_of_channels = 1;
368  return SWITCH_STATUS_FALSE;
369 }
370 
372 {
373  if (session->video_write_impl.codec_id) {
374  *impp = session->video_write_impl;
375  return SWITCH_STATUS_SUCCESS;
376  }
377 
378  memset(impp, 0, sizeof(*impp));
379  impp->number_of_channels = 1;
380  return SWITCH_STATUS_FALSE;
381 }
382 
383 
385 {
386  session->read_impl = *impp;
387  return SWITCH_STATUS_SUCCESS;
388 }
389 
391 {
392  session->write_impl = *impp;
393  return SWITCH_STATUS_SUCCESS;
394 }
395 
397 {
398  session->video_read_impl = *impp;
399  return SWITCH_STATUS_SUCCESS;
400 }
401 
403 {
404  session->video_write_impl = *impp;
405  return SWITCH_STATUS_SUCCESS;
406 }
407 
408 
410 {
411  switch_event_t *event;
413  char tmp[30];
415 
417 
418  if (!codec || !codec->implementation || !switch_core_codec_ready(codec)) {
419  if (session->real_write_codec) {
420  session->write_codec = session->real_write_codec;
421  session->write_impl = *session->real_write_codec->implementation;
422  session->real_write_codec = NULL;
423  } else {
424  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot set NULL codec!\n");
425  status = SWITCH_STATUS_FALSE;
426  goto end;
427  }
428  } else if (session->write_codec) {
429  if (session->real_write_codec) {
430  if (codec == session->real_write_codec) {
431  session->write_codec = codec;
432  session->write_impl = *codec->implementation;
433  session->real_write_codec = NULL;
434  } else {
435  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot double-set codec!\n");
436  status = SWITCH_STATUS_FALSE;
437  goto end;
438  }
439  } else {
440  session->real_write_codec = session->write_codec;
441  session->write_codec = codec;
442  session->write_impl = *codec->implementation;
443  }
444  } else {
445  session->write_codec = codec;
446  session->write_impl = *codec->implementation;
447  }
448 
449  if (codec && session->write_impl.codec_id) {
451  switch_channel_event_set_data(session->channel, event);
452  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-Write-Codec-Name", session->write_impl.iananame);
453  switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Channel-Write-Codec-Rate", "%d", session->write_impl.actual_samples_per_second);
454  switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Channel-Write-codec-bit-rate", "%d", session->write_impl.bits_per_second);
456  switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Channel-Reported-Write-Codec-Rate", "%d",
458  }
459  switch_event_fire(&event);
460  }
461 
462  switch_channel_set_variable(channel, "write_codec", session->write_impl.iananame);
463  switch_snprintf(tmp, sizeof(tmp), "%d", session->write_impl.actual_samples_per_second);
464  switch_channel_set_variable(channel, "write_rate", tmp);
465  }
466 
467  end:
469 
470  return status;
471 }
472 
473 
475 {
476  switch_codec_t *codec;
477  codec = session->write_codec;
478 
479  return codec;
480 }
481 
483 {
484  switch_codec_t *codec;
485  codec = session->real_write_codec ? session->real_write_codec : session->write_codec;
486 
487  return codec;
488 }
489 
490 
491 
493 {
494  switch_event_t *event;
496  char tmp[30];
498 
499  if (!codec || !codec->implementation || !switch_core_codec_ready(codec)) {
500  if (session->video_read_codec) {
501  session->video_read_codec = NULL;
502  status = SWITCH_STATUS_SUCCESS;
503  goto end;
504  }
505  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot set NULL codec!\n");
506  status = SWITCH_STATUS_FALSE;
507  goto end;
508  }
509 
511  switch_channel_event_set_data(session->channel, event);
512  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "channel-video-read-codec-name", codec->implementation->iananame);
513  switch_event_add_header(event, SWITCH_STACK_BOTTOM, "channel-video-read-codec-rate", "%d", codec->implementation->actual_samples_per_second);
514  switch_event_fire(&event);
515  }
516 
517  switch_channel_set_variable(channel, "video_read_codec", codec->implementation->iananame);
518  switch_snprintf(tmp, sizeof(tmp), "%d", codec->implementation->actual_samples_per_second);
519  switch_channel_set_variable(channel, "video_read_rate", tmp);
520 
521  session->video_read_codec = codec;
522  if (codec->implementation) {
523  session->video_read_impl = *codec->implementation;
524  } else {
525  memset(&session->video_read_impl, 0, sizeof(session->video_read_impl));
526  }
527  end:
528 
529  return status;
530 }
531 
533 {
534  switch_codec_t *codec;
535  codec = session->video_read_codec;
536 
537  return codec;
538 
539 }
540 
542 {
543  switch_event_t *event;
545  char tmp[30];
547  if (!codec || !codec->implementation || !switch_core_codec_ready(codec)) {
548  if (session->video_write_codec) {
549  session->video_write_codec = NULL;
550  status = SWITCH_STATUS_SUCCESS;
551  goto end;
552  }
553  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot set NULL codec!\n");
554  status = SWITCH_STATUS_FALSE;
555  goto end;
556  }
557 
559  switch_channel_event_set_data(session->channel, event);
560  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "channel-video-write-codec-name", codec->implementation->iananame);
561  switch_event_add_header(event, SWITCH_STACK_BOTTOM, "channel-video-write-codec-rate", "%d", codec->implementation->actual_samples_per_second);
562  switch_event_fire(&event);
563  }
564 
565  switch_channel_set_variable(channel, "video_write_codec", codec->implementation->iananame);
566  switch_snprintf(tmp, sizeof(tmp), "%d", codec->implementation->actual_samples_per_second);
567  switch_channel_set_variable(channel, "video_write_rate", tmp);
568 
569  session->video_write_codec = codec;
570  session->video_write_impl = *codec->implementation;
571 
572  end:
573 
574  return status;
575 }
576 
578 {
579  switch_codec_t *codec;
580  codec = session->video_write_codec;
581 
582  return codec;
583 
584 }
585 
586 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)
587 {
588  switch_codec_interface_t *codec_interface;
590 
591  if (zstr(codec_name) || zstr(fmtp) || !codec_fmtp) {
592  return SWITCH_STATUS_FALSE;
593  }
594 
595  memset(codec_fmtp, 0, sizeof(*codec_fmtp));
596 
597  if ((codec_interface = switch_loadable_module_get_codec_interface(codec_name, NULL))) {
598  if (codec_interface->parse_fmtp) {
599  codec_fmtp->actual_samples_per_second = rate;
600  status = codec_interface->parse_fmtp(fmtp, codec_fmtp);
601  }
602 
603  UNPROTECT_INTERFACE(codec_interface);
604  }
605 
606  return status;
607 }
608 
610 {
611  switch_assert(codec != NULL);
612 
613  codec->implementation->destroy(codec);
614  codec->implementation->init(codec, codec->flags, NULL);
615 
616  return SWITCH_STATUS_SUCCESS;
617 }
618 
619 
621  const switch_codec_settings_t *codec_settings, switch_memory_pool_t *pool)
622 {
623  uint32_t codec_rate;
624  switch_assert(codec != NULL);
625  switch_assert(new_codec != NULL);
626 
627  codec_rate = !strcasecmp(codec->implementation->iananame, "g722")
629 
630  return switch_core_codec_init(new_codec,
631  codec->implementation->iananame,
632  codec->implementation->modname,
633  codec->fmtp_in,
634  codec_rate,
637  codec->flags,
638  codec_settings,
639  pool);
640 
641 }
642 
643 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,
644  uint32_t rate, int ms, int channels, uint32_t bitrate, uint32_t flags,
645  const switch_codec_settings_t *codec_settings, switch_memory_pool_t *pool)
646 {
647  switch_codec_interface_t *codec_interface;
648  const switch_codec_implementation_t *iptr, *implementation = NULL;
649 
650  switch_assert(codec != NULL);
651  switch_assert(codec_name != NULL);
652 
653  memset(codec, 0, sizeof(*codec));
654 
655  if (pool) {
656  codec->session = switch_core_memory_pool_get_data(pool, "__session");
657  }
658 
659  if (strchr(codec_name, '.')) {
660  char *p = NULL;
661  codec_name = switch_core_strdup(pool, codec_name);
662  if ((p = strchr(codec_name, '.'))) {
663  *p++ = '\0';
664  modname = codec_name;
665  codec_name = p;
666  }
667  }
668 
669  if ((codec_interface = switch_loadable_module_get_codec_interface(codec_name, modname)) == 0) {
670  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid codec %s!\n", codec_name);
671  return SWITCH_STATUS_GENERR;
672  }
673 
674  if (!strncasecmp(codec_name, "PROXY", 5)) {
675  for (iptr = codec_interface->implementations; iptr; iptr = iptr->next) {
676  if (!channels || channels == iptr->number_of_channels) {
677  implementation = iptr;
678  break;
679  }
680  }
681 
682  goto found;
683  }
684 
685  /* If no specific codec interval is requested opt for 20ms above all else because lots of stuff assumes it */
686  if (!ms) {
687  for (iptr = codec_interface->implementations; iptr; iptr = iptr->next) {
688  uint32_t crate = !strcasecmp(codec_name, "g722") ? iptr->samples_per_second : iptr->actual_samples_per_second;
689  if ((!rate || rate == crate) && (!bitrate || bitrate == (uint32_t)iptr->bits_per_second) &&
690  (20 == (iptr->microseconds_per_packet / 1000)) && (!channels || channels == iptr->number_of_channels)) {
691  implementation = iptr;
692  goto found;
693  }
694  }
695  }
696 
697  /* Either looking for a specific interval or there was no interval specified and there wasn't one @20ms available */
698  for (iptr = codec_interface->implementations; iptr; iptr = iptr->next) {
699  uint32_t crate = !strcasecmp(codec_name, "g722") ? iptr->samples_per_second : iptr->actual_samples_per_second;
700  if ((!rate || rate == crate) && (!bitrate || bitrate == (uint32_t)iptr->bits_per_second) &&
701  (!ms || ms == (iptr->microseconds_per_packet / 1000)) && (!channels || channels == iptr->number_of_channels)) {
702  implementation = iptr;
703  break;
704  }
705  }
706 
707  found:
708 
709  if (implementation) {
710  switch_status_t status;
711  codec->codec_interface = codec_interface;
712  codec->implementation = implementation;
713  codec->flags = flags;
714 
715  if (pool) {
716  codec->memory_pool = pool;
717  } else {
719  return status;
720  }
722  }
723 
724  if (fmtp) {
725  codec->fmtp_in = switch_core_strdup(codec->memory_pool, fmtp);
726  }
727 
728  implementation->init(codec, flags, codec_settings);
731  return SWITCH_STATUS_SUCCESS;
732  } else {
733  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Codec %s Exists but not at the desired implementation. %dhz %dms %dch\n",
734  codec_name, rate, ms, channels);
735 
736  }
737 
738  UNPROTECT_INTERFACE(codec_interface);
739 
740  return SWITCH_STATUS_NOTIMPL;
741 }
742 
744  switch_codec_t *other_codec,
745  void *decoded_data,
746  uint32_t decoded_data_len,
747  uint32_t decoded_rate,
748  void *encoded_data, uint32_t *encoded_data_len, uint32_t *encoded_rate, unsigned int *flag)
749 {
750  switch_status_t status;
751 
752  switch_assert(codec != NULL);
753  switch_assert(encoded_data != NULL);
754  switch_assert(decoded_data != NULL);
755 
756  if (!codec->implementation || !switch_core_codec_ready(codec)) {
757  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Codec is not initialized!\n");
759  }
760 
762  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Codec encoder is not initialized!\n");
764  }
765 
766  if (codec->mutex) switch_mutex_lock(codec->mutex);
767  status = codec->implementation->encode(codec, other_codec, decoded_data, decoded_data_len,
768  decoded_rate, encoded_data, encoded_data_len, encoded_rate, flag);
769  if (codec->mutex) switch_mutex_unlock(codec->mutex);
770 
771  return status;
772 
773 }
774 
776  switch_codec_t *other_codec,
777  void *encoded_data,
778  uint32_t encoded_data_len,
779  uint32_t encoded_rate,
780  void *decoded_data, uint32_t *decoded_data_len, uint32_t *decoded_rate, unsigned int *flag)
781 {
782  switch_status_t status;
783 
784  switch_assert(codec != NULL);
785  switch_assert(encoded_data != NULL);
786  switch_assert(decoded_data != NULL);
787 
788  if (!codec->implementation || !switch_core_codec_ready(codec)) {
789  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Decode Codec is not initialized!\n");
791  }
792 
794  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Codec decoder is not initialized!\n");
796  }
797 
799  uint32_t frames = encoded_data_len / codec->implementation->encoded_bytes_per_packet / codec->implementation->number_of_channels;
800 
801  if (frames && codec->implementation->decoded_bytes_per_packet * frames > *decoded_data_len) {
802  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Buffer size sanity check failed! edl:%u ebpp:%u fr:%u ddl:%u\n",
803  encoded_data_len, codec->implementation->encoded_bytes_per_packet, frames, *decoded_data_len);
804  *decoded_data_len = codec->implementation->decoded_bytes_per_packet;
805  memset(decoded_data, 255, *decoded_data_len);
806  return SWITCH_STATUS_SUCCESS;
807  }
808  }
809 
810  if (codec->mutex) switch_mutex_lock(codec->mutex);
811  status = codec->implementation->decode(codec, other_codec, encoded_data, encoded_data_len, encoded_rate,
812  decoded_data, decoded_data_len, decoded_rate, flag);
813  if (codec->mutex) switch_mutex_unlock(codec->mutex);
814 
815  return status;
816 }
817 
819 {
821 
822  switch_assert(codec != NULL);
823 
824  if (!codec->implementation || !switch_core_codec_ready(codec)) {
825  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Codec is not initialized!\n");
827  }
828 
830  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Codec encoder is not initialized!\n");
832  }
833 
834  if (codec->mutex) switch_mutex_lock(codec->mutex);
835 
836  if (codec->implementation->encode_video) {
837  status = codec->implementation->encode_video(codec, frame);
838 
839  if (status == SWITCH_STATUS_MORE_DATA) {
840  frame->flags |= SFF_SAME_IMAGE;
841  } else {
842  frame->flags &= ~SFF_SAME_IMAGE;
843  }
844 
845  frame->packetlen = frame->datalen + 12;
846  }
847 
848  if (codec->mutex) switch_mutex_unlock(codec->mutex);
849 
850  return status;
851 
852 }
853 
855 {
857 
858  switch_assert(codec != NULL);
859  switch_assert(frame != NULL);
860 
861  if (!codec->implementation || !switch_core_codec_ready(codec)) {
862  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Decode Codec is not initialized!\n");
864  }
865 
867  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Codec decoder is not initialized!\n");
869  }
870 
871  if (codec->mutex) switch_mutex_lock(codec->mutex);
872 
873  if (codec->implementation->decode_video) {
874  status = codec->implementation->decode_video(codec, frame);
875  }
876  if (codec->mutex) switch_mutex_unlock(codec->mutex);
877 
878  return status;
879 }
880 
881 
885  void *cmd_data,
887  void *cmd_arg,
889  void **ret_data)
890 {
891 
893 
894 
895  switch_assert(codec != NULL);
896 
897 
898  if (!codec->implementation || !switch_core_codec_ready(codec)) {
899  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Codec is not initialized!\n");
900  abort();
901  //return SWITCH_STATUS_NOT_INITALIZED;
902  }
903 
904 
905  if (codec->mutex) switch_mutex_lock(codec->mutex);
906 
907  if (codec->implementation->codec_control) {
908  status = codec->implementation->codec_control(codec, cmd, ctype, cmd_data, atype, cmd_arg, rtype, ret_data);
909  }
910 
911  if (codec->mutex) switch_mutex_unlock(codec->mutex);
912 
913 
914  return status;
915 }
916 
918 {
919  switch_mutex_t *mutex = NULL;
920  switch_memory_pool_t *pool = NULL;
921  int free_pool = 0;
922 
923  switch_assert(codec != NULL);
924  mutex = codec->mutex;
925  pool = codec->memory_pool;
926 
927  if (mutex) switch_mutex_lock(mutex);
928 
929  if (switch_core_codec_ready(codec)) {
931  } else {
932  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Codec is not initialized!\n");
933  if (mutex) switch_mutex_unlock(mutex);
935  }
936 
938  free_pool = 1;
939  }
940 
941  codec->implementation->destroy(codec);
942 
944 
945  if (mutex) switch_mutex_unlock(mutex);
946 
947  if (free_pool) {
949  }
950 
951  memset(codec, 0, sizeof(*codec));
952 
953  return SWITCH_STATUS_SUCCESS;
954 }
955 
956 /* For Emacs:
957  * Local Variables:
958  * mode:c
959  * indent-tabs-mode:t
960  * tab-width:4
961  * c-basic-offset:4
962  * End:
963  * For VIM:
964  * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
965  */
switch_status_t switch_core_codec_decode_video(switch_codec_t *codec, switch_frame_t *frame)
Decode video data using a codec handle.
switch_core_session_t * session
#define switch_event_fire(event)
Fire an event filling in most of the arguements with obvious values.
Definition: switch_event.h:413
#define switch_core_new_memory_pool(p)
Create a new sub memory pool from the core&#39;s master pool.
Definition: switch_core.h:633
switch_status_t switch_thread_rwlock_unlock(switch_thread_rwlock_t *rwlock)
Definition: switch_apr.c:286
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)
switch_thread_rwlock_t * bug_rwlock
#define switch_set_flag(obj, flag)
Set a flag on an arbitrary object.
Definition: switch_utils.h:700
#define SWITCH_CHANNEL_LOG
switch_core_codec_destroy_func_t destroy
switch_mutex_t * codec_write_mutex
void switch_core_session_unset_write_codec(switch_core_session_t *session)
switch_frame_t enc_read_frame
switch_mutex_t * codec_read_mutex
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:733
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)
switch_codec_t * video_read_codec
#define switch_core_destroy_memory_pool(p)
Returns a subpool back to the main pool.
Definition: switch_core.h:642
switch_memory_pool_t * pool
switch_codec_t * read_codec
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_t * real_read_codec
switch_codec_implementation_t * implementations
void * switch_core_memory_pool_get_data(switch_memory_pool_t *pool, const char *key)
switch_codec_implementation_t video_read_impl
switch_codec_t * video_write_codec
switch_status_t switch_core_session_get_real_read_impl(switch_core_session_t *session, switch_codec_implementation_t *impp)
switch_codec_implementation_t video_write_impl
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_core_codec_video_decode_func_t decode_video
switch_codec_implementation_t read_impl
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_codec_t * codec
Definition: switch_frame.h:56
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:314
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:313
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:724
switch_codec_implementation_t write_impl
#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:260
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_codec_implementation_t real_read_impl
switch_channel_t * channel
uint32_t datalen
Definition: switch_frame.h:68
switch_core_codec_decode_func_t decode
switch_codec_interface_t * codec_interface
uint32_t packetlen
Definition: switch_frame.h:62
switch_frame_flag_t flags
Definition: switch_frame.h:85
switch_status_t switch_mutex_lock(switch_mutex_t *lock)
Definition: switch_apr.c:308
switch_status_t switch_core_session_set_video_read_impl(switch_core_session_t *session, const switch_codec_implementation_t *impp)
switch_memory_pool_t * memory_pool
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.
switch_codec_t * write_codec
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:293
An abstraction of a data frame.
Definition: switch_frame.h:54
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:1693
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&#39;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 bug_codec
struct fspr_thread_mutex_t switch_mutex_t
Definition: switch_apr.h:314
switch_frame_t raw_read_frame
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)
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:384
#define SWITCH_DECLARE(type)
switch_frame_t enc_write_frame
#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
switch_core_codec_encode_func_t encode
#define switch_test_flag(obj, flag)
Test for the existance of a flag on an arbitary object.
Definition: switch_utils.h:693
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_mutex_t * mutex
struct fspr_pool_t switch_memory_pool_t
switch_codec_t * real_write_codec
switch_core_codec_video_encode_func_t encode_video
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)
switch_frame_t raw_write_frame
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_core_codec_control_func_t codec_control
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)