Exemple #1
0
static pj_status_t codec_get_frame(pjmedia_port *port,
                                   pjmedia_frame *frame)
{
    codec_port_data_t *port_data = (codec_port_data_t*)port->port_data.pdata;
    pjmedia_vid_codec *codec = port_data->codec;
    pjmedia_frame enc_frame;
    pj_status_t status;

    enc_frame.buf = port_data->enc_buf;
    enc_frame.size = port_data->enc_buf_size;

    if (port_data->conv) {
        pj_size_t frame_size = frame->size;

        status = pjmedia_port_get_frame(port_data->src_port, frame);
        if (status != PJ_SUCCESS) goto on_error;

        status = pjmedia_vid_codec_decode(codec, 1, frame,
                                          frame->size, &enc_frame);
        if (status != PJ_SUCCESS) goto on_error;

        frame->size = frame_size;
        status = pjmedia_converter_convert(port_data->conv, &enc_frame, frame);
        if (status != PJ_SUCCESS) goto on_error;

        return PJ_SUCCESS;
    }

    status = pjmedia_port_get_frame(port_data->src_port, &enc_frame);
    if (status != PJ_SUCCESS) goto on_error;

    status = pjmedia_vid_codec_decode(codec, 1, &enc_frame,
                                      frame->size, frame);
    if (status != PJ_SUCCESS) goto on_error;

    return PJ_SUCCESS;

on_error:
    pj_perror(3, THIS_FILE, status, "codec_get_frame() error");
    return status;
}
Exemple #2
0
pj_status_t pjmedia_vid_dev_conv_resize_and_rotate(pjmedia_vid_dev_conv *conv,
				      		   void *src_buf,
				      		   void **result)
{
#define swap(a, b) {pj_uint8_t *c = a; a = b; b = c;}

    pj_status_t status;
    pjmedia_frame src_frame, dst_frame;
    pjmedia_rect_size src_size = conv->src_size;
    pj_uint8_t *src = src_buf;
    pj_uint8_t *dst = conv->conv_buf;    

    pj_assert(src_buf);
    
    if (!conv->conv) return PJ_EINVALIDOP;
    
    if (!conv->match_src_dst) {
        /* We need to resize. */
	src_frame.buf = src;
	dst_frame.buf = dst;
	src_frame.size = conv->src_frame_size;
	dst_frame.size = conv->conv_frame_size;
    
	status = pjmedia_converter_convert(conv->conv, &src_frame, &dst_frame);
	if (status != PJ_SUCCESS) {
            PJ_LOG(3, (THIS_FILE, "Failed to convert frame"));
            return status;
        }
        
        src_size = conv->res_size;
        
        swap(src, dst);
    }
    
    if (conv->handle_rotation && conv->rotation != PJMEDIA_ORIENT_NATURAL) {
        /* We need to do rotation. */
    	if (conv->fmt.id == PJMEDIA_FORMAT_I420) {
    	    pjmedia_rect_size dst_size = src_size;
    	    pj_size_t p_len = src_size.w * src_size.h;
    	    
	    if (conv->rotation == PJMEDIA_ORIENT_ROTATE_90DEG ||
		conv->rotation == PJMEDIA_ORIENT_ROTATE_270DEG)
	    {
		dst_size.w = src_size.h;
		dst_size.h = src_size.w;
	    }
    	    
#if defined(PJMEDIA_HAS_LIBYUV) && PJMEDIA_HAS_LIBYUV != 0
	    enum RotationMode mode;
	    
	    switch (conv->rotation) {
	        case PJMEDIA_ORIENT_ROTATE_90DEG:
	            mode = kRotate90;
	            break;
	        case PJMEDIA_ORIENT_ROTATE_180DEG:
	            mode = kRotate180;
	            break;
	        case PJMEDIA_ORIENT_ROTATE_270DEG:
	            mode = kRotate270;
	            break;
	        default:
	            mode = kRotate0;
	    }

    	    I420Rotate(src, src_size.w,
    	    	       src+p_len, src_size.w/2,
    	    	       src+p_len+p_len/4, src_size.w/2,
    	    	       dst, dst_size.w,
    	    	       dst+p_len, dst_size.w/2,
    	    	       dst+p_len+p_len/4, dst_size.w/2,
    	    	       src_size.w, src_size.h, mode);
    	    
    	    swap(src, dst);
#else
	    PJ_UNUSED_ARG(p_len);
	    PJ_UNUSED_ARG(dst_size);
#endif
    	}
    }
    
    if (!conv->match_src_dst && conv->maintain_aspect_ratio) {
	/* Center the frame and fill the area with black color */    
        if (conv->fmt.id == PJMEDIA_FORMAT_I420) {
    	    unsigned i = 0;
    	    pj_uint8_t *pdst = dst;
    	    pj_uint8_t *psrc = src;
            pj_size_t p_len_src = 0, p_len_dst = conv->wxh;
    	    int pad = conv->pad;

            pj_bzero(pdst, p_len_dst);

            if (conv->fit_to_h) {
                /* Fill the left and right with black */
                for (; i < conv->dst_size.h; ++i) {
                    pdst += pad;
                    pj_memcpy(pdst, psrc, conv->rot_size.w);
                    pdst += conv->rot_size.w;
                    psrc += conv->rot_size.w;
                    pdst += pad;
                }
            } else {
                /* Fill the top and bottom with black */
                p_len_src = conv->rot_size.w * conv->rot_size.h;
                pj_memcpy(pdst + conv->rot_size.w * pad, psrc, p_len_src);
                psrc += p_len_src;
                pdst += p_len_dst;
            }

	    /* Fill the U&V components with 0x80 to make it black.
	     * Bzero-ing will make the area look green instead.
	     */
	    pj_memset(pdst, 0x80, p_len_dst/2);
	    pad /= 2;
            if (conv->fit_to_h) {
	    	p_len_src = conv->rot_size.w / 2;
                for (i = conv->dst_size.h; i > 0; --i) {
                    pdst += pad;
                    pj_memcpy(pdst, psrc, p_len_src);
                    pdst += p_len_src;
                    psrc += p_len_src;
                    pdst += pad;
                }
            } else {
                pj_uint8_t *U, *V;
                pj_size_t gap = conv->rot_size.w * pad / 2;

		p_len_src /= 4;
                U = pdst;
                V = U + p_len_dst/4;

                pj_memcpy(U + gap, psrc, p_len_src);
                psrc += p_len_src;
                pj_memcpy(V + gap, psrc, p_len_src);
            }
            
            swap(src, dst);
	}
    }
    
    *result = src;
    
    return PJ_SUCCESS;
}
Exemple #3
0
static pj_status_t tee_put_frame(pjmedia_port *port, pjmedia_frame *frame)
{
    vid_tee_port *tee = (vid_tee_port*)port;
    unsigned i, j;
    const pj_uint8_t PUT_FRM_DONE = 1;

    pj_bzero(tee->put_frm_flag, tee->dst_port_cnt *
				sizeof(tee->put_frm_flag[0]));

    for (i = 0; i < tee->dst_port_cnt; ++i) {
	pjmedia_frame frame_ = *frame;

        if (tee->put_frm_flag[i])
            continue;
        
        if (tee->tee_conv[i].conv) {
            pj_status_t status;
            
            frame_.buf  = tee->buf[0];
            frame_.size = tee->tee_conv[i].conv_buf_size;
            status = pjmedia_converter_convert(tee->tee_conv[i].conv,
                                               frame, &frame_);
            if (status != PJ_SUCCESS) {
                PJ_LOG(3, (THIS_FILE,
			       "Failed to convert frame for destination"
                               " port %d (%.*s)", i,
                               tee->dst_ports[i].dst->info.name.slen,
                               tee->dst_ports[i].dst->info.name.ptr));
                continue;
            }
        }
        
        /* Find other destination ports which has the same format so
         * we don't need to do the same conversion twice.
         */
        for (j = i; j < tee->dst_port_cnt; ++j) {
            pjmedia_frame framep;
            
            if (tee->put_frm_flag[j] ||
                (tee->dst_ports[j].dst->info.fmt.id != 
                 tee->dst_ports[i].dst->info.fmt.id) ||
                (tee->dst_ports[j].dst->info.fmt.det.vid.size.w != 
                 tee->dst_ports[i].dst->info.fmt.det.vid.size.w) ||
                (tee->dst_ports[j].dst->info.fmt.det.vid.size.h != 
                 tee->dst_ports[i].dst->info.fmt.det.vid.size.h))
            {
                continue;
            }
            
            framep = frame_;
            /* For dst_ports that do in-place processing, we need to duplicate
             * the data source first.
             */
            if (tee->dst_ports[j].option & PJMEDIA_VID_TEE_DST_DO_IN_PLACE_PROC)
            {
                PJ_ASSERT_RETURN(tee->buf_size <= frame_.size, PJ_ETOOBIG);
                framep.buf = tee->buf[tee->buf_cnt-1];
                framep.size = frame_.size;
                pj_memcpy(framep.buf, frame_.buf, frame_.size);
            }

            /* Deliver the data */
            pjmedia_port_put_frame(tee->dst_ports[j].dst, &framep);
            tee->put_frm_flag[j] = PUT_FRM_DONE;
            
            if (!tee->tee_conv[i].conv)
                break;
        }
    }

    return PJ_SUCCESS;
}