コード例 #1
0
/*
 * url syntax: rtp://host:port[?option=val...]
 * option: 'multicast=1' : enable multicast
 *         'ttl=n'       : set the ttl value (for multicast only)
 *         'localport=n' : set the local port to n
 *
 */
static int rtp_open(URLContext *h, const char *uri, int flags)
{
    RTPContext *s;
    int port, is_output, is_multicast, ttl, local_port;
    char hostname[256];
    char buf[1024];
    char path[1024];
    const char *p;

    is_output = (flags & URL_WRONLY);

    s = av_mallocz(sizeof(RTPContext));
    if (!s)
        return AVERROR(ENOMEM);
    h->priv_data = s;

    url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &port,
              path, sizeof(path), uri);
    /* extract parameters */
    is_multicast = 0;
    ttl = -1;
    local_port = -1;
    p = strchr(uri, '?');
    if (p) {
        is_multicast = find_info_tag(buf, sizeof(buf), "multicast", p);
        if (find_info_tag(buf, sizeof(buf), "ttl", p)) {
            ttl = strtol(buf, NULL, 10);
        }
        if (find_info_tag(buf, sizeof(buf), "localport", p)) {
            local_port = strtol(buf, NULL, 10);
        }
    }

    build_udp_url(buf, sizeof(buf),
                  hostname, port, local_port, is_multicast, ttl);
    if (url_open(&s->rtp_hd, buf, flags) < 0)
        goto fail;
    local_port = udp_get_local_port(s->rtp_hd);
    /* XXX: need to open another connexion if the port is not even */

    /* well, should suppress localport in path */

    build_udp_url(buf, sizeof(buf),
                  hostname, port + 1, local_port + 1, is_multicast, ttl);
    if (url_open(&s->rtcp_hd, buf, flags) < 0)
        goto fail;

    /* just to ease handle access. XXX: need to suppress direct handle
       access */
    s->rtp_fd = udp_get_file_handle(s->rtp_hd);
    s->rtcp_fd = udp_get_file_handle(s->rtcp_hd);

    h->max_packet_size = url_get_max_packet_size(s->rtp_hd);
    h->is_streamed = 1;
    return 0;

fail:
    if (s->rtp_hd)
        url_close(s->rtp_hd);
    if (s->rtcp_hd)
        url_close(s->rtcp_hd);
    av_free(s);
    return AVERROR_IO;
}
コード例 #2
0
/* XXX: This class should really pass the picture parameters by a separate API
 * so that we can, by contract, enforce that the frame size can't suddenly
 * change on us. */
void Java_org_devtcg_rojocam_ffmpeg_RtpOutputContext_nativeWriteFrame(JNIEnv *env,
        jclass clazz, jint nativeInt, jbyteArray data, jlong frameTime,
        jint frameFormat, jint frameWidth, jint frameHeight,
        jint frameBitsPerPixel) {
    RtpOutputContext *rtpContext = (RtpOutputContext *)nativeInt;
    AVFormatContext *avContext;
    AVCodecContext *codec;
    AVStream *outputStream;
    AVPacket pkt;
    jbyte *data_c;
    int max_packet_size;
    uint8_t *rtp_data;
    int rtp_data_len;

    avContext = rtpContext->avContext;
    outputStream = avContext->streams[0];
    codec = outputStream->codec;

    if (rtpContext->tempFrame == NULL) {
        if (!first_frame_init(env, rtpContext, frameFormat,
                frameWidth, frameHeight)) {
            LOGE("Error initializing encoding buffers, cannot stream");
            return;
        }
    }

    data_c = (*env)->GetByteArrayElements(env, data, NULL);

    /* Convert the input arguments to an AVPacket, simulating it as though we
     * read this from the ffmpeg libraries but there was no need to do this as
     * it was passed into us already as a raw video frame. */
    int frameDuration = frameTime - rtpContext->lastFrameTime;
    bool frameEncoded = encode_video_frame(rtpContext,
            outputStream, rtpContext->tempFrame, rtpContext->imgConvert,
            rtpContext->tempEncodedBuf, sizeof(rtpContext->tempEncodedBuf),
            data_c, frameTime, frameDuration, frameFormat,
            frameWidth, frameHeight, frameBitsPerPixel, &pkt);
    rtpContext->lastFrameTime = frameTime;

    (*env)->ReleaseByteArrayElements(env, data, data_c, JNI_ABORT);

    if (frameEncoded) {
#if PROFILE_WRITE_FRAME
        struct timeval then;
        gettimeofday(&then, NULL);
#endif

        max_packet_size = url_get_max_packet_size(rtpContext->urlContext);
        url_open_dyn_packet_buf(&avContext->pb, max_packet_size);

        avContext->pb->seekable = 0;

        /* This organizes our encoded packet into RTP packet segments (but it
         * doesn't actually send anything over the network yet). */
        if (av_write_frame(avContext, &pkt) < 0) {
            jniThrowException(env, "java/io/IOException", "Error writing frame to output");
        }

        /* Actually deliver the packetized RTP data to the remote peer. */
        rtp_data_len = url_close_dyn_buf(avContext->pb, &rtp_data);
        exhaustive_send(rtpContext->urlContext, rtp_data, rtp_data_len);
        av_free(rtp_data);

        /* XXX: I dunno, ffserver.c does this... */
        outputStream->codec->frame_number++;

#if PROFILE_WRITE_FRAME
        store_elapsed(&rtpContext->write_time, &then);
#endif
    } else {
#if PROFILE_WRITE_TIME
        rtpContext->write_time = 0;
#endif
    }

#if PROFILE_WRITE_FRAME
    //LOGI("resample@%ld ms; encode@%ld ms; write@%ld ms",
     //       rtpContext->resampling_time, rtpContext->encoding_time,
      //      rtpContext->write_time);
#endif
}
コード例 #3
0
ファイル: rtpproto.c プロジェクト: gotomypc/ffmpeg_vc_ce
static int rtp_open(URLContext *h, const char *uri, int flags)
{
    RTPContext *s;
    int rtp_port, rtcp_port,
        is_output, ttl,
        local_rtp_port, local_rtcp_port, max_packet_size;
    char hostname[256];
    char buf[1024];
    char path[1024];
    const char *p;

    is_output = (flags & URL_WRONLY);

    s = av_mallocz(sizeof(RTPContext));
    if (!s)
        return AVERROR(ENOMEM);
    h->priv_data = s;

    av_url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &rtp_port,
                 path, sizeof(path), uri);
    /* extract parameters */
    ttl = -1;
    rtcp_port = rtp_port+1;
    local_rtp_port = -1;
    local_rtcp_port = -1;
    max_packet_size = -1;

    p = strchr(uri, '?');
    if (p) {
        if (find_info_tag(buf, sizeof(buf), "ttl", p)) {
            ttl = strtol(buf, NULL, 10);
        }
        if (find_info_tag(buf, sizeof(buf), "rtcpport", p)) {
            rtcp_port = strtol(buf, NULL, 10);
        }
        if (find_info_tag(buf, sizeof(buf), "localport", p)) {
            local_rtp_port = strtol(buf, NULL, 10);
        }
        if (find_info_tag(buf, sizeof(buf), "localrtpport", p)) {
            local_rtp_port = strtol(buf, NULL, 10);
        }
        if (find_info_tag(buf, sizeof(buf), "localrtcpport", p)) {
            local_rtcp_port = strtol(buf, NULL, 10);
        }
        if (find_info_tag(buf, sizeof(buf), "pkt_size", p)) {
            max_packet_size = strtol(buf, NULL, 10);
        }
    }

    build_udp_url(buf, sizeof(buf),
                  hostname, rtp_port, local_rtp_port, ttl, max_packet_size);
    if (url_open(&s->rtp_hd, buf, flags) < 0)
        goto fail;
    if (local_rtp_port>=0 && local_rtcp_port<0)
        local_rtcp_port = udp_get_local_port(s->rtp_hd) + 1;

    build_udp_url(buf, sizeof(buf),
                  hostname, rtcp_port, local_rtcp_port, ttl, max_packet_size);
    if (url_open(&s->rtcp_hd, buf, flags) < 0)
        goto fail;

    /* just to ease handle access. XXX: need to suppress direct handle
       access */
    s->rtp_fd = url_get_file_handle(s->rtp_hd);
    s->rtcp_fd = url_get_file_handle(s->rtcp_hd);

    h->max_packet_size = url_get_max_packet_size(s->rtp_hd);
    h->is_streamed = 1;
    return 0;

 fail:
    if (s->rtp_hd)
        url_close(s->rtp_hd);
    if (s->rtcp_hd)
        url_close(s->rtcp_hd);
    av_free(s);
    return AVERROR(EIO);
}
コード例 #4
0
jint Java_org_devtcg_rojocam_ffmpeg_RtpOutputContext_nativeCreate(JNIEnv *env,
        jclass clazz, jint streamConfigNativeInt, jlong nowNanoTime,
        jstring hostAddress, jint rtpPort) {
    FFStreamConfig *config = (FFStreamConfig *)streamConfigNativeInt;
    RtpOutputContext *rtpContext = NULL;
    AVFormatContext *avContext = NULL;
    AVStream *st = NULL;
    uint8_t *dummy_buf;
    int max_packet_size;

    rtpContext = av_mallocz(sizeof(RtpOutputContext));
    if (rtpContext == NULL) {
        jniThrowOOM(env);
        goto cleanup;
    }

    rtpContext->lastFrameTime = nowNanoTime;
    rtpContext->config = config;

    avContext = avformat_alloc_context();
    if (avContext == NULL) {
        jniThrowOOM(env);
        goto cleanup;
    }
    avContext->oformat = av_guess_format("rtp", NULL, NULL);
    if (avContext->oformat == NULL) {
        jniThrowException(env, "java/lang/IllegalStateException",
                "rtp avformat is not available");
        goto cleanup;
    }

    rtpContext->avContext = avContext;

    st = av_mallocz(sizeof(AVStream));
    if (st == NULL) {
        jniThrowOOM(env);
        goto cleanup;
    }
    avContext->nb_streams = 1;
    avContext->streams = av_malloc(avContext->nb_streams * sizeof(*avContext->streams));
    avContext->streams[0] = st;

    /* XXX: What would we be doing if we supported audio as well? */
    memcpy(st, config->streams[0], sizeof(AVStream));
    st->priv_data = NULL;

    const jbyte *hostAddress_str = (*env)->GetStringUTFChars(env,
            hostAddress, NULL);
    snprintf(avContext->filename, sizeof(avContext->filename),
            "rtp://%s:%d?localrtpport=5000&localrtcpport=5001",
            hostAddress_str, rtpPort);
    (*env)->ReleaseStringUTFChars(env, hostAddress, hostAddress_str);

    if (url_open(&rtpContext->urlContext,
            avContext->filename, URL_WRONLY) < 0) {
        LOGE("Cannot open url context for filename=%s", avContext->filename);
        jniThrowException(env, "java/io/IOException", "Unable to open URL");
        goto cleanup;
    }

    max_packet_size = url_get_max_packet_size(rtpContext->urlContext);

    /* XXX: No idea what purpose this serves... */
    url_open_dyn_packet_buf(&avContext->pb, max_packet_size);

    av_set_parameters(avContext, NULL);
    if (av_write_header(avContext) < 0) {
        jniThrowException(env, "java/io/IOException", "Unexpected error writing dummy RTP header");
        goto cleanup;
    }

    url_close_dyn_buf(avContext->pb, &dummy_buf);
    av_free(dummy_buf);

    return (jint)rtpContext;

cleanup:
    rtp_output_context_free(rtpContext);
    assert((*env)->ExceptionOccurred(env));

    return 0;
}