From Guillermo Ruiz Camauer, 7 Years ago, written in C.
- view diff
Embed
  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.  * Mathieu Rene <mrene@avgs.ca>
  27.  *
  28.  * fs_encode.c -- Encode a native file
  29.  *
  30.  */
  31.  
  32. #ifndef _XOPEN_SOURCE
  33. #define _XOPEN_SOURCE 600
  34. #endif
  35.  
  36. #ifndef WIN32
  37. /*GRC: #include <linux/limits.h> */
  38. #ifdef HAVE_SETRLIMIT
  39. #include <sys/resource.h>
  40. #endif
  41. #endif
  42.  
  43. // C
  44. #include <dirent.h>
  45. //#include <stdio.h>
  46. // #include <strings.h>
  47. // C++
  48. //#include <string>
  49. // Freeswitch
  50. #include <switch.h>
  51.  
  52. /* Picky compiler */
  53. #ifdef __ICC
  54. #pragma warning (disable:167)
  55. #endif
  56.  
  57. #define PATH_MAX 4096
  58.  
  59.  
  60. int encode_wav_file(int DEBUG, const char* input, int channels, int rate, int ptime, switch_codec_t* pcmu_codec, switch_codec_t* g729_codec);
  61. int encode_chunk(int DEBUG,char* buf, size_t bufsize, size_t len, int rate, switch_codec_t* codec, switch_file_handle_t fh_output);
  62. void substring(const char [], char[], int, int);
  63.  
  64. static void cleanup_globals()
  65. {
  66.         switch_safe_free(SWITCH_GLOBAL_dirs.conf_dir);
  67.         switch_safe_free(SWITCH_GLOBAL_dirs.mod_dir);
  68.         switch_safe_free(SWITCH_GLOBAL_dirs.log_dir);
  69. }
  70.  
  71. int main(int argc, char *argv[])
  72. {
  73.         int i;
  74.         int r = 1;
  75.         switch_bool_t verbose = SWITCH_FALSE;
  76.         int DEBUG = 0;
  77.         const char* err = NULL;
  78.         int cmd_fail = 0;
  79.         const char *fmtp = "";
  80.         const char *input;
  81.         int ptime = 20;
  82.         int channels = 1;
  83.         int rate = 8000;
  84.         int bitrate = 0;
  85.         switch_memory_pool_t *pool = NULL;
  86.         switch_codec_t pcmu_codec = { 0 };
  87.         switch_codec_t g729_codec = { 0 };
  88.         DIR* dir = NULL;
  89.         struct dirent* ent = NULL;
  90.         const char* dot = NULL;
  91.         int num_converted = 0;
  92.         char filename[PATH_MAX];
  93.         const char* slash = "";
  94.         const char* loadable_modules[] = {"mod_dahdi_codec","mod_spandsp","mod_sndfile", "mod_native_file"};
  95.  
  96.         for (i = 1; i < argc; i++) {
  97.                 if (argv[i][0] == '-') {
  98.                         switch(argv[i][1]) {
  99.                                 case 'c':
  100.                                         i++;
  101.                                         if((SWITCH_GLOBAL_dirs.conf_dir = (char *) malloc(strlen(argv[i]) + 1)) == NULL) {
  102.                                                 return 255;
  103.                                         }
  104.                                         strcpy(SWITCH_GLOBAL_dirs.conf_dir, argv[i]);
  105.                                         break;
  106.                                 case 'k':
  107.                                         i++;
  108.                                         if((SWITCH_GLOBAL_dirs.log_dir = (char *) malloc(strlen(argv[i]) + 1)) == NULL) {
  109.                                                 return 255;
  110.                                         }
  111.                                         strcpy(SWITCH_GLOBAL_dirs.log_dir, argv[i]);
  112.                                         break;
  113.                                 case 'm':
  114.                                         i++;
  115.                                         if((SWITCH_GLOBAL_dirs.mod_dir = (char *) malloc(strlen(argv[i]) + 1)) == NULL) {
  116.                                                 return 255;
  117.                                         }
  118.                                         strcpy(SWITCH_GLOBAL_dirs.mod_dir, argv[i]);
  119.                                         break;
  120.                                 case 'f':
  121.                                         fmtp = argv[++i];
  122.                                         break;
  123.                                 case 'p':
  124.                                         ptime = atoi(argv[++i]);
  125.                                         break;
  126.                                 case 'r':
  127.                                         rate = atoi(argv[++i]);
  128.                                         break;
  129.                                 case 'b':
  130.                                         bitrate = atoi(argv[++i]);
  131.                                         break;
  132.                                 case 'v':
  133.                                         verbose = SWITCH_TRUE;
  134.                                         DEBUG = 1;
  135.                                         break;
  136.                                 default:
  137.                                         printf("Command line option not recognized: %s\n", argv[i]);
  138.                                         cmd_fail = 1;
  139.                         }
  140.                 } else {
  141.                         break;
  142.                 }
  143.         }
  144.         if (DEBUG)
  145.                 fprintf(stderr, "GRC: Parsed arguments\n");
  146.         if (argc - i < 1 || cmd_fail) {
  147.                 goto usage;
  148.         }
  149.        
  150.         input = argv[i++];
  151.         if (zstr(input)) {
  152.                 goto usage;
  153.         }
  154.        
  155.         if (switch_core_init(SCF_MINIMAL, verbose, &err) != SWITCH_STATUS_SUCCESS) {
  156.                 fprintf(stderr, "Cannot init core [%s]\n", err);
  157.                 goto end;
  158.         }
  159.     if (DEBUG){
  160.                 fprintf(stderr, "GRC: Inistialized Core\n");
  161.                 fprintf(stderr, "Mod dir=%s\n", SWITCH_GLOBAL_dirs.mod_dir);
  162.         }
  163.        
  164.         switch_loadable_module_init(SWITCH_FALSE);
  165.         switch_loadable_module_load_module((char*)"", (char*)"CORE_PCM_MODULE", SWITCH_TRUE, &err);
  166.         if (DEBUG) fprintf(stderr, "GRC: Inistialized CORE_PCM_MODULE: %s\n",err);
  167.         switch_loadable_module_load_module((char*)"", (char*)"CORE_SPEEX_MODULE", SWITCH_TRUE, &err);
  168.         if (DEBUG) fprintf(stderr, "GRC: Inistialized CORE_SPEEX_MODULE: %s\n",err);
  169.         switch_loadable_module_load_module((char*)"", (char*)"CORE_SOFTTIMER_MODULE", SWITCH_TRUE, &err);
  170.         if (DEBUG) fprintf(stderr, "GRC: Inistialized CORE_SOFTTIMER_MODULE: %s\n",err);
  171.        
  172.         if (DEBUG) fprintf(stderr, "GRC: Loadable modules: %d\n",(int)(sizeof(loadable_modules)/sizeof(loadable_modules[0])));
  173.  
  174.         for (i = 0; i < (int)(sizeof(loadable_modules)/sizeof(loadable_modules[0])); i++) {
  175.                 if (switch_loadable_module_load_module((char*) SWITCH_GLOBAL_dirs.mod_dir, (char*)loadable_modules[i], SWITCH_TRUE, &err) != SWITCH_STATUS_SUCCESS) {
  176.                         fprintf(stderr, "Cannot init %s [%s]\n", loadable_modules[i], err);
  177.                         goto end;
  178.                 }
  179.                 if (DEBUG) fprintf(stderr, "GRC: Inistialized Loadable module: %s -- %s\n",(char*)loadable_modules[i],err);
  180.         }
  181.         if (DEBUG) fprintf(stderr, "GRC: Inistialized Loadable modules: %s\n",err);
  182.        
  183.         switch_core_new_memory_pool(&pool);
  184.         if (DEBUG) fprintf(stderr, "GRC: Allocated memory pool\n");
  185.        
  186.         if (input[strlen(input)-1] != '/') {
  187.                 slash = "/";
  188.         }
  189.         if (DEBUG) {
  190.                 fprintf(stderr, "GRC: Slash: %s\n",slash);
  191.                 fprintf(stderr, "GRC: Input: %s\n",input);
  192.                 fprintf(stderr, "About to initialize PCMU codec for PCMU@%dh@%di  Channels %d   Bitrate %d\n", rate, ptime, channels, bitrate);
  193.         }
  194.        
  195.         i=switch_core_codec_init_with_bitrate(&pcmu_codec, "PCMU", NULL,fmtp,rate, ptime, channels, bitrate,(uint32_t)SWITCH_CODEC_FLAG_ENCODE, NULL,pool);
  196.                                
  197.                                 /* switch_codec_t*, const char*, const char*, uint32_t, int, int, uint32_t, uint32_t, const switch_codec_settings_t*, switch_memory_pool_t**/
  198.                                
  199.         if (DEBUG) fprintf(stderr, "i:%d\n", i);       
  200.         if (i != SWITCH_STATUS_SUCCESS) {
  201.                 fprintf(stderr, "Couldn't initialize codec for PCMU@%dh@%di\n", rate, ptime);
  202.                 goto end;
  203.         }
  204.         if (DEBUG) fprintf(stderr, "GRC: Inistialized PCMU\n");
  205.         i=0;
  206.        
  207.         if (DEBUG) fprintf(stderr, "About to initialize G729 codec for G729@%dh@%di  Channels %d   Bitrate %d\n", rate, ptime, channels, bitrate);
  208.        
  209.         i = switch_core_codec_init_with_bitrate(&g729_codec, "G729", NULL, fmtp, rate, ptime, channels, bitrate,
  210.                                 SWITCH_CODEC_FLAG_ENCODE, NULL, pool);
  211.         if (DEBUG) fprintf(stderr, "i:%d\n", i);
  212.         if (i != SWITCH_STATUS_SUCCESS) {
  213.                 fprintf(stderr, "Couldn't initialize codec for G729@%dh@%di\n", rate, ptime);
  214.                 goto end;
  215.         }
  216.         if (DEBUG) fprintf(stderr, "GRC: Inistialized G.729\n");
  217.        
  218.  
  219.        
  220.         if ((dir = opendir(input)) != NULL) {
  221.                 while ((ent = readdir(dir)) != NULL) {
  222.                         if (ent->d_type == 8) {   //DT_REG
  223.                                 if ((dot = strrchr(ent->d_name, '.')) != NULL && strcasecmp(dot, ".WAV") == 0) {
  224.                                         sprintf(filename, "%s%s%s", input, slash, ent->d_name);
  225.                                         if (DEBUG) printf("Converting %s\n", filename);
  226.                                         if (encode_wav_file(DEBUG, filename, channels, rate, ptime, &pcmu_codec, &g729_codec)) {
  227.                                                 num_converted++;
  228.                                         } else {
  229.                                                 fprintf(stderr, "Error converting %s\n", ent->d_name);
  230.                                                 goto end;
  231.                                         }
  232.                                 }
  233.                         }
  234.                 }
  235.         } else {
  236.                 fprintf(stderr, "Couldn't open directory %s\n", input);
  237.                 goto end;
  238.         }
  239.  
  240.         if (DEBUG) fprintf(stdout, "Done converting %d file(s).\n", num_converted);
  241.         r = 0;
  242.  
  243. end:
  244.         if (dir) {
  245.                 closedir (dir);
  246.         }
  247.  
  248.         switch_core_codec_destroy(&pcmu_codec);
  249.         switch_core_codec_destroy(&g729_codec);
  250.  
  251.         if (pool) {
  252.                 switch_core_destroy_memory_pool(&pool);
  253.         }
  254.  
  255.         cleanup_globals();
  256.         return r;
  257.  
  258. usage:
  259.         printf("Usage: %s [options] dir\n\n", argv[0]);
  260.         printf("dir: path to directory containing .WAV files to convert\n");
  261.         printf("\t\t -c path\t\t Path to the FS configurations.\n");
  262.         printf("\t\t -k path\t\t Path to the FS log directory\n");
  263.         printf("\t\t -m path\t\t Path to the modules.\n");
  264.         printf("\t\t -f format\t\t fmtp to pass to the codec\n");
  265.         printf("\t\t -p ptime\t\t ptime to use while encoding\n");
  266.         printf("\t\t -r rate\t\t sampling rate\n");
  267.         printf("\t\t -b bitrate\t\t codec bitrate (if supported)\n");
  268.         printf("\t\t -v\t\t\t verbose\n");
  269.  
  270.         cleanup_globals();
  271.         return 1;
  272. }
  273.  
  274. void substring(const char s[], char sub[], int p, int l) {
  275.    int c = 0;
  276.  
  277.    while (c < l) {
  278.       sub[c] = s[p+c-1];
  279.       c++;
  280.    }
  281.    sub[c] = '\0';
  282. }
  283.  
  284. int encode_wav_file(int DEBUG,const char* input, int channels, int rate, int ptime, switch_codec_t* pcmu_codec, switch_codec_t* g729_codec)
  285. {
  286.         //using namespace std;
  287.  
  288.         int pos = 0;
  289.         char* charpos;
  290.         int r = 1;
  291.         switch_file_handle_t fh_wav = { 0 };
  292.         switch_file_handle_t fh_pcmu = { 0 };
  293.         switch_file_handle_t fh_g729 = { 0 };
  294.         char buf[2048];
  295.         char basename[PATH_MAX];
  296.         char pcmu_output[PATH_MAX];
  297.         char g729_output[PATH_MAX];
  298.        
  299.         switch_size_t len = (rate*ptime)/1000;
  300.         int blocksize = len;
  301.        
  302.         switch_assert(sizeof(buf) >= len * 2);
  303.  
  304.         //string tmp = input;
  305.         //size_t pos = tmp.find_last_of('.');
  306.         charpos = strrchr(input,'.');
  307.         if (charpos == NULL) {
  308.                 fprintf(stderr, "Missing file extension in %s\n", input);
  309.                 return 0;
  310.         }
  311.        
  312.         //string basename = tmp.substr(0, pos);
  313.         //string pcmu_output = basename + ".PCMU";
  314.         //string g729_output = basename + ".G729";
  315.        
  316.         pos = charpos - input;
  317.         if (DEBUG) fprintf(stderr, "encode_wav_file:pos: %d\n", pos);
  318.         //substring(input,basename,0,pos);
  319.         strncpy(basename,input,pos);
  320.         basename[pos]='\0';
  321.  
  322.         sprintf(pcmu_output,"%s.PCMU",basename);
  323.         sprintf(g729_output,"%s.G729",basename);
  324.        
  325.         if (DEBUG){
  326.                 fprintf(stderr, "encode_wav_file:input: %s\n", input);
  327.                 fprintf(stderr, "encode_wav_file:basename: %s\n", basename);
  328.                 fprintf(stderr, "encode_wav_file:PCMU %s\n", pcmu_output);
  329.                 fprintf(stderr, "encode_wav_file:G729 %s\n", g729_output);
  330.         }
  331.        
  332.         if (switch_core_file_open(&fh_wav, input, channels, rate,
  333.                                 SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) {
  334.                 fprintf(stderr, "Couldn't open %s\n", input);
  335.                 goto end;
  336.         }
  337.  
  338.         if (switch_core_file_open(&fh_pcmu, pcmu_output, channels, pcmu_codec->implementation->actual_samples_per_second,
  339.                                 SWITCH_FILE_FLAG_WRITE | SWITCH_FILE_NATIVE, NULL) != SWITCH_STATUS_SUCCESS) {
  340.                 fprintf(stderr, "Couldn't open %s\n", pcmu_output);
  341.                 goto end;      
  342.         }
  343.  
  344.         if (switch_core_file_open(&fh_g729, g729_output, channels, g729_codec->implementation->actual_samples_per_second,
  345.                                 SWITCH_FILE_FLAG_WRITE | SWITCH_FILE_NATIVE, NULL) != SWITCH_STATUS_SUCCESS) {
  346.                 fprintf(stderr, "Couldn't open %s\n", g729_output);
  347.                 goto end;      
  348.         }
  349.  
  350.         if (DEBUG) fprintf(stderr, "encode_wav_file:blocksize %d, rate %d\n", blocksize, rate);
  351.         while (switch_core_file_read(&fh_wav, buf, &len) == SWITCH_STATUS_SUCCESS) {
  352.                 if (!encode_chunk(DEBUG,(char*)buf, sizeof(buf), len, rate, pcmu_codec, fh_pcmu) ||
  353.                         !encode_chunk(DEBUG,(char*)buf, sizeof(buf), len, rate, g729_codec, fh_g729)) {
  354.                         goto end;
  355.                 }
  356.                
  357.                 len = blocksize;
  358.         }
  359.  
  360.         r = 1;
  361.  
  362. end:
  363.         if (fh_wav.file_interface) {
  364.                 switch_core_file_close(&fh_wav);
  365.         }
  366.  
  367.         if (fh_pcmu.file_interface) {
  368.                 switch_core_file_close(&fh_pcmu);
  369.         }
  370.        
  371.         if (fh_g729.file_interface) {
  372.                 switch_core_file_close(&fh_g729);
  373.         }
  374.  
  375.         return r;
  376. }
  377.  
  378. int encode_chunk(int DEBUG,char* buf, size_t bufsize, size_t len, int rate, switch_codec_t* codec, switch_file_handle_t fh_output) {
  379.         char encode_buf[2048];
  380.         uint32_t encoded_len = bufsize;
  381.         uint32_t encoded_rate = rate;
  382.         unsigned int flags = 0;
  383.  
  384.         if (switch_core_codec_encode(codec, NULL, buf, len*2, rate, encode_buf, &encoded_len, &encoded_rate, &flags) != SWITCH_STATUS_SUCCESS) {
  385.                 fprintf(stderr, "Codec encoder error\n");
  386.                 return 0;
  387.         }
  388.        
  389.         len = encoded_len;
  390.         if (DEBUG) fprintf(stderr, "encode_chunk: len: %d\n",(int)len);
  391.         if (switch_core_file_write(&fh_output, encode_buf, &len) != SWITCH_STATUS_SUCCESS) {
  392.                 fprintf(stderr, "Write error\n");
  393.                 return 0;
  394.         }
  395.        
  396.         if (len != encoded_len) {
  397.                 printf("Short write: wrote %"SWITCH_SIZE_T_FMT"/%d bytes\n", len, encoded_len);
  398.                 return 0;
  399.         }
  400.  
  401.         return 1;
  402. }
  403.  
  404.  
  405.