コード例 #1
0
ファイル: vpx.c プロジェクト: acatighera/python-sipsimple
static pj_status_t pj_vpx_codec_decode_whole(pjmedia_vid_codec *codec,
                                             const vpx_image_t *img,
                                             const pj_timestamp *ts,
                                             unsigned output_buf_len,
                                             pjmedia_frame *output) {
    pj_status_t status;
    int half_width = (img->d_w + 1) >> 1;
    int half_height = (img->d_h + 1) >> 1;
    uint8_t* buf;
    uint32_t pos = 0;
    uint32_t plane, y;
    uint8_t* buffer = output->buf;
    int buffer_size = img->d_w * img->d_h + half_width * half_height * 2;

    output->type = PJMEDIA_FRAME_TYPE_NONE;
    output->size = 0;

    /* Check decoding result, e.g: see if the format got changed,
     * keyframe found/missing.
     */
    status = check_decode_result(codec, img, ts);
    if (status != PJ_SUCCESS)
    	return status;

    /* Reset output frame bit info */
    output->bit_info = 0;
    output->timestamp = *ts;

    if (buffer_size <= output_buf_len) {
        for (plane = 0; plane < 3; plane++) {
            unsigned int width = (plane ? half_width : img->d_w);
            unsigned int height = (plane ? half_height : img->d_h);
            buf = img->planes[plane];
            for (y = 0; y < height; y++) {
                pj_memcpy(&buffer[pos], buf, width);
                pos += width;
                buf += img->stride[plane];
            }
        }
        output->size = buffer_size;
        output->type = PJMEDIA_FRAME_TYPE_VIDEO;
        return PJ_SUCCESS;
    } else {
        PJ_LOG(1, (THIS_FILE, "Frame ignored because of too small buffer"));
        return PJ_ETOOSMALL;
    }
}
コード例 #2
0
ファイル: ffmpeg_codecs.c プロジェクト: RockHardJim/idphone
/*
 * Decode frame.
 */
static pj_status_t ffmpeg_codec_decode_whole(pjmedia_vid_codec *codec,
					     const pjmedia_frame *input,
					     unsigned output_buf_len,
					     pjmedia_frame *output)
{
    ffmpeg_private *ff = (ffmpeg_private*)codec->codec_data;
    AVFrame avframe;
    AVPacket avpacket;
    int err, got_picture;

    /* Check if decoder has been opened */
    PJ_ASSERT_RETURN(ff->dec_ctx, PJ_EINVALIDOP);

    /* Reset output frame bit info */
    output->bit_info = 0;

    /* Validate output buffer size */
    // Do this validation later after getting decoding result, where the real
    // decoded size will be assured.
    //if (ff->dec_vafp.framebytes > output_buf_len)
	//return PJ_ETOOSMALL;

    /* Init frame to receive the decoded data, the ffmpeg codec context will
     * automatically provide the decoded buffer (single buffer used for the
     * whole decoding session, and seems to be freed when the codec context
     * closed).
     */
    avcodec_get_frame_defaults(&avframe);

    /* Init packet, the container of the encoded data */
    av_init_packet(&avpacket);
    avpacket.data = (pj_uint8_t*)input->buf;
    avpacket.size = input->size;

    /* ffmpeg warns:
     * - input buffer padding, at least FF_INPUT_BUFFER_PADDING_SIZE
     * - null terminated
     * Normally, encoded buffer is allocated more than needed, so lets just
     * bzero the input buffer end/pad, hope it will be just fine.
     */
    pj_bzero(avpacket.data+avpacket.size, FF_INPUT_BUFFER_PADDING_SIZE);

    output->bit_info = 0;
    output->timestamp = input->timestamp;

#if LIBAVCODEC_VER_AT_LEAST(52,72)
    //avpacket.flags = AV_PKT_FLAG_KEY;
#else
    avpacket.flags = 0;
#endif

#if LIBAVCODEC_VER_AT_LEAST(52,72)
    err = avcodec_decode_video2(ff->dec_ctx, &avframe, 
                                &got_picture, &avpacket);
#else
    err = avcodec_decode_video(ff->dec_ctx, &avframe,
                               &got_picture, avpacket.data, avpacket.size);
#endif
    if (err < 0) {
	pjmedia_event event;

	output->type = PJMEDIA_FRAME_TYPE_NONE;
	output->size = 0;
        print_ffmpeg_err(err);

	/* Broadcast missing keyframe event */
	pjmedia_event_init(&event, PJMEDIA_EVENT_KEYFRAME_MISSING,
			   &input->timestamp, codec);
	pjmedia_event_publish(NULL, codec, &event, 0);

	return PJMEDIA_CODEC_EBADBITSTREAM;
    } else if (got_picture) {
        pjmedia_video_apply_fmt_param *vafp = &ff->dec_vafp;
        pj_uint8_t *q = (pj_uint8_t*)output->buf;
	unsigned i;
	pj_status_t status;

	/* Check decoding result, e.g: see if the format got changed,
	 * keyframe found/missing.
	 */
	status = check_decode_result(codec, &input->timestamp,
				     avframe.key_frame);
	if (status != PJ_SUCCESS)
	    return status;

	/* Check provided buffer size */
	if (vafp->framebytes > output_buf_len)
	    return PJ_ETOOSMALL;

	/* Get the decoded data */
	for (i = 0; i < ff->dec_vfi->plane_cnt; ++i) {
	    pj_uint8_t *p = avframe.data[i];

	    /* The decoded data may contain padding */
	    if (avframe.linesize[i]!=vafp->strides[i]) {
		/* Padding exists, copy line by line */
		pj_uint8_t *q_end;
                    
		q_end = q+vafp->plane_bytes[i];
		while(q < q_end) {
		    pj_memcpy(q, p, vafp->strides[i]);
		    q += vafp->strides[i];
		    p += avframe.linesize[i];
		}
	    } else {
		/* No padding, copy the whole plane */
		pj_memcpy(q, p, vafp->plane_bytes[i]);
		q += vafp->plane_bytes[i];
	    }
	}

	output->type = PJMEDIA_FRAME_TYPE_VIDEO;
        output->size = vafp->framebytes;
    } else {
	output->type = PJMEDIA_FRAME_TYPE_NONE;
	output->size = 0;
    }
    
    return PJ_SUCCESS;
}