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 {
64  do {
67  return;
68  }
69 
71  }
72 
74  } while (1);
75 }
76 
78 {
81 }
82 
84 {
86 }
87 
89 {
91 }
92 
94 {
96 }
97 
99 {
101 }
102 
104 {
105  switch_mutex_t *mutex = NULL;
106 
108  if (session->write_codec) mutex = session->write_codec->mutex;
109  if (mutex) switch_mutex_lock(mutex);
110  session->real_write_codec = session->write_codec = NULL;
111  if (mutex) switch_mutex_unlock(mutex);
113 }
114 
116 {
117  switch_event_t *event;
119  char tmp[30];
121  int changed_read_codec = 0;
122 
124 
125  if (codec && (!codec->implementation || !switch_core_codec_ready(codec))) {
126  codec = NULL;
127  }
128 
129  if (codec) {
130  /* set real_read_codec and read_codec */
131  if (!session->real_read_codec) {
132  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Original read codec set to %s:%d\n",
134  session->read_codec = session->real_read_codec = codec;
135  changed_read_codec = 1;
136  if (codec->implementation) {
137  session->read_impl = *codec->implementation;
138  session->real_read_impl = *codec->implementation;
139  } else {
140  memset(&session->read_impl, 0, sizeof(session->read_impl));
141  }
142  } else { /* replace real_read_codec */
143  switch_codec_t *cur_codec;
144 
145  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Original read codec replaced with %s:%d\n",
146  switch_channel_get_name(session->channel), codec->implementation ? codec->implementation->iananame : "undefined", codec->implementation ? codec->implementation->ianacode : -1);
147  /* Set real_read_codec to front of the list of read_codecs */
148  cur_codec = session->read_codec;
149  while (cur_codec != NULL) {
150  if (cur_codec->next == session->real_read_codec) {
151  cur_codec->next = codec;
152  break;
153  }
154 
155  cur_codec = cur_codec->next;
156  }
157 
158  session->real_read_codec = codec;
159  session->real_read_impl = *codec->implementation;
160 
161  /* set read_codec with real_read_codec if it no longer is ready */
162  if (!switch_core_codec_ready(session->read_codec)) {
163  session->read_codec = codec;
164  changed_read_codec = 1;
165  if (codec->implementation) {
166  session->read_impl = *codec->implementation;
167  session->real_read_impl = *codec->implementation;
168  } else {
169  memset(&session->read_impl, 0, sizeof(session->read_impl));
170  }
171  }
172  }
173 
174  /* force media bugs to copy the read codec from the next frame */
176  if (switch_core_codec_ready(&session->bug_codec)) {
177  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Destroying BUG Codec %s:%d\n",
180  }
181 
183  } else {
184  status = SWITCH_STATUS_FALSE;
185  goto end;
186  }
187 
188  if (changed_read_codec && session->read_codec && session->read_impl.decoded_bytes_per_packet) {
190  switch_channel_event_set_data(session->channel, event);
191  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "channel-read-codec-name", session->read_impl.iananame);
192  switch_event_add_header(event, SWITCH_STACK_BOTTOM, "channel-read-codec-rate", "%d", session->read_impl.actual_samples_per_second);
193  switch_event_add_header(event, SWITCH_STACK_BOTTOM, "channel-read-codec-bit-rate", "%d", session->read_impl.bits_per_second);
195  switch_event_add_header(event, SWITCH_STACK_BOTTOM, "channel-reported-read-codec-rate", "%d", session->read_impl.samples_per_second);
196  }
197 
198  switch_event_fire(&event);
199  }
200 
201  switch_channel_set_variable(channel, "read_codec", session->read_impl.iananame);
202  switch_channel_set_variable(channel, "original_read_codec", session->read_impl.iananame);
203  switch_snprintf(tmp, sizeof(tmp), "%d", session->read_impl.actual_samples_per_second);
204  switch_channel_set_variable(channel, "read_rate", tmp);
205  switch_channel_set_variable(channel, "original_read_rate", tmp);
206 
207  session->raw_read_frame.codec = session->read_codec;
208  session->raw_write_frame.codec = session->read_codec;
209  session->enc_read_frame.codec = session->read_codec;
210  session->enc_write_frame.codec = session->read_codec;
211  }
212 
213  end:
214 
215  if (session->read_codec) {
217  }
218 
220 
221  return status;
222 }
223 
225 {
226  switch_event_t *event;
228  char tmp[30];
230 
232 
233  if (codec && (!codec->implementation || !switch_core_codec_ready(codec))) {
234  codec = NULL;
235  }
236 
237  if (codec) {
238  if (!session->real_read_codec) {
239  session->read_codec = session->real_read_codec = codec;
240  if (codec->implementation) {
241  session->read_impl = *codec->implementation;
242  session->real_read_impl = *codec->implementation;
243  } else {
244  memset(&session->read_impl, 0, sizeof(session->read_impl));
245  }
246  } else {
247  if (codec == session->read_codec) {
248  goto end;
249  }
250  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Push codec %s:%d\n",
251  switch_channel_get_name(session->channel), codec->implementation ? codec->implementation->iananame : "undefined", codec->implementation ? codec->implementation->ianacode : -1);
252  codec->next = session->read_codec;
253  session->read_codec = codec;
254  if (codec->implementation) {
255  session->read_impl = *codec->implementation;
256  } else {
257  memset(&session->read_impl, 0, sizeof(session->read_impl));
258  }
259  }
260  } else {
261  if (session->read_codec == session->real_read_codec) {
262  goto end;
263  }
264 
265  if (session->read_codec->next && switch_core_codec_ready(session->read_codec->next)) {
266  switch_codec_t *old = session->read_codec;
267  session->read_codec = session->read_codec->next;
268  if (session->read_codec->implementation) {
269  session->read_impl = *session->read_codec->implementation;
270  } else {
271  memset(&session->read_impl, 0, sizeof(session->read_impl));
272  }
273  old->next = NULL;
274 
275  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Restore previous codec %s:%d.\n",
277  session->read_impl.iananame ? session->read_impl.iananame : "N/A", session->read_impl.ianacode);
278 
279 
280  } else if (session->real_read_codec) {
281  session->read_codec = session->real_read_codec;
282  if (session->real_read_codec->implementation) {
283  session->read_impl = *session->real_read_codec->implementation;
284  } else {
285  memset(&session->read_impl, 0, sizeof(session->read_impl));
286  }
287  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Restore original codec.\n");
288  } else {
289  status = SWITCH_STATUS_FALSE;
290  goto end;
291  }
292  }
293 
294  if (!session->read_codec) {
295  status = SWITCH_STATUS_FALSE;
296  goto end;
297  }
298 
299  if (session->read_impl.decoded_bytes_per_packet) {
301  switch_channel_event_set_data(session->channel, event);
302  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "channel-read-codec-name", session->read_impl.iananame);
303  switch_event_add_header(event, SWITCH_STACK_BOTTOM, "channel-read-codec-rate", "%d", session->read_impl.actual_samples_per_second);
304  switch_event_add_header(event, SWITCH_STACK_BOTTOM, "channel-read-codec-bit-rate", "%d", session->read_impl.bits_per_second);
306  switch_event_add_header(event, SWITCH_STACK_BOTTOM, "channel-reported-read-codec-rate", "%d", session->read_impl.samples_per_second);
307  }
308  switch_event_fire(&event);
309  }
310 
311  switch_channel_set_variable(channel, "read_codec", session->read_impl.iananame);
312  switch_snprintf(tmp, sizeof(tmp), "%d", session->read_impl.actual_samples_per_second);
313  switch_channel_set_variable(channel, "read_rate", tmp);
314 
315  session->raw_read_frame.codec = session->read_codec;
316  session->raw_write_frame.codec = session->read_codec;
317  session->enc_read_frame.codec = session->read_codec;
318  session->enc_write_frame.codec = session->read_codec;
319  }
320 
321  end:
322 
323  if (session->read_codec) {
325  }
326 
328  return status;
329 
330 }
331 
333 {
334  switch_codec_t *codec;
335  codec = session->read_codec;
336  return codec;
337 }
338 
340 {
341  switch_codec_t *codec;
342  codec = session->real_read_codec ? session->real_read_codec : session->read_codec;
343  return codec;
344 }
345 
347 {
348  if (session->read_impl.codec_id) {
349  *impp = session->read_impl;
350  return SWITCH_STATUS_SUCCESS;
351  }
352 
353  memset(impp, 0, sizeof(*impp));
354  impp->number_of_channels = 1;
355  return SWITCH_STATUS_FALSE;
356 }
357 
359 {
360  if (session->real_read_impl.codec_id) {
361  *impp = session->real_read_impl;
362  return SWITCH_STATUS_SUCCESS;
363  }
364 
365  return switch_core_session_get_read_impl(session, impp);
366 }
367 
369 {
370  if (session->write_impl.codec_id) {
371  *impp = session->write_impl;
372  return SWITCH_STATUS_SUCCESS;
373  }
374 
375  memset(impp, 0, sizeof(*impp));
376  impp->number_of_channels = 1;
377  return SWITCH_STATUS_FALSE;
378 }
379 
381 {
382  if (session->video_read_impl.codec_id) {
383  *impp = session->video_read_impl;
384  return SWITCH_STATUS_SUCCESS;
385  }
386 
387  memset(impp, 0, sizeof(*impp));
388  impp->number_of_channels = 1;
389  return SWITCH_STATUS_FALSE;
390 }
391 
393 {
394  if (session->video_write_impl.codec_id) {
395  *impp = session->video_write_impl;
396  return SWITCH_STATUS_SUCCESS;
397  }
398 
399  memset(impp, 0, sizeof(*impp));
400  impp->number_of_channels = 1;
401  return SWITCH_STATUS_FALSE;
402 }
403 
404 
406 {
407  session->read_impl = *impp;
408  return SWITCH_STATUS_SUCCESS;
409 }
410 
412 {
413  session->write_impl = *impp;
414  return SWITCH_STATUS_SUCCESS;
415 }
416 
418 {
419  session->video_read_impl = *impp;
420  return SWITCH_STATUS_SUCCESS;
421 }
422 
424 {
425  session->video_write_impl = *impp;
426  return SWITCH_STATUS_SUCCESS;
427 }
428 
429 
431 {
432  switch_event_t *event;
434  char tmp[30];
436 
438 
439  if (!codec || !codec->implementation || !switch_core_codec_ready(codec)) {
440  if (session->real_write_codec) {
441  session->write_codec = session->real_write_codec;
442  session->write_impl = *session->real_write_codec->implementation;
443  session->real_write_codec = NULL;
444  } else {
445  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot set NULL codec!\n");
446  status = SWITCH_STATUS_FALSE;
447  goto end;
448  }
449  } else if (session->write_codec) {
450  if (session->real_write_codec) {
451  if (codec == session->real_write_codec) {
452  session->write_codec = codec;
453  session->write_impl = *codec->implementation;
454  session->real_write_codec = NULL;
455  } else {
456  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot double-set codec!\n");
457  status = SWITCH_STATUS_FALSE;
458  goto end;
459  }
460  } else {
461  session->real_write_codec = session->write_codec;
462  session->write_codec = codec;
463  session->write_impl = *codec->implementation;
464  }
465  } else {
466  session->write_codec = codec;
467  session->write_impl = *codec->implementation;
468  }
469 
470  if (codec && session->write_impl.codec_id) {
472  switch_channel_event_set_data(session->channel, event);
473  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-Write-Codec-Name", session->write_impl.iananame);
474  switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Channel-Write-Codec-Rate", "%d", session->write_impl.actual_samples_per_second);
475  switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Channel-Write-codec-bit-rate", "%d", session->write_impl.bits_per_second);
477  switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Channel-Reported-Write-Codec-Rate", "%d",
479  }
480  switch_event_fire(&event);
481  }
482 
483  switch_channel_set_variable(channel, "write_codec", session->write_impl.iananame);
484  switch_snprintf(tmp, sizeof(tmp), "%d", session->write_impl.actual_samples_per_second);
485  switch_channel_set_variable(channel, "write_rate", tmp);
486  }
487 
488  end:
490 
491  return status;
492 }
493 
494 
496 {
497  switch_codec_t *codec;
498  codec = session->write_codec;
499 
500  return codec;
501 }
502 
504 {
505  switch_codec_t *codec;
506  codec = session->real_write_codec ? session->real_write_codec : session->write_codec;
507 
508  return codec;
509 }
510 
511 
512 
514 {
515  switch_event_t *event;
517  char tmp[30];
519 
520  if (!codec || !codec->implementation || !switch_core_codec_ready(codec)) {
521  if (session->video_read_codec) {
522  session->video_read_codec = NULL;
523  status = SWITCH_STATUS_SUCCESS;
524  goto end;
525  }
526  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot set NULL codec!\n");
527  status = SWITCH_STATUS_FALSE;
528  goto end;
529  }
530 
532  switch_channel_event_set_data(session->channel, event);
533  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "channel-video-read-codec-name", codec->implementation->iananame);
534  switch_event_add_header(event, SWITCH_STACK_BOTTOM, "channel-video-read-codec-rate", "%d", codec->implementation->actual_samples_per_second);
535  switch_event_fire(&event);
536  }
537 
538  switch_channel_set_variable(channel, "video_read_codec", codec->implementation->iananame);
539  switch_snprintf(tmp, sizeof(tmp), "%d", codec->implementation->actual_samples_per_second);
540  switch_channel_set_variable(channel, "video_read_rate", tmp);
541 
542  session->video_read_codec = codec;
543  if (codec->implementation) {
544  session->video_read_impl = *codec->implementation;
545  } else {
546  memset(&session->video_read_impl, 0, sizeof(session->video_read_impl));
547  }
548  end:
549 
550  return status;
551 }
552 
554 {
555  switch_codec_t *codec;
556  codec = session->video_read_codec;
557 
558  return codec;
559 
560 }
561 
563 {
564  switch_event_t *event;
566  char tmp[30];
568  if (!codec || !codec->implementation || !switch_core_codec_ready(codec)) {
569  if (session->video_write_codec) {
570  session->video_write_codec = NULL;
571  status = SWITCH_STATUS_SUCCESS;
572  goto end;
573  }
574  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot set NULL codec!\n");
575  status = SWITCH_STATUS_FALSE;
576  goto end;
577  }
578 
580  switch_channel_event_set_data(session->channel, event);
581  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "channel-video-write-codec-name", codec->implementation->iananame);
582  switch_event_add_header(event, SWITCH_STACK_BOTTOM, "channel-video-write-codec-rate", "%d", codec->implementation->actual_samples_per_second);
583  switch_event_fire(&event);
584  }
585 
586  switch_channel_set_variable(channel, "video_write_codec", codec->implementation->iananame);
587  switch_snprintf(tmp, sizeof(tmp), "%d", codec->implementation->actual_samples_per_second);
588  switch_channel_set_variable(channel, "video_write_rate", tmp);
589 
590  session->video_write_codec = codec;
591  session->video_write_impl = *codec->implementation;
592 
593  end:
594 
595  return status;
596 }
597 
599 {
600  switch_codec_t *codec;
601  codec = session->video_write_codec;
602 
603  return codec;
604 
605 }
606 
607 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)
608 {
609  switch_codec_interface_t *codec_interface;
611 
612  if (zstr(codec_name) || zstr(fmtp) || !codec_fmtp) {
613  return SWITCH_STATUS_FALSE;
614  }
615 
616  memset(codec_fmtp, 0, sizeof(*codec_fmtp));
617 
618  if ((codec_interface = switch_loadable_module_get_codec_interface(codec_name, NULL))) {
619  if (codec_interface->parse_fmtp) {
620  codec_fmtp->actual_samples_per_second = rate;
621  status = codec_interface->parse_fmtp(fmtp, codec_fmtp);
622  }
623 
624  UNPROTECT_INTERFACE(codec_interface);
625  }
626 
627  return status;
628 }
629 
631 {
632  switch_assert(codec != NULL);
633 
634  codec->implementation->destroy(codec);
635  codec->implementation->init(codec, codec->flags, NULL);
636 
637  return SWITCH_STATUS_SUCCESS;
638 }
639 
640 
642  const switch_codec_settings_t *codec_settings, switch_memory_pool_t *pool)
643 {
644  uint32_t codec_rate;
645  switch_assert(codec != NULL);
646  switch_assert(new_codec != NULL);
647 
648  codec_rate = !strcasecmp(codec->implementation->iananame, "g722")
650 
651  return switch_core_codec_init(new_codec,
652  codec->implementation->iananame,
653  codec->implementation->modname,
654  codec->fmtp_in,
655  codec_rate,
658  codec->flags,
659  codec_settings,
660  pool);
661 
662 }
663 
664 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,
665  uint32_t rate, int ms, int channels, uint32_t bitrate, uint32_t flags,
666  const switch_codec_settings_t *codec_settings, switch_memory_pool_t *pool)
667 {
668  switch_codec_interface_t *codec_interface;
669  const switch_codec_implementation_t *iptr, *implementation = NULL;
670 
671  switch_assert(codec != NULL);
672  switch_assert(codec_name != NULL);
673 
674  memset(codec, 0, sizeof(*codec));
675 
676  if (pool) {
677  codec->session = switch_core_memory_pool_get_data(pool, "__session");
678  }
679 
680  if (strchr(codec_name, '.')) {
681  char *p = NULL;
682  codec_name = switch_core_strdup(pool, codec_name);
683  if ((p = strchr(codec_name, '.'))) {
684  *p++ = '\0';
685  modname = codec_name;
686  codec_name = p;
687  }
688  }
689 
690  if ((codec_interface = switch_loadable_module_get_codec_interface(codec_name, modname)) == 0) {
691  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid codec %s!\n", codec_name);
692  return SWITCH_STATUS_GENERR;
693  }
694 
695  if (!strncasecmp(codec_name, "PROXY", 5)) {
696  for (iptr = codec_interface->implementations; iptr; iptr = iptr->next) {
697  if (!channels || channels == iptr->number_of_channels) {
698  implementation = iptr;
699  break;
700  }
701  }
702 
703  goto found;
704  }
705 
706  /* If no specific codec interval is requested opt for 20ms above all else because lots of stuff assumes it */
707  if (!ms) {
708  for (iptr = codec_interface->implementations; iptr; iptr = iptr->next) {
709  uint32_t crate = !strcasecmp(codec_name, "g722") ? iptr->samples_per_second : iptr->actual_samples_per_second;
710  if ((!rate || rate == crate) && (!bitrate || bitrate == (uint32_t)iptr->bits_per_second) &&
711  (20 == (iptr->microseconds_per_packet / 1000)) && (!channels || channels == iptr->number_of_channels)) {
712  implementation = iptr;
713  goto found;
714  }
715  }
716  }
717 
718  /* Either looking for a specific interval or there was no interval specified and there wasn't one @20ms available */
719  for (iptr = codec_interface->implementations; iptr; iptr = iptr->next) {
720  uint32_t crate = !strcasecmp(codec_name, "g722") ? iptr->samples_per_second : iptr->actual_samples_per_second;
721  if ((!rate || rate == crate) && (!bitrate || bitrate == (uint32_t)iptr->bits_per_second) &&
722  (!ms || ms == (iptr->microseconds_per_packet / 1000)) && (!channels || channels == iptr->number_of_channels)) {
723  implementation = iptr;
724  break;
725  }
726  }
727 
728  found:
729 
730  if (implementation) {
731  switch_status_t status;
732  codec->codec_interface = codec_interface;
733  codec->implementation = implementation;
734  codec->flags = flags;
735 
736  if (pool) {
737  codec->memory_pool = pool;
738  } else {
740  return status;
741  }
743  }
744 
745  if (fmtp) {
746  codec->fmtp_in = switch_core_strdup(codec->memory_pool, fmtp);
747  }
748 
749  implementation->init(codec, flags, codec_settings);
752  return SWITCH_STATUS_SUCCESS;
753  } else {
754  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Codec %s Exists but not at the desired implementation. %dhz %dms %dch\n",
755  codec_name, rate, ms, channels);
756 
757  }
758 
759  UNPROTECT_INTERFACE(codec_interface);
760 
761  return SWITCH_STATUS_NOTIMPL;
762 }
763 
765  switch_codec_t *other_codec,
766  void *decoded_data,
767  uint32_t decoded_data_len,
768  uint32_t decoded_rate,
769  void *encoded_data, uint32_t *encoded_data_len, uint32_t *encoded_rate, unsigned int *flag)
770 {
771  switch_status_t status;
772 
773  switch_assert(codec != NULL);
774  switch_assert(encoded_data != NULL);
775  switch_assert(decoded_data != NULL);
776 
777  if (!codec->implementation || !switch_core_codec_ready(codec)) {
778  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Codec is not initialized!\n");
780  }
781 
783  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Codec encoder is not initialized!\n");
785  }
786 
787  if (codec->mutex) switch_mutex_lock(codec->mutex);
788  status = codec->implementation->encode(codec, other_codec, decoded_data, decoded_data_len,
789  decoded_rate, encoded_data, encoded_data_len, encoded_rate, flag);
790  if (codec->mutex) switch_mutex_unlock(codec->mutex);
791 
792  return status;
793 
794 }
795 
797  switch_codec_t *other_codec,
798  void *encoded_data,
799  uint32_t encoded_data_len,
800  uint32_t encoded_rate,
801  void *decoded_data, uint32_t *decoded_data_len, uint32_t *decoded_rate, unsigned int *flag)
802 {
803  switch_status_t status;
804 
805  switch_assert(codec != NULL);
806  switch_assert(encoded_data != NULL);
807  switch_assert(decoded_data != NULL);
808 
809  if (!codec->implementation || !switch_core_codec_ready(codec)) {
810  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Decode Codec is not initialized!\n");
812  }
813 
815  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Codec decoder is not initialized!\n");
817  }
818 
820  uint32_t frames = encoded_data_len / codec->implementation->encoded_bytes_per_packet / codec->implementation->number_of_channels;
821 
822  if (frames && codec->implementation->decoded_bytes_per_packet * frames > *decoded_data_len) {
823  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Buffer size sanity check failed! edl:%u ebpp:%u fr:%u ddl:%u\n",
824  encoded_data_len, codec->implementation->encoded_bytes_per_packet, frames, *decoded_data_len);
825  *decoded_data_len = codec->implementation->decoded_bytes_per_packet;
826  memset(decoded_data, 255, *decoded_data_len);
827  return SWITCH_STATUS_SUCCESS;
828  }
829  }
830 
831  if (codec->mutex) switch_mutex_lock(codec->mutex);
832  status = codec->implementation->decode(codec, other_codec, encoded_data, encoded_data_len, encoded_rate,
833  decoded_data, decoded_data_len, decoded_rate, flag);
834  if (codec->mutex) switch_mutex_unlock(codec->mutex);
835 
836  return status;
837 }
838 
840 {
842 
843  switch_assert(codec != NULL);
844 
845  if (!codec->implementation || !switch_core_codec_ready(codec)) {
846  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Codec is not initialized!\n");
848  }
849 
851  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Codec encoder is not initialized!\n");
853  }
854 
855  if (codec->mutex) switch_mutex_lock(codec->mutex);
856 
857  if (codec->implementation->encode_video) {
858  status = codec->implementation->encode_video(codec, frame);
859 
860  if (status == SWITCH_STATUS_MORE_DATA) {
861  frame->flags |= SFF_SAME_IMAGE;
862  } else {
863  frame->flags &= ~SFF_SAME_IMAGE;
864  }
865 
866  frame->packetlen = frame->datalen + 12;
867  }
868 
869  if (codec->mutex) switch_mutex_unlock(codec->mutex);
870 
871  return status;
872 
873 }
874 
876 {
878 
879  switch_assert(codec != NULL);
880  switch_assert(frame != NULL);
881 
882  if (!codec->implementation || !switch_core_codec_ready(codec)) {
883  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Decode Codec is not initialized!\n");
885  }
886 
888  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Codec decoder is not initialized!\n");
890  }
891 
892  if (codec->mutex) switch_mutex_lock(codec->mutex);
893 
894  if (codec->implementation->decode_video) {
895  status = codec->implementation->decode_video(codec, frame);
896  }
897  if (codec->mutex) switch_mutex_unlock(codec->mutex);
898 
899  return status;
900 }
901 
902 
906  void *cmd_data,
908  void *cmd_arg,
910  void **ret_data)
911 {
912 
914 
915 
916  switch_assert(codec != NULL);
917 
918 
919  if (!codec->implementation || !switch_core_codec_ready(codec)) {
920  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Codec is not initialized!\n");
921  abort();
922  //return SWITCH_STATUS_NOT_INITALIZED;
923  }
924 
925 
926  if (codec->mutex) switch_mutex_lock(codec->mutex);
927 
928  if (codec->implementation->codec_control) {
929  status = codec->implementation->codec_control(codec, cmd, ctype, cmd_data, atype, cmd_arg, rtype, ret_data);
930  }
931 
932  if (codec->mutex) switch_mutex_unlock(codec->mutex);
933 
934 
935  return status;
936 }
937 
939 {
940  switch_mutex_t *mutex = NULL;
941  switch_memory_pool_t *pool = NULL;
942  int free_pool = 0;
943 
944  switch_assert(codec != NULL);
945  mutex = codec->mutex;
946  pool = codec->memory_pool;
947 
948  if (mutex) switch_mutex_lock(mutex);
949 
950  if (switch_core_codec_ready(codec)) {
952  } else {
953  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Codec is not initialized!\n");
954  if (mutex) switch_mutex_unlock(mutex);
956  }
957 
959  free_pool = 1;
960  }
961 
962  codec->implementation->destroy(codec);
963 
965 
966  if (mutex) switch_mutex_unlock(mutex);
967 
968  if (free_pool) {
970  }
971 
972  memset(codec, 0, sizeof(*codec));
973 
974  return SWITCH_STATUS_SUCCESS;
975 }
976 
977 /* For Emacs:
978  * Local Variables:
979  * mode:c
980  * indent-tabs-mode:t
981  * tab-width:4
982  * c-basic-offset:4
983  * End:
984  * For VIM:
985  * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
986  */
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
void switch_core_codec_unlock_full(switch_core_session_t *session)
Unlock codec read mutex and codec write mutex.
#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_status_t switch_mutex_trylock(switch_mutex_t *lock)
Definition: switch_apr.c:318
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
void switch_core_codec_lock_full(switch_core_session_t *session)
Lock codec read mutex and codec write mutex using trylock in an infinite loop.
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)
void switch_cond_next(void)
Definition: switch_time.c:658
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)