diff options
author | Nanang Izzuddin <nanang@teluu.com> | 2011-07-19 03:42:28 +0000 |
---|---|---|
committer | Nanang Izzuddin <nanang@teluu.com> | 2011-07-19 03:42:28 +0000 |
commit | cd283c8825c9a94400f27735acb1c9385e90ffc8 (patch) | |
tree | 56d5722310fa8957ce5d1ba7cbd137cf8802dcc7 /pjmedia/src/test | |
parent | ed8f8d08abba9040f769e922aa0c1adbde86fbbc (diff) |
Re #1326: Initial code integration from branch 2.0-dev to trunk as "2.0-pre-alpha-svn".
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@3664 74dad513-b988-da41-8d7b-12977e46ad98
Diffstat (limited to 'pjmedia/src/test')
-rw-r--r-- | pjmedia/src/test/codec_vectors.c | 26 | ||||
-rw-r--r-- | pjmedia/src/test/main.c | 10 | ||||
-rw-r--r-- | pjmedia/src/test/mips_test.c | 32 | ||||
-rw-r--r-- | pjmedia/src/test/test.c | 23 | ||||
-rw-r--r-- | pjmedia/src/test/test.h | 6 | ||||
-rw-r--r-- | pjmedia/src/test/vid_codec_test.c | 467 | ||||
-rw-r--r-- | pjmedia/src/test/vid_dev_test.c | 292 | ||||
-rw-r--r-- | pjmedia/src/test/vid_port_test.c | 241 |
8 files changed, 1065 insertions, 32 deletions
diff --git a/pjmedia/src/test/codec_vectors.c b/pjmedia/src/test/codec_vectors.c index b53850b6..5257b5a7 100644 --- a/pjmedia/src/test/codec_vectors.c +++ b/pjmedia/src/test/codec_vectors.c @@ -73,13 +73,13 @@ static int codec_test_encode(pjmedia_codec_mgr *mgr, codec_param.info.avg_bps = bitrate; codec_param.setting.vad = 0; - status = codec->op->init(codec, pool); + status = pjmedia_codec_init(codec, pool); if (status != PJ_SUCCESS) { rc = -60; goto on_return; } - status = codec->op->open(codec, &codec_param); + status = pjmedia_codec_open(codec, &codec_param); if (status != PJ_SUCCESS) { rc = -70; goto on_return; @@ -117,7 +117,7 @@ static int codec_test_encode(pjmedia_codec_mgr *mgr, break; out_frame.size = samples_per_frame; - status = codec->op->encode(codec, &in_frame, samples_per_frame, + status = pjmedia_codec_encode(codec, &in_frame, samples_per_frame, &out_frame); if (status != PJ_SUCCESS) { rc = -95; @@ -188,7 +188,7 @@ on_return: fclose(fref); if (codec) { - codec->op->close(codec); + pjmedia_codec_close(codec); pjmedia_codec_mgr_dealloc_codec(mgr, codec); } @@ -326,13 +326,13 @@ static int codec_test_decode(pjmedia_codec_mgr *mgr, codec_param.info.avg_bps = bitrate; codec_param.setting.vad = 0; - status = codec->op->init(codec, pool); + status = pjmedia_codec_init(codec, pool); if (status != PJ_SUCCESS) { rc = -60; goto on_return; } - status = codec->op->open(codec, &codec_param); + status = pjmedia_codec_open(codec, &codec_param); if (status != PJ_SUCCESS) { rc = -70; goto on_return; @@ -387,8 +387,8 @@ static int codec_test_decode(pjmedia_codec_mgr *mgr, if (has_frame) { count = 2; - if (codec->op->parse(codec, pkt, encoded_len, &ts, - &count, in_frame) != PJ_SUCCESS) + if (pjmedia_codec_parse(codec, pkt, encoded_len, &ts, + &count, in_frame) != PJ_SUCCESS) { rc = -100; goto on_return; @@ -399,15 +399,15 @@ static int codec_test_decode(pjmedia_codec_mgr *mgr, goto on_return; } - if (codec->op->decode(codec, &in_frame[0], samples_per_frame*2, - &out_frame) != PJ_SUCCESS) + if (pjmedia_codec_decode(codec, &in_frame[0], samples_per_frame*2, + &out_frame) != PJ_SUCCESS) { rc = -120; goto on_return; } } else { - if (codec->op->recover(codec, samples_per_frame*2, - &out_frame) != PJ_SUCCESS) + if (pjmedia_codec_recover(codec, samples_per_frame*2, + &out_frame) != PJ_SUCCESS) { rc = -125; goto on_return; @@ -483,7 +483,7 @@ on_return: fclose(input); if (codec) { - codec->op->close(codec); + pjmedia_codec_close(codec); pjmedia_codec_mgr_dealloc_codec(mgr, codec); } diff --git a/pjmedia/src/test/main.c b/pjmedia/src/test/main.c index b48f7d77..6ea1595c 100644 --- a/pjmedia/src/test/main.c +++ b/pjmedia/src/test/main.c @@ -17,6 +17,8 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include <pj/os.h> + #include "test.h" @@ -29,8 +31,7 @@ # include "../../../pjlib/include/rtems-network-config.h" #endif - -int main(int argc, char *argv[]) +static int main_func(int argc, char *argv[]) { int rc; char s[10]; @@ -46,4 +47,7 @@ int main(int argc, char *argv[]) return rc; } - +int main(int argc, char *argv[]) +{ + return pj_run_app(&main_func, argc, argv, 0); +} diff --git a/pjmedia/src/test/mips_test.c b/pjmedia/src/test/mips_test.c index d5ece9c7..31a33ed1 100644 --- a/pjmedia/src/test/mips_test.c +++ b/pjmedia/src/test/mips_test.c @@ -684,7 +684,7 @@ struct codec_port static pj_status_t codec_put_frame(struct pjmedia_port *this_port, - const pjmedia_frame *frame) + pjmedia_frame *frame) { struct codec_port *cp = (struct codec_port*)this_port; pjmedia_frame out_frame; @@ -692,8 +692,8 @@ static pj_status_t codec_put_frame(struct pjmedia_port *this_port, out_frame.buf = cp->pkt; out_frame.size = sizeof(cp->pkt); - status = cp->codec->op->encode(cp->codec, frame, sizeof(cp->pkt), - &out_frame); + status = pjmedia_codec_encode(cp->codec, frame, sizeof(cp->pkt), + &out_frame); pj_assert(status == PJ_SUCCESS); if (out_frame.size != 0) { @@ -701,16 +701,16 @@ static pj_status_t codec_put_frame(struct pjmedia_port *this_port, unsigned frame_cnt = PJ_ARRAY_SIZE(parsed_frm); unsigned i; - status = cp->codec->op->parse(cp->codec, out_frame.buf, - out_frame.size, &out_frame.timestamp, - &frame_cnt, parsed_frm); + status = pjmedia_codec_parse(cp->codec, out_frame.buf, + out_frame.size, &out_frame.timestamp, + &frame_cnt, parsed_frm); pj_assert(status == PJ_SUCCESS); for (i=0; i<frame_cnt; ++i) { pcm_frm.buf = cp->pcm; pcm_frm.size = sizeof(cp->pkt); - status = cp->codec->op->decode(cp->codec, &parsed_frm[i], - sizeof(cp->pcm), &pcm_frm); + status = pjmedia_codec_decode(cp->codec, &parsed_frm[i], + sizeof(cp->pcm), &pcm_frm); pj_assert(status == PJ_SUCCESS); } } @@ -722,7 +722,7 @@ static pj_status_t codec_on_destroy(struct pjmedia_port *this_port) { struct codec_port *cp = (struct codec_port*)this_port; - cp->codec->op->close(cp->codec); + pjmedia_codec_close(cp->codec); pjmedia_codec_mgr_dealloc_codec(pjmedia_endpt_get_codec_mgr(cp->endpt), cp->codec); cp->codec_deinit(); @@ -782,11 +782,11 @@ static pjmedia_port* codec_encode_decode( pj_pool_t *pool, if (status != PJ_SUCCESS) return NULL; - status = (*cp->codec->op->init)(cp->codec, pool); + status = pjmedia_codec_init(cp->codec, pool); if (status != PJ_SUCCESS) return NULL; - status = cp->codec->op->open(cp->codec, &codec_param); + status = pjmedia_codec_open(cp->codec, &codec_param); if (status != PJ_SUCCESS) return NULL; @@ -1131,13 +1131,13 @@ static pj_status_t wsola_discard_get_frame(struct pjmedia_port *this_port, pj_status_t status; while (pjmedia_circ_buf_get_len(wp->circbuf) < - wp->base.info.samples_per_frame * (CIRC_BUF_FRAME_CNT-1)) + PJMEDIA_PIA_SPF(&wp->base.info) * (CIRC_BUF_FRAME_CNT-1)) { status = pjmedia_port_get_frame(wp->gen_port, frame); pj_assert(status==PJ_SUCCESS); status = pjmedia_circ_buf_write(wp->circbuf, (short*)frame->buf, - wp->base.info.samples_per_frame); + PJMEDIA_PIA_SPF(&wp->base.info)); pj_assert(status==PJ_SUCCESS); } @@ -1149,7 +1149,7 @@ static pj_status_t wsola_discard_get_frame(struct pjmedia_port *this_port, pjmedia_circ_buf_get_read_regions(wp->circbuf, ®1, ®1_len, ®2, ®2_len); - del_cnt = wp->base.info.samples_per_frame; + del_cnt = PJMEDIA_PIA_SPF(&wp->base.info); status = pjmedia_wsola_discard(wp->wsola, reg1, reg1_len, reg2, reg2_len, &del_cnt); pj_assert(status==PJ_SUCCESS); @@ -2010,7 +2010,7 @@ static pj_status_t delaybuf_get_frame(struct pjmedia_port *this_port, } static pj_status_t delaybuf_put_frame(struct pjmedia_port *this_port, - const pjmedia_frame *frame) + pjmedia_frame *frame) { struct delaybuf_port *dp = (struct delaybuf_port*)this_port; pj_status_t status; @@ -2219,7 +2219,7 @@ static pj_timestamp run_entry(unsigned clock_rate, struct test_entry *e) } /* Port may decide to use different ptime (e.g. iLBC) */ - samples_per_frame = port->info.samples_per_frame; + samples_per_frame = PJMEDIA_PIA_SPF(&port->info); gen_port = create_gen_port(pool, clock_rate, 1, samples_per_frame, 100); diff --git a/pjmedia/src/test/test.c b/pjmedia/src/test/test.c index ca53d732..d243ed8a 100644 --- a/pjmedia/src/test/test.c +++ b/pjmedia/src/test/test.c @@ -47,15 +47,33 @@ int test_main(void) { int rc = 0; pj_caching_pool caching_pool; + pj_pool_t *pool; pj_init(); pj_caching_pool_init(&caching_pool, &pj_pool_factory_default_policy, 0); + pool = pj_pool_create(&caching_pool.factory, "test", 1000, 512, NULL); pj_log_set_decor(PJ_LOG_HAS_NEWLINE); pj_log_set_level(3); mem = &caching_pool.factory; + pjmedia_video_format_mgr_create(pool, 64, 0, NULL); + pjmedia_converter_mgr_create(pool, NULL); + pjmedia_vid_codec_mgr_create(pool, NULL); + +#if HAS_VID_PORT_TEST + DO_TEST(vid_port_test()); +#endif + +#if HAS_VID_DEV_TEST + DO_TEST(vid_dev_test()); +#endif + +#if HAS_VID_CODEC_TEST + DO_TEST(vid_codec_test()); +#endif + #if HAS_SDP_NEG_TEST DO_TEST(sdp_neg_test()); #endif @@ -81,6 +99,11 @@ on_return: PJ_LOG(3,(THIS_FILE,"Looks like everything is okay!")); } + pjmedia_video_format_mgr_destroy(pjmedia_video_format_mgr_instance()); + pjmedia_converter_mgr_destroy(pjmedia_converter_mgr_instance()); + pjmedia_vid_codec_mgr_destroy(pjmedia_vid_codec_mgr_instance()); + + pj_pool_release(pool); pj_caching_pool_destroy(&caching_pool); return rc; diff --git a/pjmedia/src/test/test.h b/pjmedia/src/test/test.h index 74279c38..abd7d0bd 100644 --- a/pjmedia/src/test/test.h +++ b/pjmedia/src/test/test.h @@ -23,6 +23,9 @@ #include <pjmedia.h> #include <pjlib.h> +#define HAS_VID_DEV_TEST 1 +#define HAS_VID_PORT_TEST 0 +#define HAS_VID_CODEC_TEST 1 #define HAS_SDP_NEG_TEST 1 #define HAS_JBUF_TEST 1 #define HAS_MIPS_TEST 1 @@ -35,6 +38,9 @@ int jbuf_main(void); int sdp_neg_test(void); int mips_test(void); int codec_test_vectors(void); +int vid_codec_test(void); +int vid_dev_test(void); +int vid_port_test(void); extern pj_pool_factory *mem; void app_perror(pj_status_t status, const char *title); diff --git a/pjmedia/src/test/vid_codec_test.c b/pjmedia/src/test/vid_codec_test.c new file mode 100644 index 00000000..36ca19ac --- /dev/null +++ b/pjmedia/src/test/vid_codec_test.c @@ -0,0 +1,467 @@ +#include "test.h" +#include <pjmedia-codec/ffmpeg_codecs.h> +#include <pjmedia-videodev/videodev.h> +#include <pjmedia/vid_codec.h> +#include <pjmedia/port.h> + +#define THIS_FILE "vid_codec.c" + +#define BYPASS_CODEC 0 +#define BYPASS_PACKETIZER 0 + +/* + * Capture device setting: + * -1 = colorbar, + * -2 = any non-colorbar capture device (first found) + * x = specified capture device id + */ +#define CAPTURE_DEV -1 + + +typedef struct codec_port_data_t +{ + pjmedia_vid_codec *codec; + pjmedia_vid_port *rdr_port; + pj_uint8_t *enc_buf; + pj_size_t enc_buf_size; + pj_uint8_t *pack_buf; + pj_size_t pack_buf_size; +} codec_port_data_t; + +static pj_status_t codec_on_event(pjmedia_event_subscription *esub, + pjmedia_event *event) +{ + codec_port_data_t *port_data = (codec_port_data_t*)esub->user_data; + + if (event->type == PJMEDIA_EVENT_FMT_CHANGED) { + pjmedia_vid_codec *codec = port_data->codec; + pjmedia_vid_codec_param codec_param; + pj_status_t status; + + ++event->proc_cnt; + + status = pjmedia_vid_codec_get_param(codec, &codec_param); + if (status != PJ_SUCCESS) + return status; + + status = pjmedia_vid_dev_stream_set_cap( + pjmedia_vid_port_get_stream(port_data->rdr_port), + PJMEDIA_VID_DEV_CAP_FORMAT, + &codec_param.dec_fmt); + if (status != PJ_SUCCESS) + return status; + } + + return PJ_SUCCESS; +} + +static pj_status_t codec_put_frame(pjmedia_port *port, + pjmedia_frame *frame) +{ + codec_port_data_t *port_data = (codec_port_data_t*)port->port_data.pdata; + pj_status_t status; + +#if !BYPASS_CODEC + { + pjmedia_vid_codec *codec = port_data->codec; + pjmedia_frame enc_frame; + + enc_frame.buf = port_data->enc_buf; + enc_frame.size = port_data->enc_buf_size; + + status = pjmedia_vid_codec_encode(codec, frame, enc_frame.size, + &enc_frame); + if (status != PJ_SUCCESS) goto on_error; + +#if !BYPASS_PACKETIZER + if (enc_frame.size) { + unsigned pos = 0; + pj_bool_t packetized = PJ_FALSE; + unsigned unpack_pos = 0; + + while (pos < enc_frame.size) { + pj_uint8_t *payload; + pj_size_t payload_len; + + status = pjmedia_vid_codec_packetize( + codec, + (pj_uint8_t*)enc_frame.buf, + enc_frame.size, &pos, + (const pj_uint8_t**)&payload, + &payload_len); + if (status == PJ_ENOTSUP) + break; + if (status != PJ_SUCCESS) + goto on_error; + + status = pjmedia_vid_codec_unpacketize( + codec, payload, payload_len, + port_data->pack_buf, + port_data->pack_buf_size, + &unpack_pos); + if (status != PJ_SUCCESS) + goto on_error; + + // what happen if the bitstream is broken? + //if (i++ != 1) unpack_pos -= 10; + + packetized = PJ_TRUE; + } + + if (packetized) { + enc_frame.buf = port_data->pack_buf; + enc_frame.size = unpack_pos; + } + } +#endif + + status = pjmedia_vid_codec_decode(codec, &enc_frame, + frame->size, frame); + if (status != PJ_SUCCESS) goto on_error; + } +#endif + + status = pjmedia_port_put_frame( + pjmedia_vid_port_get_passive_port(port_data->rdr_port), + frame); + if (status != PJ_SUCCESS) goto on_error; + + return PJ_SUCCESS; + +on_error: + pj_perror(3, THIS_FILE, status, "codec_put_frame() error"); + return status; +} + +static const char* dump_codec_info(const pjmedia_vid_codec_info *info) +{ + static char str[80]; + unsigned i; + char *p = str; + + /* Raw format ids */ + for (i=0; (i<info->dec_fmt_id_cnt) && (p-str+5<sizeof(str)); ++i) { + pj_memcpy(p, &info->dec_fmt_id[i], 4); + p += 4; + *p++ = ' '; + } + *p = '\0'; + + return str; +} + +static int enum_codecs() +{ + unsigned i, cnt; + pjmedia_vid_codec_info info[PJMEDIA_CODEC_MGR_MAX_CODECS]; + pj_status_t status; + + PJ_LOG(3, (THIS_FILE, " codec enums")); + cnt = PJ_ARRAY_SIZE(info); + status = pjmedia_vid_codec_mgr_enum_codecs(NULL, &cnt, info, NULL); + if (status != PJ_SUCCESS) + return 100; + + for (i = 0; i < cnt; ++i) { + PJ_LOG(3, (THIS_FILE, " %-16.*s %c%c %s", + info[i].encoding_name.slen, info[i].encoding_name.ptr, + (info[i].dir & PJMEDIA_DIR_ENCODING? 'E' : ' '), + (info[i].dir & PJMEDIA_DIR_DECODING? 'D' : ' '), + dump_codec_info(&info[i]))); + } + + return PJ_SUCCESS; +} + +static int encode_decode_test(pj_pool_t *pool, const char *codec_id) +{ + const pj_str_t port_name = {"codec", 5}; + + pjmedia_vid_codec *codec=NULL; + pjmedia_port codec_port; + codec_port_data_t codec_port_data; + pjmedia_vid_codec_param codec_param; + const pjmedia_vid_codec_info *codec_info; + + pjmedia_vid_dev_index cap_idx, rdr_idx; + pjmedia_vid_port *capture=NULL, *renderer=NULL; + pjmedia_vid_port_param vport_param; + pjmedia_video_format_detail *vfd; + pjmedia_event_subscription esub; + pj_status_t status; + int rc = 0; + + PJ_LOG(3, (THIS_FILE, " encode decode test")); + + /* Lookup codec */ + { + pj_str_t codec_id_st; + unsigned info_cnt = 1; + + /* Lookup codec */ + pj_cstr(&codec_id_st, codec_id); + status = pjmedia_vid_codec_mgr_find_codecs_by_id(NULL, &codec_id_st, + &info_cnt, + &codec_info, NULL); + if (status != PJ_SUCCESS) { + rc = 205; goto on_return; + } + } + + +#if CAPTURE_DEV == -1 + /* Lookup colorbar source */ + status = pjmedia_vid_dev_lookup("Colorbar", "Colorbar generator", &cap_idx); + if (status != PJ_SUCCESS) { + rc = 206; goto on_return; + } +#elif CAPTURE_DEV == -2 + /* Lookup any first non-colorbar source */ + { + unsigned i, cnt; + pjmedia_vid_dev_info info; + + cap_idx = -1; + cnt = pjmedia_vid_dev_count(); + for (i = 0; i < cnt; ++i) { + status = pjmedia_vid_dev_get_info(i, &info); + if (status != PJ_SUCCESS) { + rc = 206; goto on_return; + } + if (info.dir & PJMEDIA_DIR_CAPTURE && + pj_ansi_stricmp(info.driver, "Colorbar")) + { + cap_idx = i; + break; + } + } + + if (cap_idx == -1) { + status = PJ_ENOTFOUND; + rc = 206; goto on_return; + } + } +#else + cap_idx = CAPTURE_DEV; +#endif + + /* Lookup SDL renderer */ + status = pjmedia_vid_dev_lookup("SDL", "SDL renderer", &rdr_idx); + if (status != PJ_SUCCESS) { + rc = 207; goto on_return; + } + + /* Prepare codec */ + { + pj_str_t codec_id_st; + unsigned info_cnt = 1; + const pjmedia_vid_codec_info *codec_info; + + /* Lookup codec */ + pj_cstr(&codec_id_st, codec_id); + status = pjmedia_vid_codec_mgr_find_codecs_by_id(NULL, &codec_id_st, + &info_cnt, + &codec_info, NULL); + if (status != PJ_SUCCESS) { + rc = 245; goto on_return; + } + status = pjmedia_vid_codec_mgr_get_default_param(NULL, codec_info, + &codec_param); + if (status != PJ_SUCCESS) { + rc = 246; goto on_return; + } + +#if !BYPASS_CODEC + + /* Open codec */ + status = pjmedia_vid_codec_mgr_alloc_codec(NULL, codec_info, + &codec); + if (status != PJ_SUCCESS) { + rc = 250; goto on_return; + } + + status = pjmedia_vid_codec_init(codec, pool); + if (status != PJ_SUCCESS) { + rc = 251; goto on_return; + } + + status = pjmedia_vid_codec_open(codec, &codec_param); + if (status != PJ_SUCCESS) { + rc = 252; goto on_return; + } + + /* After opened, codec will update the param, let's sync encoder & + * decoder format detail. + */ + codec_param.dec_fmt.det = codec_param.enc_fmt.det; + + /* Subscribe to codec events */ + pjmedia_event_subscription_init(&esub, &codec_on_event, + &codec_port_data); + pjmedia_event_subscribe(&codec->epub, &esub); +#endif /* !BYPASS_CODEC */ + } + + pjmedia_vid_port_param_default(&vport_param); + + /* Create capture, set it to active (master) */ + status = pjmedia_vid_dev_default_param(pool, cap_idx, + &vport_param.vidparam); + if (status != PJ_SUCCESS) { + rc = 220; goto on_return; + } + pjmedia_format_copy(&vport_param.vidparam.fmt, &codec_param.dec_fmt); + vport_param.vidparam.dir = PJMEDIA_DIR_CAPTURE; + vport_param.active = PJ_TRUE; + + if (vport_param.vidparam.fmt.detail_type != PJMEDIA_FORMAT_DETAIL_VIDEO) { + rc = 221; goto on_return; + } + + vfd = pjmedia_format_get_video_format_detail(&vport_param.vidparam.fmt, + PJ_TRUE); + if (vfd == NULL) { + rc = 225; goto on_return; + } + + status = pjmedia_vid_port_create(pool, &vport_param, &capture); + if (status != PJ_SUCCESS) { + rc = 226; goto on_return; + } + + /* Create renderer, set it to passive (slave) */ + vport_param.active = PJ_FALSE; + vport_param.vidparam.dir = PJMEDIA_DIR_RENDER; + vport_param.vidparam.rend_id = rdr_idx; + vport_param.vidparam.disp_size = vfd->size; + + status = pjmedia_vid_port_create(pool, &vport_param, &renderer); + if (status != PJ_SUCCESS) { + rc = 230; goto on_return; + } + + /* Init codec port */ + pj_bzero(&codec_port, sizeof(codec_port)); + status = pjmedia_port_info_init2(&codec_port.info, &port_name, 0x1234, + PJMEDIA_DIR_ENCODING, + &codec_param.dec_fmt); + if (status != PJ_SUCCESS) { + rc = 260; goto on_return; + } + + codec_port_data.codec = codec; + codec_port_data.rdr_port = renderer; + codec_port_data.enc_buf_size = codec_param.dec_fmt.det.vid.size.w * + codec_param.dec_fmt.det.vid.size.h * 4; + codec_port_data.enc_buf = pj_pool_alloc(pool, + codec_port_data.enc_buf_size); + codec_port_data.pack_buf_size = codec_port_data.enc_buf_size; + codec_port_data.pack_buf = pj_pool_alloc(pool, + codec_port_data.pack_buf_size); + + codec_port.put_frame = &codec_put_frame; + codec_port.port_data.pdata = &codec_port_data; + + /* Connect capture to codec port */ + status = pjmedia_vid_port_connect(capture, + &codec_port, + PJ_FALSE); + if (status != PJ_SUCCESS) { + rc = 270; goto on_return; + } + +#if BYPASS_CODEC + PJ_LOG(3, (THIS_FILE, " starting loopback test: %c%c%c%c %dx%d", + ((codec_param.dec_fmt.id & 0x000000FF) >> 0), + ((codec_param.dec_fmt.id & 0x0000FF00) >> 8), + ((codec_param.dec_fmt.id & 0x00FF0000) >> 16), + ((codec_param.dec_fmt.id & 0xFF000000) >> 24), + codec_param.dec_fmt.det.vid.size.w, + codec_param.dec_fmt.det.vid.size.h + )); +#else + PJ_LOG(3, (THIS_FILE, " starting codec test: %c%c%c%c<->%.*s %dx%d", + ((codec_param.dec_fmt.id & 0x000000FF) >> 0), + ((codec_param.dec_fmt.id & 0x0000FF00) >> 8), + ((codec_param.dec_fmt.id & 0x00FF0000) >> 16), + ((codec_param.dec_fmt.id & 0xFF000000) >> 24), + codec_info->encoding_name.slen, + codec_info->encoding_name.ptr, + codec_param.dec_fmt.det.vid.size.w, + codec_param.dec_fmt.det.vid.size.h + )); +#endif + + /* Start streaming.. */ + status = pjmedia_vid_port_start(renderer); + if (status != PJ_SUCCESS) { + rc = 275; goto on_return; + } + status = pjmedia_vid_port_start(capture); + if (status != PJ_SUCCESS) { + rc = 280; goto on_return; + } + + /* Sleep while the video is being displayed... */ + pj_thread_sleep(10000); + +on_return: + if (status != PJ_SUCCESS) { + PJ_PERROR(3, (THIS_FILE, status, " error")); + } + if (capture) { + pjmedia_vid_port_stop(capture); + pjmedia_vid_port_destroy(capture); + } + if (renderer) { + pjmedia_vid_port_stop(renderer); + pjmedia_vid_port_destroy(renderer); + } + if (codec) { + pjmedia_vid_codec_close(codec); + pjmedia_vid_codec_mgr_dealloc_codec(NULL, codec); + } + + return rc; +} + +int vid_codec_test(void) +{ + pj_pool_t *pool; + int rc = 0; + pj_status_t status; + int orig_log_level; + + orig_log_level = pj_log_get_level(); + pj_log_set_level(6); + + PJ_LOG(3, (THIS_FILE, "Performing video codec tests..")); + + pool = pj_pool_create(mem, "Vid codec test", 256, 256, 0); + + status = pjmedia_vid_dev_subsys_init(mem); + if (status != PJ_SUCCESS) + return -10; + + status = pjmedia_codec_ffmpeg_init(NULL, mem); + if (status != PJ_SUCCESS) + return -20; + + rc = enum_codecs(); + if (rc != 0) + goto on_return; + + rc = encode_decode_test(pool, "h263-1998"); + if (rc != 0) + goto on_return; + +on_return: + pjmedia_codec_ffmpeg_deinit(); + pjmedia_vid_dev_subsys_shutdown(); + pj_pool_release(pool); + pj_log_set_level(orig_log_level); + + return rc; +} + + diff --git a/pjmedia/src/test/vid_dev_test.c b/pjmedia/src/test/vid_dev_test.c new file mode 100644 index 00000000..36966047 --- /dev/null +++ b/pjmedia/src/test/vid_dev_test.c @@ -0,0 +1,292 @@ +/* $Id$ */ +/* + * Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com) + * Copyright (C) 2003-2008 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 + */ +#include "test.h" +#include <pjmedia-audiodev/audiodev.h> +#include <pjmedia-codec/ffmpeg_codecs.h> +#include <pjmedia/vid_codec.h> +#include <pjmedia_videodev.h> + +#define THIS_FILE "vid_dev_test.c" +#define LOOP_DURATION 10 + +static pj_bool_t is_quitting = PJ_FALSE; + +static const char *vid_dir_name(pjmedia_dir dir) +{ + switch (dir) { + case PJMEDIA_DIR_CAPTURE: + return "capture"; + case PJMEDIA_DIR_RENDER: + return "render"; + case PJMEDIA_DIR_CAPTURE_RENDER: + return "capture & render"; + default: + return "unknown"; + } +} + +static int enum_devs(void) +{ + unsigned i, dev_cnt; + pj_status_t status; + + PJ_LOG(3, (THIS_FILE, " Enum video devices:")); + dev_cnt = pjmedia_vid_dev_count(); + for (i = 0; i < dev_cnt; ++i) { + pjmedia_vid_dev_info di; + status = pjmedia_vid_dev_get_info(i, &di); + if (status == PJ_SUCCESS) { + unsigned j; + + PJ_LOG(3, (THIS_FILE, " %3d: %s (%s) - %s", i, di.name, di.driver, + vid_dir_name(di.dir))); + + PJ_LOG(3,(THIS_FILE, " Supported formats:")); + for (j=0; j<di.fmt_cnt; ++j) { + const pjmedia_video_format_info *vfi; + + vfi = pjmedia_get_video_format_info(NULL, di.fmt[j].id); + PJ_LOG(3,(THIS_FILE, " %s", + (vfi ? vfi->name : "unknown"))); + } + } + } + + return PJ_SUCCESS; +} + +static pj_status_t vid_event_cb(pjmedia_event_subscription *esub, + pjmedia_event *event) +{ + if (event->type == PJMEDIA_EVENT_WND_CLOSED) + is_quitting = PJ_TRUE; + + return PJ_SUCCESS; +} + +static int capture_render_loopback(int cap_dev_id, int rend_dev_id, + const pjmedia_format *fmt) +{ + pj_pool_t *pool; + pjmedia_vid_port *capture=NULL, *renderer=NULL; + pjmedia_vid_dev_info cdi, rdi; + pjmedia_vid_port_param param; + pjmedia_video_format_detail *vfd; + pjmedia_event_subscription esub; + pj_status_t status; + int rc = 0, i; + + pool = pj_pool_create(mem, "vidloop", 1000, 1000, NULL); + + status = pjmedia_vid_dev_get_info(cap_dev_id, &cdi); + if (status != PJ_SUCCESS) + goto on_return; + + status = pjmedia_vid_dev_get_info(rend_dev_id, &rdi); + if (status != PJ_SUCCESS) + goto on_return; + + PJ_LOG(3,(THIS_FILE, + " %s (%s) ===> %s (%s)\t%s\t%dx%d\t@%d:%d fps", + cdi.name, cdi.driver, rdi.name, rdi.driver, + pjmedia_get_video_format_info(NULL, fmt->id)->name, + fmt->det.vid.size.w, fmt->det.vid.size.h, + fmt->det.vid.fps.num, fmt->det.vid.fps.denum)); + + pjmedia_vid_port_param_default(¶m); + + /* Create capture, set it to active (master) */ + status = pjmedia_vid_dev_default_param(pool, cap_dev_id, + ¶m.vidparam); + if (status != PJ_SUCCESS) { + rc = 100; goto on_return; + } + param.vidparam.dir = PJMEDIA_DIR_CAPTURE; + param.vidparam.fmt = *fmt; + param.active = PJ_TRUE; + + if (param.vidparam.fmt.detail_type != PJMEDIA_FORMAT_DETAIL_VIDEO) { + rc = 103; goto on_return; + } + + vfd = pjmedia_format_get_video_format_detail(¶m.vidparam.fmt, PJ_TRUE); + if (vfd == NULL) { + rc = 105; goto on_return; + } + + status = pjmedia_vid_port_create(pool, ¶m, &capture); + if (status != PJ_SUCCESS) { + rc = 110; goto on_return; + } + + /* Create renderer, set it to passive (slave) */ + status = pjmedia_vid_dev_default_param(pool, rend_dev_id, + ¶m.vidparam); + if (status != PJ_SUCCESS) { + rc = 120; goto on_return; + } + + param.active = PJ_FALSE; + param.vidparam.dir = PJMEDIA_DIR_RENDER; + param.vidparam.rend_id = rend_dev_id; + param.vidparam.fmt = *fmt; + param.vidparam.disp_size = vfd->size; + + status = pjmedia_vid_port_create(pool, ¶m, &renderer); + if (status != PJ_SUCCESS) { + rc = 130; goto on_return; + } + + /* Set event handler */ + pjmedia_event_subscription_init(&esub, &vid_event_cb, NULL); + pjmedia_event_subscribe( + pjmedia_vid_port_get_event_publisher(renderer), + &esub); + + /* Connect capture to renderer */ + status = pjmedia_vid_port_connect( + capture, + pjmedia_vid_port_get_passive_port(renderer), + PJ_FALSE); + if (status != PJ_SUCCESS) { + rc = 140; goto on_return; + } + + /* Start streaming.. */ + status = pjmedia_vid_port_start(renderer); + if (status != PJ_SUCCESS) { + rc = 150; goto on_return; + } + status = pjmedia_vid_port_start(capture); + if (status != PJ_SUCCESS) { + rc = 160; goto on_return; + } + + /* Sleep while the webcam is being displayed... */ + for (i = 0; i < LOOP_DURATION*10 && (!is_quitting); i++) { + pj_thread_sleep(100); + } + +on_return: + if (status != PJ_SUCCESS) + PJ_PERROR(3, (THIS_FILE, status, " error")); + + if (capture) + pjmedia_vid_port_destroy(capture); + if (renderer) + pjmedia_vid_port_destroy(renderer); + + pj_pool_release(pool); + return rc; +} + +static int loopback_test(void) +{ + unsigned count, i; + pjmedia_format_id test_fmts[] = { + PJMEDIA_FORMAT_YUY2 + }; + pjmedia_rect_size test_sizes[] = { + {176,144}, /* QCIF */ + {352,288}, /* CIF */ + {704,576} /* 4CIF */ + }; + pjmedia_ratio test_fpses[] = { + {25, 1}, + {30, 1}, + }; + pj_status_t status; + + PJ_LOG(3, (THIS_FILE, " Loopback tests (prepare you webcams):")); + + count = pjmedia_vid_dev_count(); + for (i=0; i<count; ++i) { + pjmedia_vid_dev_info cdi; + unsigned j; + + status = pjmedia_vid_dev_get_info(i, &cdi); + if (status != PJ_SUCCESS) + return -300; + + /* Only interested with capture device */ + if ((cdi.dir & PJMEDIA_DIR_CAPTURE) == 0) + continue; + + for (j=i+1; j<count; ++j) { + pjmedia_vid_dev_info rdi; + unsigned k; + + status = pjmedia_vid_dev_get_info(j, &rdi); + if (status != PJ_SUCCESS) + return -310; + + /* Only interested with render device */ + if ((rdi.dir & PJMEDIA_DIR_RENDER) == 0) + continue; + + /* Test with the format, size, and fps combinations */ + for (k=0; k<PJ_ARRAY_SIZE(test_fmts); ++k) { + unsigned l; + + for (l=0; l<PJ_ARRAY_SIZE(test_sizes); ++l) { + unsigned m; + + for (m=0; m<PJ_ARRAY_SIZE(test_fpses); ++m) { + pjmedia_format fmt; + + pjmedia_format_init_video(&fmt, test_fmts[k], + test_sizes[l].w, + test_sizes[l].h, + test_fpses[m].num, + test_fpses[m].denum); + + capture_render_loopback(i, j, &fmt); + } + } + } /* k */ + + } + } + + return 0; +} + +int vid_dev_test(void) +{ + int rc = 0; + pj_status_t status; + + status = pjmedia_vid_dev_subsys_init(mem); + if (status != PJ_SUCCESS) + return -10; + + rc = enum_devs(); + if (rc != 0) + goto on_return; + + rc = loopback_test(); + if (rc != 0) + goto on_return; + +on_return: + pjmedia_vid_dev_subsys_shutdown(); + + return rc; +} diff --git a/pjmedia/src/test/vid_port_test.c b/pjmedia/src/test/vid_port_test.c new file mode 100644 index 00000000..cd7acd8d --- /dev/null +++ b/pjmedia/src/test/vid_port_test.c @@ -0,0 +1,241 @@ +/* $Id$ */ +/* + * Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com) + * Copyright (C) 2003-2008 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 + */ +#include "test.h" +#include <pjmedia-audiodev/audiodev.h> +#include <pjmedia-codec/ffmpeg_codecs.h> +#include <pjmedia/vid_codec.h> +#include <pjmedia_videodev.h> + +#define THIS_FILE "vid_dev_test.c" +#define LOOP_DURATION 6 + +static pj_bool_t is_quitting = PJ_FALSE; + +static pj_status_t vid_event_cb(pjmedia_event_subscription *esub, + pjmedia_event *event) +{ + if (event->type == PJMEDIA_EVENT_WND_CLOSED) + is_quitting = PJ_TRUE; + + return PJ_SUCCESS; +} + +static int capture_render_loopback(pj_bool_t active, + int cap_dev_id, int rend_dev_id, + const pjmedia_format *fmt) +{ + pj_pool_t *pool; + pjmedia_vid_port *capture=NULL, *renderer=NULL; + pjmedia_vid_dev_info cdi, rdi; + pjmedia_vid_port_param param; + pjmedia_video_format_detail *vfd; + pjmedia_vid_dev_cb cb; + pjmedia_event_subscription esub; + pj_status_t status; + int rc = 0, i; + + pool = pj_pool_create(mem, "vidportloop", 1000, 1000, NULL); + + status = pjmedia_vid_dev_get_info(cap_dev_id, &cdi); + if (status != PJ_SUCCESS) + goto on_return; + + status = pjmedia_vid_dev_get_info(rend_dev_id, &rdi); + if (status != PJ_SUCCESS) + goto on_return; + + PJ_LOG(3,(THIS_FILE, + " %s (%s) ===> %s (%s)\t%s\t%dx%d\t@%d:%d fps", + cdi.name, cdi.driver, rdi.name, rdi.driver, + pjmedia_get_video_format_info(NULL, fmt->id)->name, + fmt->det.vid.size.w, fmt->det.vid.size.h, + fmt->det.vid.fps.num, fmt->det.vid.fps.denum)); + + pjmedia_vid_port_param_default(¶m); + + /* Create capture, set it to active (master) */ + status = pjmedia_vid_dev_default_param(pool, cap_dev_id, + ¶m.vidparam); + if (status != PJ_SUCCESS) { + rc = 100; goto on_return; + } + param.vidparam.dir = PJMEDIA_DIR_CAPTURE; + param.vidparam.fmt = *fmt; + param.active = (active? PJ_TRUE: PJ_FALSE); + + if (param.vidparam.fmt.detail_type != PJMEDIA_FORMAT_DETAIL_VIDEO) { + rc = 103; goto on_return; + } + + vfd = pjmedia_format_get_video_format_detail(¶m.vidparam.fmt, PJ_TRUE); + if (vfd == NULL) { + rc = 105; goto on_return; + } + + status = pjmedia_vid_port_create(pool, ¶m, &capture); + if (status != PJ_SUCCESS) { + rc = 110; goto on_return; + } + + /* Create renderer, set it to passive (slave) */ + status = pjmedia_vid_dev_default_param(pool, rend_dev_id, + ¶m.vidparam); + if (status != PJ_SUCCESS) { + rc = 120; goto on_return; + } + + param.active = (active? PJ_FALSE: PJ_TRUE); + param.vidparam.dir = PJMEDIA_DIR_RENDER; + param.vidparam.rend_id = rend_dev_id; + param.vidparam.fmt = *fmt; + param.vidparam.disp_size = vfd->size; + + status = pjmedia_vid_port_create(pool, ¶m, &renderer); + if (status != PJ_SUCCESS) { + rc = 130; goto on_return; + } + + /* Set event handler */ + pjmedia_event_subscription_init(&esub, &vid_event_cb, NULL); + pjmedia_event_subscribe( + pjmedia_vid_port_get_event_publisher(renderer), + &esub); + + /* Connect capture to renderer */ + status = pjmedia_vid_port_connect( + (active? capture: renderer), + pjmedia_vid_port_get_passive_port(active? renderer: capture), + PJ_FALSE); + if (status != PJ_SUCCESS) { + rc = 140; goto on_return; + } + + /* Start streaming.. */ + status = pjmedia_vid_port_start(renderer); + if (status != PJ_SUCCESS) { + rc = 150; goto on_return; + } + status = pjmedia_vid_port_start(capture); + if (status != PJ_SUCCESS) { + rc = 160; goto on_return; + } + + /* Sleep while the webcam is being displayed... */ + for (i = 0; i < LOOP_DURATION*10 && (!is_quitting); i++) { + pj_thread_sleep(100); + } + +on_return: + if (status != PJ_SUCCESS) + PJ_PERROR(3, (THIS_FILE, status, " error")); + + if (capture) + pjmedia_vid_port_destroy(capture); + if (renderer) + pjmedia_vid_port_destroy(renderer); + + pj_pool_release(pool); + return rc; +} + +static int find_device(pjmedia_dir dir, + pj_bool_t has_callback) +{ + unsigned i, count = pjmedia_vid_dev_count(); + + for (i = 0; i < count; ++i) { + pjmedia_vid_dev_info cdi; + + if (pjmedia_vid_dev_get_info(i, &cdi) != PJ_SUCCESS) + continue; + if ((cdi.dir & dir) != 0 && cdi.has_callback == has_callback) + return i; + } + + return -999; +} + +static int vidport_test(void) +{ + int i, j, k, l; + int cap_id, rend_id; + pjmedia_format_id test_fmts[] = { + PJMEDIA_FORMAT_RGBA, + PJMEDIA_FORMAT_I420 + }; + pj_status_t status; + + PJ_LOG(3, (THIS_FILE, " Video port tests:")); + + /* Capturer's role: active/passive. */ + for (i = 1; i >= 0; i--) { + /* Capturer's device has_callback: TRUE/FALSE. */ + for (j = 1; j >= 0; j--) { + cap_id = find_device(PJMEDIA_DIR_CAPTURE, j); + if (cap_id < 0) + continue; + + /* Renderer's device has callback: TRUE/FALSE. */ + for (k = 1; k >= 0; k--) { + rend_id = find_device(PJMEDIA_DIR_RENDER, k); + if (rend_id < 0) + continue; + + /* Check various formats to test format conversion. */ + for (l = 0; l < PJ_ARRAY_SIZE(test_fmts); ++l) { + pjmedia_format fmt; + + PJ_LOG(3,(THIS_FILE, + "capturer %s (stream: %s) ===> " + "renderer %s (stream: %s)", + (i? "active": "passive"), + (j? "active": "passive"), + (i? "passive": "active"), + (k? "active": "passive"))); + + pjmedia_format_init_video(&fmt, test_fmts[l], + 640, 480, 25, 1); + capture_render_loopback(i, cap_id, rend_id, &fmt); + } + } + } + } + + return 0; +} + +int vid_port_test(void) +{ + int rc = 0; + pj_status_t status; + + status = pjmedia_vid_dev_subsys_init(mem); + if (status != PJ_SUCCESS) + return -10; + + rc = vidport_test(); + if (rc != 0) + goto on_return; + +on_return: + pjmedia_vid_dev_subsys_shutdown(); + + return rc; +} |