static int per_client_init(RTSPContext *ctx) { int i; AVOutputFormat *fmt; // if((fmt = av_guess_format("rtp", NULL, NULL)) == NULL) { ga_error("RTP not supported.\n"); return -1; } if((ctx->sdp_fmtctx = avformat_alloc_context()) == NULL) { ga_error("create avformat context failed.\n"); return -1; } ctx->sdp_fmtctx->oformat = fmt; // video stream for(i = 0; i < video_source_channels(); i++) { if((ctx->sdp_vstream[i] = ga_avformat_new_stream( ctx->sdp_fmtctx, i, rtspconf->video_encoder_codec)) == NULL) { // ga_error("cannot create new video stream (%d:%d)\n", i, rtspconf->video_encoder_codec->id); return -1; } if((ctx->sdp_vencoder[i] = ga_avcodec_vencoder_init( ctx->sdp_vstream[i]->codec, rtspconf->video_encoder_codec, video_source_width(i), video_source_height(i), rtspconf->video_fps, rtspconf->vso)) == NULL) { // ga_error("cannot init video encoder\n"); return -1; } } // audio stream #ifdef ENABLE_AUDIO if((ctx->sdp_astream = ga_avformat_new_stream( ctx->sdp_fmtctx, video_source_channels(), rtspconf->audio_encoder_codec)) == NULL) { ga_error("cannot create new audio stream (%d)\n", rtspconf->audio_encoder_codec->id); return -1; } if((ctx->sdp_aencoder = ga_avcodec_aencoder_init( ctx->sdp_astream->codec, rtspconf->audio_encoder_codec, rtspconf->audio_bitrate, rtspconf->audio_samplerate, rtspconf->audio_channels, rtspconf->audio_codec_format, rtspconf->audio_codec_channel_layout)) == NULL) { ga_error("cannot init audio encoder\n"); return -1; } #endif return 0; }
static int rtp_new_av_stream(RTSPContext *ctx, struct sockaddr_in *sin, int streamid, enum AVCodecID codecid) { AVOutputFormat *fmt = NULL; AVFormatContext *fmtctx = NULL; AVStream *stream = NULL; AVCodecContext *encoder = NULL; uint8_t *dummybuf = NULL; // if(streamid > VIDEO_SOURCE_CHANNEL_MAX) { ga_error("invalid stream index (%d > %d)\n", streamid, VIDEO_SOURCE_CHANNEL_MAX); return -1; } if(codecid != rtspconf->video_encoder_codec->id && codecid != rtspconf->audio_encoder_codec->id) { ga_error("invalid codec (%d)\n", codecid); return -1; } if(ctx->fmtctx[streamid] != NULL) { ga_error("duplicated setup to an existing stream (%d)\n", streamid); return -1; } if((fmt = av_guess_format("rtp", NULL, NULL)) == NULL) { ga_error("RTP not supported.\n"); return -1; } if((fmtctx = avformat_alloc_context()) == NULL) { ga_error("create avformat context failed.\n"); return -1; } fmtctx->oformat = fmt; if(ctx->mtu > 0) { if(fmtctx->packet_size > 0) { fmtctx->packet_size = ctx->mtu < fmtctx->packet_size ? ctx->mtu : fmtctx->packet_size; } else { fmtctx->packet_size = ctx->mtu; } ga_error("RTP: packet size set to %d (configured: %d)\n", fmtctx->packet_size, ctx->mtu); } #ifdef HOLE_PUNCHING if(ffio_open_dyn_packet_buf(&fmtctx->pb, ctx->mtu) < 0) { ga_error("cannot open dynamic packet buffer\n"); return -1; } ga_error("RTP: Dynamic buffer opened, max_packet_size=%d.\n", (int) fmtctx->pb->max_packet_size); if(ctx->lower_transport[streamid] == RTSP_LOWER_TRANSPORT_UDP) { if(rtp_open_ports(ctx, streamid) < 0) { ga_error("RTP: open ports failed - %s\n", strerror(errno)); return -1; } } #else if(ctx->lower_transport[streamid] == RTSP_LOWER_TRANSPORT_UDP) { snprintf(fmtctx->filename, sizeof(fmtctx->filename), "rtp://%s:%d", inet_ntoa(sin->sin_addr), ntohs(sin->sin_port)); if(avio_open(&fmtctx->pb, fmtctx->filename, AVIO_FLAG_WRITE) < 0) { ga_error("cannot open URL: %s\n", fmtctx->filename); return -1; } ga_error("RTP/UDP: URL opened [%d]: %s, max_packet_size=%d\n", streamid, fmtctx->filename, fmtctx->pb->max_packet_size); } else if(ctx->lower_transport[streamid] == RTSP_LOWER_TRANSPORT_TCP) { // XXX: should we use avio_open_dyn_buf(&fmtctx->pb)? if(ffio_open_dyn_packet_buf(&fmtctx->pb, ctx->mtu) < 0) { ga_error("cannot open dynamic packet buffer\n"); return -1; } ga_error("RTP/TCP: Dynamic buffer opened, max_packet_size=%d.\n", (int) fmtctx->pb->max_packet_size); } #endif fmtctx->pb->seekable = 0; // if((stream = ga_avformat_new_stream(fmtctx, 0, codecid == rtspconf->video_encoder_codec->id ? rtspconf->video_encoder_codec : rtspconf->audio_encoder_codec)) == NULL) { ga_error("Cannot create new stream (%d)\n", codecid); return -1; } // if(codecid == rtspconf->video_encoder_codec->id) { encoder = ga_avcodec_vencoder_init( stream->codec, rtspconf->video_encoder_codec, video_source_out_width(streamid), video_source_out_height(streamid), rtspconf->video_fps, rtspconf->vso); } else if(codecid == rtspconf->audio_encoder_codec->id) { encoder = ga_avcodec_aencoder_init( stream->codec, rtspconf->audio_encoder_codec, rtspconf->audio_bitrate, rtspconf->audio_samplerate, rtspconf->audio_channels, rtspconf->audio_codec_format, rtspconf->audio_codec_channel_layout); } if(encoder == NULL) { ga_error("Cannot init encoder\n"); return -1; } // ctx->encoder[streamid] = encoder; ctx->stream[streamid] = stream; ctx->fmtctx[streamid] = fmtctx; // write header if(avformat_write_header(ctx->fmtctx[streamid], NULL) < 0) { ga_error("Cannot write stream id %d.\n", streamid); return -1; } #ifdef HOLE_PUNCHING avio_close_dyn_buf(ctx->fmtctx[streamid]->pb, &dummybuf); av_free(dummybuf); #else if(ctx->lower_transport[streamid] == RTSP_LOWER_TRANSPORT_TCP) { /*int rlen; rlen =*/ avio_close_dyn_buf(ctx->fmtctx[streamid]->pb, &dummybuf); av_free(dummybuf); } #endif return 0; }