PJ_DEF(pj_status_t) pjmedia_vid_port_disconnect(pjmedia_vid_port *vp) { PJ_ASSERT_RETURN(vp && vp->role==ROLE_ACTIVE, PJ_EINVAL); pjmedia_event_unsubscribe(NULL, &client_port_event_cb, vp, vp->client_port); vp->client_port = NULL; return PJ_SUCCESS; }
static int aviplay(pj_pool_t *pool, const char *fname) { pjmedia_vid_port *renderer=NULL; pjmedia_vid_port_param param; const pjmedia_video_format_info *vfi; pjmedia_video_format_detail *vfd; pjmedia_snd_port *snd_port = NULL; pj_status_t status; int rc = 0; pjmedia_avi_streams *avi_streams; pjmedia_avi_stream *vid_stream, *aud_stream; pjmedia_port *vid_port = NULL, *aud_port = NULL; pjmedia_vid_codec *codec=NULL; avi_port_t avi_port; pj_bzero(&avi_port, sizeof(avi_port)); status = pjmedia_avi_player_create_streams(pool, fname, 0, &avi_streams); if (status != PJ_SUCCESS) { PJ_PERROR(2,("", status, " Error playing %s", fname)); rc = 210; goto on_return; } vid_stream = pjmedia_avi_streams_get_stream_by_media(avi_streams, 0, PJMEDIA_TYPE_VIDEO); vid_port = pjmedia_avi_stream_get_port(vid_stream); if (vid_port) { pjmedia_vid_port_param_default(¶m); status = pjmedia_vid_dev_default_param(pool, PJMEDIA_VID_DEFAULT_RENDER_DEV, ¶m.vidparam); if (status != PJ_SUCCESS) { rc = 220; goto on_return; } /* Create renderer, set it to active */ param.active = PJ_TRUE; param.vidparam.dir = PJMEDIA_DIR_RENDER; vfd = pjmedia_format_get_video_format_detail(&vid_port->info.fmt, PJ_TRUE); pjmedia_format_init_video(¶m.vidparam.fmt, vid_port->info.fmt.id, vfd->size.w, vfd->size.h, vfd->fps.num, vfd->fps.denum); vfi = pjmedia_get_video_format_info( pjmedia_video_format_mgr_instance(), vid_port->info.fmt.id); /* Check whether the frame is encoded */ if (!vfi || vfi->bpp == 0) { /* Yes, prepare codec */ pj_str_t codec_id_st; unsigned info_cnt = 1, i, k; const pjmedia_vid_codec_info *codec_info; pj_str_t port_name = {"codec", 5}; pj_uint8_t *enc_buf = NULL; pj_size_t enc_buf_size = 0; pjmedia_vid_dev_info rdr_info; pjmedia_port codec_port; codec_port_data_t codec_port_data; pjmedia_vid_codec_param codec_param; struct codec_fmt *codecp = NULL; /* Lookup codec */ for (i = 0; i < sizeof(codec_fmts)/sizeof(codec_fmts[0]); i++) { if (vid_port->info.fmt.id == codec_fmts[i].pjmedia_id) { codecp = &codec_fmts[i]; break; } } if (!codecp) { rc = 242; goto on_return; } pj_cstr(&codec_id_st, codecp->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; } pjmedia_format_copy(&codec_param.enc_fmt, ¶m.vidparam.fmt); pjmedia_vid_dev_get_info(param.vidparam.rend_id, &rdr_info); for (i=0; i<codec_info->dec_fmt_id_cnt; ++i) { for (k=0; k<rdr_info.fmt_cnt; ++k) { if (codec_info->dec_fmt_id[i]==(int)rdr_info.fmt[k].id) { param.vidparam.fmt.id = codec_info->dec_fmt_id[i]; i = codec_info->dec_fmt_id_cnt; break; } } } /* 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; } pjmedia_format_copy(&codec_param.dec_fmt, ¶m.vidparam.fmt); codec_param.dir = PJMEDIA_DIR_DECODING; codec_param.packing = PJMEDIA_VID_PACKING_WHOLE; status = pjmedia_vid_codec_open(codec, &codec_param); if (status != PJ_SUCCESS) { rc = 252; goto on_return; } /* Alloc encoding buffer */ enc_buf_size = codec_param.dec_fmt.det.vid.size.w * codec_param.dec_fmt.det.vid.size.h * 4 + 16; /*< padding, just in case */ enc_buf = pj_pool_alloc(pool,enc_buf_size); /* 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; } pj_bzero(&codec_port_data, sizeof(codec_port_data)); codec_port_data.codec = codec; codec_port_data.src_port = vid_port; codec_port_data.enc_buf = enc_buf; codec_port_data.enc_buf_size = enc_buf_size; codec_port.get_frame = &codec_get_frame; codec_port.port_data.pdata = &codec_port_data; /* Check whether we need to convert the decoded frame */ if (codecp->need_conversion) { pjmedia_conversion_param conv_param; pjmedia_format_copy(&conv_param.src, ¶m.vidparam.fmt); pjmedia_format_copy(&conv_param.dst, ¶m.vidparam.fmt); conv_param.dst.id = codecp->dst_fmt; param.vidparam.fmt.id = conv_param.dst.id; status = pjmedia_converter_create(NULL, pool, &conv_param, &codec_port_data.conv); if (status != PJ_SUCCESS) { rc = 270; goto on_return; } } status = pjmedia_vid_port_create(pool, ¶m, &renderer); if (status != PJ_SUCCESS) { rc = 230; goto on_return; } status = pjmedia_vid_port_connect(renderer, &codec_port, PJ_FALSE); } else { status = pjmedia_vid_port_create(pool, ¶m, &renderer); if (status != PJ_SUCCESS) { rc = 230; goto on_return; } /* Connect avi port to renderer */ status = pjmedia_vid_port_connect(renderer, vid_port, PJ_FALSE); } if (status != PJ_SUCCESS) { rc = 240; goto on_return; } } aud_stream = pjmedia_avi_streams_get_stream_by_media(avi_streams, 0, PJMEDIA_TYPE_AUDIO); aud_port = pjmedia_avi_stream_get_port(aud_stream); if (aud_port) { /* Create sound player port. */ status = pjmedia_snd_port_create_player( pool, /* pool */ -1, /* use default dev. */ PJMEDIA_PIA_SRATE(&aud_port->info),/* clock rate. */ PJMEDIA_PIA_CCNT(&aud_port->info), /* # of channels. */ PJMEDIA_PIA_SPF(&aud_port->info), /* samples per frame. */ PJMEDIA_PIA_BITS(&aud_port->info), /* bits per sample. */ 0, /* options */ &snd_port /* returned port */ ); if (status != PJ_SUCCESS) { rc = 310; goto on_return; } /* Connect file port to the sound player. * Stream playing will commence immediately. */ status = pjmedia_snd_port_connect(snd_port, aud_port); if (status != PJ_SUCCESS) { rc = 330; goto on_return; } } if (vid_port) { pjmedia_vid_dev_cb cb; pj_bzero(&cb, sizeof(cb)); avi_port.snd_port = snd_port; avi_port.vid_port = renderer; avi_port.is_running = PJ_TRUE; pjmedia_vid_port_set_cb(renderer, &cb, &avi_port); /* subscribe events */ pjmedia_event_subscribe(NULL, &avi_event_cb, &avi_port, renderer); if (snd_port) { /* Synchronize video rendering and audio playback */ pjmedia_vid_port_set_clock_src( renderer, pjmedia_snd_port_get_clock_src( snd_port, PJMEDIA_DIR_PLAYBACK)); } /* Start video streaming.. */ status = pjmedia_vid_port_start(renderer); if (status != PJ_SUCCESS) { rc = 270; goto on_return; } } while (!avi_port.is_quitting) { pj_thread_sleep(100); } on_return: if (snd_port) { pjmedia_snd_port_disconnect(snd_port); /* Without this sleep, Windows/DirectSound will repeteadly * play the last frame during destroy. */ pj_thread_sleep(100); pjmedia_snd_port_destroy(snd_port); } if (renderer) { pjmedia_event_unsubscribe(NULL, &avi_event_cb, &avi_port, renderer); pjmedia_vid_port_destroy(renderer); } if (aud_port) pjmedia_port_destroy(aud_port); if (vid_port) pjmedia_port_destroy(vid_port); if (codec) { pjmedia_vid_codec_close(codec); pjmedia_vid_codec_mgr_dealloc_codec(NULL, codec); } return rc; }
static int encode_decode_test(pj_pool_t *pool, const char *codec_id, pjmedia_vid_packing packing) { 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; const char *packing_name; 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; char codec_name[5]; pj_status_t status; int rc = 0; switch (packing) { case PJMEDIA_VID_PACKING_PACKETS: packing_name = "framed"; break; case PJMEDIA_VID_PACKING_WHOLE: packing_name = "whole"; break; default: packing_name = "unknown"; break; } PJ_LOG(3, (THIS_FILE, " encode decode test: codec=%s, packing=%s", codec_id, packing_name)); /* 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; } codec_param.packing = packing; /* 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_subscribe(NULL, &codec_on_event, &codec_port_data, 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; } PJ_LOG(3, (THIS_FILE, " starting codec test: %s<->%.*s %dx%d", pjmedia_fourcc_name(codec_param.dec_fmt.id, codec_name), 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 )); /* 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); if (renderer) pjmedia_vid_port_stop(renderer); if (capture) pjmedia_vid_port_destroy(capture); if (renderer) pjmedia_vid_port_destroy(renderer); if (codec) { pjmedia_event_unsubscribe(NULL, &codec_on_event, &codec_port_data, codec); pjmedia_vid_codec_close(codec); pjmedia_vid_codec_mgr_dealloc_codec(NULL, codec); } return rc; }
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; 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_subscribe(NULL, &vid_event_cb, NULL, renderer); /* 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_stop(capture); if (renderer) pjmedia_vid_port_stop(renderer); if (capture) pjmedia_vid_port_destroy(capture); if (renderer) { pjmedia_event_unsubscribe(NULL, &vid_event_cb, NULL, renderer); pjmedia_vid_port_destroy(renderer); } pj_pool_release(pool); return rc; }