static int prepare_sdp_description(RTSPContext *ctx, char *buf, int bufsize) { buf[0] = '\0'; av_dict_set(&ctx->sdp_fmtctx->metadata, "title", rtspconf->title, 0); snprintf(ctx->sdp_fmtctx->filename, sizeof(ctx->sdp_fmtctx->filename), "rtp://0.0.0.0"); av_sdp_create(&ctx->sdp_fmtctx, 1, buf, bufsize); return strlen(buf); }
static int sap_write_header(AVFormatContext *s) { struct SAPState *sap = s->priv_data; char host[1024], path[1024], url[1024], announce_addr[50] = ""; char *option_list; int port = 9875, base_port = 5004, i, pos = 0, same_port = 0, ttl = 255; AVFormatContext **contexts = NULL; int ret = 0; struct sockaddr_storage localaddr; socklen_t addrlen = sizeof(localaddr); int udp_fd; if (!ff_network_init()) return AVERROR(EIO); /* extract hostname and port */ av_url_split(NULL, 0, NULL, 0, host, sizeof(host), &base_port, path, sizeof(path), s->filename); if (base_port < 0) base_port = 5004; /* search for options */ option_list = strrchr(path, '?'); if (option_list) { char buf[50]; if (av_find_info_tag(buf, sizeof(buf), "announce_port", option_list)) { port = strtol(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "same_port", option_list)) { same_port = strtol(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "ttl", option_list)) { ttl = strtol(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "announce_addr", option_list)) { av_strlcpy(announce_addr, buf, sizeof(announce_addr)); } } if (!announce_addr[0]) { struct addrinfo hints = { 0 }, *ai = NULL; hints.ai_family = AF_UNSPEC; if (getaddrinfo(host, NULL, &hints, &ai)) { av_log(s, AV_LOG_ERROR, "Unable to resolve %s\n", host); ret = AVERROR(EIO); goto fail; } if (ai->ai_family == AF_INET) { /* Also known as sap.mcast.net */ av_strlcpy(announce_addr, "224.2.127.254", sizeof(announce_addr)); #if HAVE_STRUCT_SOCKADDR_IN6 } else if (ai->ai_family == AF_INET6) { /* With IPv6, you can use the same destination in many different * multicast subnets, to choose how far you want it routed. * This one is intended to be routed globally. */ av_strlcpy(announce_addr, "ff0e::2:7ffe", sizeof(announce_addr)); #endif } else { freeaddrinfo(ai); av_log(s, AV_LOG_ERROR, "Host %s resolved to unsupported " "address family\n", host); ret = AVERROR(EIO); goto fail; } freeaddrinfo(ai); } contexts = av_mallocz(sizeof(AVFormatContext*) * s->nb_streams); if (!contexts) { ret = AVERROR(ENOMEM); goto fail; } s->start_time_realtime = av_gettime(); for (i = 0; i < s->nb_streams; i++) { URLContext *fd; ff_url_join(url, sizeof(url), "rtp", NULL, host, base_port, "?ttl=%d", ttl); if (!same_port) base_port += 2; ret = ffurl_open(&fd, url, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL); if (ret) { ret = AVERROR(EIO); goto fail; } s->streams[i]->priv_data = contexts[i] = ff_rtp_chain_mux_open(s, s->streams[i], fd, 0); av_strlcpy(contexts[i]->filename, url, sizeof(contexts[i]->filename)); } ff_url_join(url, sizeof(url), "udp", NULL, announce_addr, port, "?ttl=%d&connect=1", ttl); ret = ffurl_open(&sap->ann_fd, url, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL); if (ret) { ret = AVERROR(EIO); goto fail; } udp_fd = ffurl_get_file_handle(sap->ann_fd); if (getsockname(udp_fd, (struct sockaddr*) &localaddr, &addrlen)) { ret = AVERROR(EIO); goto fail; } if (localaddr.ss_family != AF_INET #if HAVE_STRUCT_SOCKADDR_IN6 && localaddr.ss_family != AF_INET6 #endif ) { av_log(s, AV_LOG_ERROR, "Unsupported protocol family\n"); ret = AVERROR(EIO); goto fail; } sap->ann_size = 8192; sap->ann = av_mallocz(sap->ann_size); if (!sap->ann) { ret = AVERROR(EIO); goto fail; } sap->ann[pos] = (1 << 5); #if HAVE_STRUCT_SOCKADDR_IN6 if (localaddr.ss_family == AF_INET6) sap->ann[pos] |= 0x10; #endif pos++; sap->ann[pos++] = 0; /* Authentication length */ AV_WB16(&sap->ann[pos], av_get_random_seed()); pos += 2; if (localaddr.ss_family == AF_INET) { memcpy(&sap->ann[pos], &((struct sockaddr_in*)&localaddr)->sin_addr, sizeof(struct in_addr)); pos += sizeof(struct in_addr); #if HAVE_STRUCT_SOCKADDR_IN6 } else { memcpy(&sap->ann[pos], &((struct sockaddr_in6*)&localaddr)->sin6_addr, sizeof(struct in6_addr)); pos += sizeof(struct in6_addr); #endif } av_strlcpy(&sap->ann[pos], "application/sdp", sap->ann_size - pos); pos += strlen(&sap->ann[pos]) + 1; if (av_sdp_create(contexts, s->nb_streams, &sap->ann[pos], sap->ann_size - pos)) { ret = AVERROR_INVALIDDATA; goto fail; } av_freep(&contexts); av_log(s, AV_LOG_VERBOSE, "SDP:\n%s\n", &sap->ann[pos]); pos += strlen(&sap->ann[pos]); sap->ann_size = pos; if (sap->ann_size > sap->ann_fd->max_packet_size) { av_log(s, AV_LOG_ERROR, "Announcement too large to send in one " "packet\n"); goto fail; } return 0; fail: av_free(contexts); sap_write_close(s); return ret; }
int ff_rtsp_setup_output_streams(AVFormatContext *s, const char *addr) { RTSPState *rt = s->priv_data; RTSPMessageHeader reply1, *reply = &reply1; int i; char *sdp; AVFormatContext sdp_ctx, *ctx_array[1]; s->start_time_realtime = av_gettime(); /* Announce the stream */ sdp = av_mallocz(SDP_MAX_SIZE); if (sdp == NULL) return AVERROR(ENOMEM); /* We create the SDP based on the RTSP AVFormatContext where we * aren't allowed to change the filename field. (We create the SDP * based on the RTSP context since the contexts for the RTP streams * don't exist yet.) In order to specify a custom URL with the actual * peer IP instead of the originally specified hostname, we create * a temporary copy of the AVFormatContext, where the custom URL is set. * * FIXME: Create the SDP without copying the AVFormatContext. * This either requires setting up the RTP stream AVFormatContexts * already here (complicating things immensely) or getting a more * flexible SDP creation interface. */ sdp_ctx = *s; ff_url_join(sdp_ctx.filename, sizeof(sdp_ctx.filename), "rtsp", NULL, addr, -1, NULL); ctx_array[0] = &sdp_ctx; if (av_sdp_create(ctx_array, 1, sdp, SDP_MAX_SIZE)) { av_free(sdp); return AVERROR_INVALIDDATA; } av_log(s, AV_LOG_VERBOSE, "SDP:\n%s\n", sdp); ff_rtsp_send_cmd_with_content(s, "ANNOUNCE", rt->control_uri, "Content-Type: application/sdp\r\n", reply, NULL, sdp, strlen(sdp)); av_free(sdp); if (reply->status_code != RTSP_STATUS_OK) return AVERROR_INVALIDDATA; /* Set up the RTSPStreams for each AVStream */ for (i = 0; i < s->nb_streams; i++) { RTSPStream *rtsp_st; rtsp_st = av_mallocz(sizeof(RTSPStream)); if (!rtsp_st) return AVERROR(ENOMEM); dynarray_add(&rt->rtsp_streams, &rt->nb_rtsp_streams, rtsp_st); rtsp_st->stream_index = i; av_strlcpy(rtsp_st->control_url, rt->control_uri, sizeof(rtsp_st->control_url)); /* Note, this must match the relative uri set in the sdp content */ av_strlcatf(rtsp_st->control_url, sizeof(rtsp_st->control_url), "/streamid=%d", i); } return 0; }
int main(int argc, char **argv) { /* int i; char b[40]; char c[21]; HANDLE hConsole; int k; #ifdef _DEBUG _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); #endif for(i = 0; i < sizeof(b); ++i ) { b[i] = ' '; } b[255] = '\0'; system("color 5"); for(i = 0; i < 20; ++i) { c[i] = '>'; c[i+1] = '\0'; printf("Progress |%s%*s|\r",c,19-i,&""); Sleep(100); //printf("%s\r", b); } printf("\n"); printf("sizeof(structa_t) = %d\n", sizeof(structa_t)); printf("sizeof(structb_t) = %d\n", sizeof(structb_t)); printf("sizeof(structc_t) = %d\n", sizeof(structc_t)); printf("sizeof(structd_t) = %d\n", AV_TIME_BASE); hConsole = GetStdHandle(STD_OUTPUT_HANDLE); // you can loop k higher to see more color choices for(k = 1; k < 255; k++) { // pick the colorattribute k you want SetConsoleTextAttribute(hConsole, k); printf("%d I want to be nice today!",k); }*/ AVFormatContext *in_ctx = NULL, *out_ctx = NULL; AVInputFormat *file_iformat = NULL; AVOutputFormat *out_fmt = NULL; AVFrame *frame = NULL, *frameRGB = NULL; AVStream *st = NULL; AVCodecContext *codec_ctx = NULL, *pCodecCtx = NULL; AVCodec *codec = NULL, *pCodec = NULL; AVCodec dummy_codec = {0}; AVPacket pkt, p; AVBitStreamFilterContext *bsf = NULL; struct SwsContext *sws_ctx = NULL; BOOL tom = TRUE; char b[1024]; int err, i, ret, frameFinished, numBytes; const char *src_filename = "final.mp4"; int64_t timestamp; uint8_t buf[128]; uint8_t *buffer = NULL; int video_stream_idx = -1; int audio_stream_idx = -1; FILE* sdp_file; #ifdef _DEBUG _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); #endif /* register all formats and codecs */ av_register_all(); avformat_network_init(); av_log_set_level(AV_LOG_DEBUG); /* open input file, and allocate format context */ ret = avformat_open_input(&in_ctx, src_filename, NULL, NULL); if (ret < 0) { fprintf(stderr, "Could not open source file %s\n", src_filename); PAUSE_EXIT(1); } in_ctx->flags |= AVFMT_FLAG_GENPTS; ret = avformat_find_stream_info(in_ctx, NULL); if (ret < 0) { av_log(NULL, AV_LOG_FATAL, "%s: could not find codec parameters\n", src_filename); avformat_close_input(&in_ctx); PAUSE_EXIT(1); } av_dump_format(in_ctx, 0, src_filename, 0); for (i = 0; i < in_ctx->nb_streams; i++) { AVStream *st_ptr; AVCodecContext *coctx_ptr; if (in_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { if (in_ctx->streams[i]->codec->codec_id == CODEC_ID_MPEG4) { bsf = av_bitstream_filter_init("dump_extra"); } else if (in_ctx->streams[i]->codec->codec_id == CODEC_ID_H264) { fprintf(stderr, "Found h264 Stream\n"); bsf = av_bitstream_filter_init("h264_mp4toannexb"); } else { bsf = NULL; } pCodecCtx=in_ctx->streams[i]->codec; pCodec=avcodec_find_decoder(pCodecCtx->codec_id); if(pCodec==NULL) { fprintf(stderr, "Unsupported codec!\n"); return -1; // Codec not found } // Open codec if(avcodec_open2(pCodecCtx, pCodec, NULL)<0) return -1; // Could not open codec out_ctx = avformat_alloc_context(); out_fmt = av_guess_format("rtp", NULL, NULL); if (!out_fmt) { fprintf(stderr, "Unable for find the RTP format for output\n"); avformat_close_input(&in_ctx); PAUSE_EXIT(1); } out_ctx->oformat = out_fmt; //out_ctx->flags |= AVFMT_FLAG_NONBLOCK; st = avformat_new_stream(out_ctx, 0); if (!st) { fprintf(stderr, "Cannot allocate stream\n"); avformat_close_input(&in_ctx); PAUSE_EXIT(1); } dummy_codec.type = in_ctx->streams[i]->codec->codec_type; codec_ctx = st->codec; avcodec_get_context_defaults3(codec_ctx, &dummy_codec); avcodec_open2(codec_ctx, NULL, NULL); codec_ctx->codec_type = in_ctx->streams[i]->codec->codec_type; /* FIXME: global headers stuff... */ snprintf(out_ctx->filename, sizeof(out_ctx->filename), "rtp://%s:%d", "127.0.0.1", 55444); /* open the UDP sockets for RTP and RTCP */ if (!software_streaming) { printf("Distant Connection\n"); ret = avio_open(&out_ctx->pb, out_ctx->filename, AVIO_FLAG_WRITE); if (ret < 0) { fprintf(stderr, "Cannot open '%s'\n", out_ctx->filename); avformat_close_input(&in_ctx); PAUSE_EXIT(1); } } else { ret = avio_open_dyn_buf(&out_ctx->pb); out_ctx->pb->max_packet_size = 1460; printf("MAX packet size = %d\n",out_ctx->pb->max_packet_size); } st_ptr = in_ctx->streams[i]; coctx_ptr = st_ptr->codec; codec_ctx->codec_id = coctx_ptr->codec_id; codec_ctx->codec_type = coctx_ptr->codec_type; if(!codec_ctx->codec_tag) { codec_ctx->codec_tag = coctx_ptr->codec_tag; } codec_ctx->bit_rate = coctx_ptr->bit_rate; printf("\n\n\n\nFIRE!!!!! %d %d\n\n\n\n", codec_ctx->profile, codec_ctx->level); if(coctx_ptr->extradata_size) { codec_ctx->extradata = (uint8_t*)av_malloc(coctx_ptr->extradata_size); memcpy(codec_ctx->extradata, coctx_ptr->extradata, coctx_ptr->extradata_size); } else { codec_ctx->extradata = NULL; } codec_ctx->extradata_size = coctx_ptr->extradata_size; /* FIXME: ExtraData ??? */ if (codec_ctx->codec_id == CODEC_ID_H264) { printf("BINGO\n"); extradata_convert(codec_ctx); } if(out_ctx->oformat->flags & AVFMT_GLOBALHEADER) codec_ctx->flags |= CODEC_FLAG_GLOBAL_HEADER; if(av_q2d(coctx_ptr->time_base) > av_q2d(st_ptr->time_base) && av_q2d(st_ptr->time_base) < 1.0/1000) { codec_ctx->time_base = coctx_ptr->time_base; } else { codec_ctx->time_base = st_ptr->time_base; } switch(codec_ctx->codec_type) { case AVMEDIA_TYPE_AUDIO: codec_ctx->sample_rate = coctx_ptr->sample_rate; codec_ctx->time_base.den = 1; codec_ctx->time_base.num = coctx_ptr->sample_rate; codec_ctx->channels = coctx_ptr->channels; codec_ctx->frame_size = coctx_ptr->frame_size; codec_ctx->block_align= coctx_ptr->block_align; break; case AVMEDIA_TYPE_VIDEO: //printf("Pixel Format %d\n", coctx_ptr->pix_fmt); codec_ctx->pix_fmt = coctx_ptr->pix_fmt; codec_ctx->width = coctx_ptr->width; codec_ctx->height = coctx_ptr->height; codec_ctx->has_b_frames = coctx_ptr->has_b_frames; break; default: fprintf(stderr, "Strange Codec Type %d\n", codec_ctx->codec_type); PAUSE_EXIT(1); } ret = avformat_write_header(out_ctx, NULL); if (ret < 0) { fprintf(stderr, "Cannot Initialize output stream %d\n", i); //close_output(rtp_c->out_s[i]); continue; } av_dump_format(out_ctx, i, out_ctx->filename, 1); } } frame = avcodec_alloc_frame(); frameRGB = avcodec_alloc_frame(); // Determine required buffer size and allocate buffer numBytes=avpicture_get_size(PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height); buffer=(uint8_t *)av_malloc(numBytes*sizeof(uint8_t)); printf("Allocated %d", numBytes); sws_ctx = sws_getContext ( pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, PIX_FMT_RGB24, SWS_BILINEAR, NULL, NULL, NULL ); // Assign appropriate parts of buffer to image planes in pFrameRGB // Note that pFrameRGB is an AVFrame, but AVFrame is a superset // of AVPicture avpicture_fill((AVPicture *)frameRGB, buffer, PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height); av_sdp_create(&out_ctx,1,b,1024); printf("SDP : \n%s", b); sdp_file = fopen("rtp.sdp","w"); fprintf(sdp_file, "%s",b); fclose(sdp_file); i = 0; av_init_packet(&pkt); av_init_packet(&p); printf("Payload Size %d\n", *(uint8_t *)out_ctx->streams[0]->codec->extradata != 1); while (av_read_frame(in_ctx, &pkt) >= 0) { if (pkt.stream_index == 0) { int res; uint8_t *ptr; uint16_t ptr16; if (avcodec_decode_video2(pCodecCtx, frame, &frameFinished, &pkt) < 0 ) { fprintf(stderr, "Error decoding packet\n"); } /* if(frameFinished) { // Convert the image from its native format to RGB sws_scale ( sws_ctx, (uint8_t const * const *)frame->data, frame->linesize, 0, pCodecCtx->height, frameRGB->data, frameRGB->linesize ); // Save the frame to disk if(++i<=5) SaveFrame(frameRGB, pCodecCtx->width, pCodecCtx->height, i); }*/ printf("PTS %lld DTS%lld\n",pkt.pts,pkt.dts); printf("Got frame %s %d %s\n",STRING_BOOL(frameFinished), pkt.size, STRING_BOOL(pkt.flags & AV_PKT_FLAG_KEY)); //break; /*ret = av_bitstream_filter_filter(bsf, in_ctx->streams[pkt.stream_index]->codec, NULL, &p.data, &p.size, pkt.data, pkt.size, pkt.flags & AV_PKT_FLAG_KEY); if(ret > 0) { av_free_packet(&pkt); p.destruct = av_destruct_packet; } else if (ret < 0) { fprintf(stderr, "%s failed for stream %d, codec %s: ", bsf->filter->name, pkt.stream_index, in_ctx->streams[pkt.stream_index]->codec->codec->name); fprintf(stderr, "%d\n", ret); } pkt = p;*/ stream_convert(&pkt); printf("pkt size %d %d\n",pkt.size, pkt.flags); av_usleep(4000000); if (av_write_frame(out_ctx, &pkt) < 0) printf("MITSOS eisai!!!!\n"); int written_size = avio_close_dyn_buf(out_ctx->pb,&ptr); printf("Written Size %d\n", written_size); ((uint8_t*)&ptr16)[0] = *(ptr+2); ((uint8_t*)&ptr16)[1] = *(ptr+3); printf("CC adsasd%d\n", ptr16 ); printByte(ptr); printByte(ptr+1); //printf("Second Byte %d\n", *(ptr+1)); parseStream(ptr, written_size); printf("Version %d\n",(*(ptr) & 0xC0) >> 6); printf("Padding %d\n",(*(ptr) & 0x20) > 0); printf("Ext %d\n",(*(ptr) & 0x10) > 0); printf("CC %d\n",(*(ptr) & 0xF)); printf("Marker %d\n",(*(ptr+1) & 0x80) > 0); printf("Type %u\n",(*(ptr+1))); printf("Seq %d\n",(*((uint16_t*)((uint8_t*)ptr+2)))); ret = avio_open_dyn_buf(&out_ctx->pb); out_ctx->pb->max_packet_size = 1514; } av_free_packet(&pkt); }