Ticket #445: added codec encoding/decoding sample
git-svn-id: https://svn.pjsip.org/repos/pjproject/trunk@1678 74dad513-b988-da41-8d7b-12977e46ad98
This commit is contained in:
parent
7a17068dea
commit
06e62d76f6
|
@ -50,6 +50,7 @@ BINDIR = ..\bin\samples
|
|||
|
||||
SAMPLES = $(BINDIR)\confsample.exe \
|
||||
$(BINDIR)\confbench.exe \
|
||||
$(BINDIR)\encdec.exe \
|
||||
$(BINDIR)\level.exe \
|
||||
$(BINDIR)\pjsip-perf.exe \
|
||||
$(BINDIR)\playfile.exe \
|
||||
|
|
|
@ -14,6 +14,7 @@ OBJDIR := ./output/samples-$(TARGET_NAME)
|
|||
BINDIR := ../bin/samples
|
||||
|
||||
SAMPLES := confsample \
|
||||
encdec \
|
||||
level \
|
||||
pjsip-perf \
|
||||
playfile \
|
||||
|
|
|
@ -98,6 +98,10 @@ SOURCE=..\src\samples\confsample.c
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\src\samples\encdec.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\src\samples\footprint.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
|
|
@ -81,6 +81,10 @@
|
|||
RelativePath="..\src\samples\confsample.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\src\samples\encdec.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\src\samples\footprint.c"
|
||||
>
|
||||
|
|
|
@ -0,0 +1,245 @@
|
|||
/* $Id$ */
|
||||
/*
|
||||
* Copyright (C) 2003-2007 Benny Prijono <benny@prijono.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* \page page_pjmedia_samples_encdec_c Samples: Encoding and Decoding
|
||||
*
|
||||
* This sample shows how to use codec.
|
||||
*
|
||||
* This file is pjsip-apps/src/samples/encdec.c
|
||||
*
|
||||
* \includelineno encdec.c
|
||||
*/
|
||||
|
||||
#include <pjlib.h>
|
||||
#include <pjmedia.h>
|
||||
#include <pjmedia-codec.h>
|
||||
|
||||
#define THIS_FILE "encdec.c"
|
||||
|
||||
static const char *desc =
|
||||
" encdec \n"
|
||||
" \n"
|
||||
" PURPOSE: \n"
|
||||
" Encode input WAV with a codec, and decode the result to another WAV \n"
|
||||
"\n"
|
||||
"\n"
|
||||
" USAGE: \n"
|
||||
" encdec codec input.wav output.wav \n"
|
||||
"\n"
|
||||
"\n"
|
||||
" where:\n"
|
||||
" codec Set the codec name. \n"
|
||||
" input.wav Set the input WAV filename. \n"
|
||||
" output.wav Set the output WAV filename. \n"
|
||||
|
||||
"\n"
|
||||
;
|
||||
|
||||
#define HAS_G729_CODEC 0
|
||||
#if HAS_G729_CODEC
|
||||
#include "keystream_g729ab.h"
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
# define TRACE_(expr) PJ_LOG(4,expr)
|
||||
#else
|
||||
# define TRACE_(expr)
|
||||
#endif
|
||||
|
||||
|
||||
static void err(const char *op, pj_status_t status)
|
||||
{
|
||||
char errmsg[PJ_ERR_MSG_SIZE];
|
||||
pj_strerror(status, errmsg, sizeof(errmsg));
|
||||
PJ_LOG(3,("", "%s error: %s", op, errmsg));
|
||||
}
|
||||
|
||||
#define CHECK(op) do { \
|
||||
status = op; \
|
||||
if (status != PJ_SUCCESS) { \
|
||||
err(#op, status); \
|
||||
return status; \
|
||||
} \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
static pjmedia_endpt *mept;
|
||||
static unsigned file_msec_duration;
|
||||
|
||||
static pj_status_t enc_dec_test(const char *codec_id,
|
||||
const char *filein,
|
||||
const char *fileout)
|
||||
{
|
||||
pj_pool_t *pool;
|
||||
pjmedia_codec_mgr *cm;
|
||||
pjmedia_codec *codec;
|
||||
pjmedia_codec_info *pci;
|
||||
pjmedia_codec_param param;
|
||||
unsigned cnt, samples_per_frame;
|
||||
pj_str_t tmp;
|
||||
pjmedia_port *wavin, *wavout;
|
||||
pj_status_t status;
|
||||
|
||||
pool = pjmedia_endpt_create_pool(mept, "encdec", 1000, 1000);
|
||||
|
||||
cm = pjmedia_endpt_get_codec_mgr(mept);
|
||||
|
||||
cnt = 1;
|
||||
CHECK( pjmedia_codec_mgr_find_codecs_by_id(cm, pj_cstr(&tmp, codec_id),
|
||||
&cnt, &pci, NULL) );
|
||||
CHECK( pjmedia_codec_mgr_get_default_param(cm, pci, ¶m) );
|
||||
|
||||
samples_per_frame = param.info.clock_rate * param.info.frm_ptime / 1000;
|
||||
|
||||
/* Control VAD */
|
||||
param.setting.vad = 0;
|
||||
|
||||
/* Open wav for reading */
|
||||
CHECK( pjmedia_wav_player_port_create(pool, filein,
|
||||
param.info.frm_ptime,
|
||||
PJMEDIA_FILE_NO_LOOP, 0, &wavin) );
|
||||
|
||||
/* Open wav for writing */
|
||||
CHECK( pjmedia_wav_writer_port_create(pool, fileout,
|
||||
param.info.clock_rate,
|
||||
param.info.channel_cnt,
|
||||
samples_per_frame,
|
||||
16, 0, 0, &wavout) );
|
||||
|
||||
/* Alloc codec */
|
||||
CHECK( pjmedia_codec_mgr_alloc_codec(cm, pci, &codec) );
|
||||
CHECK( codec->op->init(codec, pool) );
|
||||
CHECK( codec->op->open(codec, ¶m) );
|
||||
|
||||
for (;;) {
|
||||
pjmedia_frame frm_pcm, frm_bit, out_frm, frames[4];
|
||||
pj_int16_t pcmbuf[320];
|
||||
pj_timestamp ts;
|
||||
pj_uint8_t bitstream[160];
|
||||
|
||||
frm_pcm.buf = (char*)pcmbuf;
|
||||
frm_pcm.size = samples_per_frame * 2;
|
||||
|
||||
/* Read from WAV */
|
||||
if (pjmedia_port_get_frame(wavin, &frm_pcm) != PJ_SUCCESS)
|
||||
break;
|
||||
if (frm_pcm.type != PJMEDIA_FRAME_TYPE_AUDIO)
|
||||
break;;
|
||||
|
||||
/* Encode */
|
||||
frm_bit.buf = bitstream;
|
||||
frm_bit.size = sizeof(bitstream);
|
||||
CHECK(codec->op->encode(codec, &frm_pcm, sizeof(bitstream), &frm_bit));
|
||||
|
||||
/* Parse the bitstream (not really necessary for this case
|
||||
* since we always decode 1 frame, but it's still good
|
||||
* for testing)
|
||||
*/
|
||||
ts.u64 = 0;
|
||||
cnt = PJ_ARRAY_SIZE(frames);
|
||||
CHECK( codec->op->parse(codec, bitstream, frm_bit.size, &ts, &cnt,
|
||||
frames) );
|
||||
CHECK( (cnt==1 ? PJ_SUCCESS : -1) );
|
||||
|
||||
/* Decode */
|
||||
out_frm.buf = (char*)pcmbuf;
|
||||
out_frm.size = sizeof(pcmbuf);
|
||||
CHECK( codec->op->decode(codec, &frames[0], sizeof(pcmbuf),
|
||||
&out_frm) );
|
||||
|
||||
/* Write to WAV */
|
||||
CHECK( pjmedia_port_put_frame(wavout, &out_frm) );
|
||||
|
||||
file_msec_duration += samples_per_frame * 1000 /
|
||||
param.info.clock_rate;
|
||||
|
||||
TRACE_((THIS_FILE, "Bytes read: %u, encode: %u, decode/write: %u",
|
||||
frm_pcm.size, frm_bit.size, out_frm.size));
|
||||
}
|
||||
|
||||
/* Close wavs */
|
||||
pjmedia_port_destroy(wavout);
|
||||
pjmedia_port_destroy(wavin);
|
||||
|
||||
/* Close codec */
|
||||
codec->op->close(codec);
|
||||
pjmedia_codec_mgr_dealloc_codec(cm, codec);
|
||||
|
||||
/* Release pool */
|
||||
pj_pool_release(pool);
|
||||
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
pj_caching_pool cp;
|
||||
pj_time_val t0, t1;
|
||||
pj_status_t status;
|
||||
|
||||
if (argc != 4) {
|
||||
puts(desc);
|
||||
return 1;
|
||||
}
|
||||
|
||||
CHECK( pj_init() );
|
||||
|
||||
pj_caching_pool_init(&cp, NULL, 0);
|
||||
|
||||
CHECK( pjmedia_endpt_create(&cp.factory, NULL, 1, &mept) );
|
||||
|
||||
/* Register all codecs */
|
||||
#if PJMEDIA_HAS_G711_CODEC
|
||||
CHECK( pjmedia_codec_g711_init(mept) );
|
||||
#endif
|
||||
#if PJMEDIA_HAS_GSM_CODEC
|
||||
CHECK( pjmedia_codec_gsm_init(mept) );
|
||||
#endif
|
||||
#if PJMEDIA_HAS_ILBC_CODEC
|
||||
CHECK( pjmedia_codec_ilbc_init(mept, 30) );
|
||||
#endif
|
||||
#if PJMEDIA_HAS_SPEEX_CODEC
|
||||
CHECK( pjmedia_codec_speex_init(mept, 0, 5, 5) );
|
||||
#endif
|
||||
#if HAS_G729_CODEC
|
||||
CHECK( keystream_g729ab_init(mept) );
|
||||
#endif
|
||||
|
||||
pj_gettimeofday(&t0);
|
||||
status = enc_dec_test(argv[1], argv[2], argv[3]);
|
||||
pj_gettimeofday(&t1);
|
||||
PJ_TIME_VAL_SUB(t1, t0);
|
||||
|
||||
pjmedia_endpt_destroy(mept);
|
||||
pj_caching_pool_destroy(&cp);
|
||||
pj_shutdown();
|
||||
|
||||
if (status == PJ_SUCCESS) {
|
||||
puts("");
|
||||
puts("Success");
|
||||
printf("Duration: %ds.%03d\n", file_msec_duration/1000,
|
||||
file_msec_duration%1000);
|
||||
printf("Time: %ds.%03d\n", t1.sec, t1.msec);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue