From 48c606f5765c4b5ca45a3717a6255353496d5779 Mon Sep 17 00:00:00 2001 From: Pedro Rodriguez Date: Mon, 25 Jun 2012 16:11:23 +0200 Subject: [PATCH 01/29] Added media files --- src/erizo/media/MediaProcessor.cpp | 784 +++++++++++++++++++++++++++++ src/erizo/media/MediaProcessor.h | 119 +++++ src/erizo/media/Test.cpp | 138 +++++ src/erizo/media/Test.h | 26 + 4 files changed, 1067 insertions(+) create mode 100644 src/erizo/media/MediaProcessor.cpp create mode 100644 src/erizo/media/MediaProcessor.h create mode 100644 src/erizo/media/Test.cpp create mode 100644 src/erizo/media/Test.h diff --git a/src/erizo/media/MediaProcessor.cpp b/src/erizo/media/MediaProcessor.cpp new file mode 100644 index 0000000000..2befb19361 --- /dev/null +++ b/src/erizo/media/MediaProcessor.cpp @@ -0,0 +1,784 @@ +#include "MediaProcessor.h" +#include +//UDPSocket *sock=NULL; +//UDPSocket *out=NULL; +std::string s; +unsigned short u; + +MediaProcessor::MediaProcessor() { + + audioCoder = 0; + audioDecoder = 0; + videoCoder = 0; + videoDecoder = 0; + + audioPackager = 0; + audioUnpackager = 0; + videoPackager = 0; + videoUnpackager = 0; + + avcodec_register_all(); + av_register_all(); +// avformat_network_init(); +} + +MediaProcessor::~MediaProcessor() { + + if (audioCoder == 1) { + avcodec_close(aCoderContext); + av_free(aCoderContext); + } + if (audioDecoder == 1) { + avcodec_close(aDecoderContext); + av_free(aDecoderContext); + } + + if (videoCoder == 1) { + avcodec_close(vCoderContext); + av_free(vCoderContext); + av_free(cPicture); + } + + if (videoDecoder == 1) { + avcodec_close(vDecoderContext); + av_free(vDecoderContext); + av_free(dPicture); + } +} + +bool MediaProcessor::initAudioCoder(const audioCodecInfo *audioCodec) { + + aCoder = avcodec_find_encoder(audioCodec->codec); + if (!aCoder){ + printf("Encoder de audio no encontrado"); + return false; + } + + aCoderContext = avcodec_alloc_context3(aCoder); + if (!aCoderContext) { + printf("Error de memoria en coder de audio"); + return false; + } + + aCoderContext->sample_fmt = AV_SAMPLE_FMT_S16; + aCoderContext->bit_rate = audioCodec->bitRate; + aCoderContext->sample_rate = audioCodec->sampleRate; + aCoderContext->channels = 1; + + if (avcodec_open2(aCoderContext, aCoder, NULL) < 0) { + printf("Error al abrir el coder de audio"); + return false; + } + + audioCoder = 1; + return true; +} + +bool MediaProcessor::initAudioDecoder(const audioCodecInfo *audioCodec) { + + aDecoder = avcodec_find_decoder(audioCodec->codec); + if (!aDecoder){ + printf("Decoder de audio no encontrado"); + return false; + } + + aDecoderContext = avcodec_alloc_context3(aDecoder); + if (!aDecoderContext) { + printf("Error de memoria en decoder de audio"); + return false; + } + + aDecoderContext->sample_fmt = AV_SAMPLE_FMT_S16; + aDecoderContext->bit_rate = audioCodec->bitRate; + aDecoderContext->sample_rate = audioCodec->sampleRate; + aDecoderContext->channels = 1; + + if (avcodec_open2(aDecoderContext, aDecoder, NULL) < 0) { + printf("Error al abrir el decoder de audio"); + return false; + } + + audioDecoder = 1; + return true; + +} + +bool MediaProcessor::initVideoCoder(const videoCodecInfo *videoCodec) { + + vCoder = avcodec_find_encoder(videoCodec->codec); + if (!vCoder){ + printf("Encoder de vídeo no encontrado"); + return false; + } + + vCoderContext = avcodec_alloc_context3(vCoder); + if (!vCoderContext) { + printf("Error de memoria en coder de vídeo"); + return false; + } + + vCoderContext->bit_rate = videoCodec->bitRate; + vCoderContext->bit_rate_tolerance = 1.1 * videoCodec->bitRate / videoCodec->frameRate; + vCoderContext->rc_max_rate = videoCodec->bitRate * 2; + + if (videoCodec->frameRate >= 1.0) { + vCoderContext->rc_buffer_size = videoCodec->bitRate; // 1 second stored, in bps + } else { + vCoderContext->rc_buffer_size = 1.1 * videoCodec->bitRate / videoCodec->frameRate; + } + + vCoderContext->rc_buffer_aggressivity = 1.0; + vCoderContext->gop_size = videoCodec->maxInter; + vCoderContext->max_b_frames= 0; + vCoderContext->me_method= ME_EPZS; + + vCoderContext->width = videoCodec->width; + vCoderContext->height = videoCodec->height; + vCoderContext->pix_fmt = PIX_FMT_YUV420P; + vCoderContext->time_base= (AVRational){1000, 1000*videoCodec->frameRate}; + + if (avcodec_open2(vCoderContext, vCoder, NULL) < 0) { + printf("Error al abrir el decoder de vídeo"); + return false; + } + + cPicture = avcodec_alloc_frame(); + if (!cPicture) { + printf("Error de memoria en frame del coder de vídeo"); + return false; + } + + videoCoder = 1; + return true; +} + +bool MediaProcessor::initVideoDecoder(const videoCodecInfo *videoCodec) { + + vDecoder = avcodec_find_decoder(videoCodec->codec); + if (!vDecoder){ + printf("Decoder de vídeo no encontrado"); + return false; + } + + vDecoderContext = avcodec_alloc_context3(vDecoder); + if (!vDecoderContext) { + printf("Error de memoria en decoder de vídeo"); + return false; + } + + vDecoderContext->width = videoCodec->width; + vDecoderContext->height = videoCodec->height; + + if (avcodec_open2(vDecoderContext, vDecoder, NULL) < 0) { + printf("Error al abrir el decoder de vídeo"); + return false; + } + + dPicture = avcodec_alloc_frame(); + if (!dPicture) { + printf("Error de memoria en frame del decoder de vídeo"); + return false; + } + + videoDecoder = 1; + return true; +} + +bool MediaProcessor::initAudioPackagerRTP(const RTPInfo *audioRTP) { + + aOutputFormatContext = avformat_alloc_context(); + if (!aOutputFormatContext){ + printf("Memory Error al inicializar audioPackager"); + return false; + } + + aOutputFormat = av_guess_format("rtp",NULL,NULL); + if (aOutputFormat == NULL){ + printf("Could not guess format al inicializar audioPackager"); + return false; + } + + aOutputFormatContext->oformat=aOutputFormat; + aOutputFormat->audio_codec = audioRTP->codec; + + audioPackager = 1; + return true; +} + +bool MediaProcessor::initAudioUnpackagerRTP(const RTPInfo *audioRTP) { + + aInputFormatContext = avformat_alloc_context(); + if (!aInputFormatContext){ + printf("Memory Error al inicializar audioUnpackager"); + return false; + } + + aInputFormat = av_find_input_format("rtp"); + if (aInputFormat == NULL){ + printf("Could not guess format al inicializar audioUnpackager"); + return false; + } + + //aInputFormat->flags = AVFMT_NOFILE; + aInputFormatContext->iformat = aInputFormat; + + audioUnpackager = 1; + return true; +} + +bool MediaProcessor::initVideoPackagerRTP(const RTPInfo *videoRTP) { +// +// vOutputFormatContext = avformat_alloc_context(); +// if (!vOutputFormatContext){ +// printf("Memory Error al inicializar videoPackager"); +// return false; +// } +// +// vOutputFormat = av_guess_format("rtp",NULL,NULL); +// if (vOutputFormat == NULL){ +// printf("Could not guess format al inicializar videoPackager"); +// return false; +// } +// +// vOutputFormatContext->oformat=vOutputFormat; +// vOutputFormat->video_codec = videoRTP->codec; + + vRTPInfo = (RTPInfo*)videoRTP; + vRTPInfo->seqNum = 0; + vRTPInfo->ssrc = 5; + + videoPackager = 1; + return true; +} + +int readPacket(void *opaque, uint8_t *buf, int buf_size) { + /* + if (sock==NULL){ + sock = new UDPSocket(5004); + printf("Abierto socket\n"); + } + + int a = sock->recvFrom(buf, buf_size, s, u); + rtpHeader *h = (rtpHeader*)buf; + h->payloadtype = 33; + if (a>12){ + buf = buf+12; + a-=12; + } + printf("Read packet %d, buf_size %d\n", a, buf_size); +*/ + return 0; + +} + + +int writePacket(void *opaque, uint8_t *buf, int buf_size) { + + printf("Write packet\n"); + + return 0; + + +} +bool MediaProcessor::initVideoUnpackagerRTP(const RTPInfo *videoRTP) { + + vInputFormatContext = avformat_alloc_context(); + if (!vInputFormatContext){ + printf("Memory Error al inicializar videoUnpackager"); + return false; + } + + vInputFormat = av_find_input_format("rtp"); + if (vInputFormat == NULL){ + printf("Could not find format al inicializar videoUnpackager"); + return false; + } + +// vInputFormat->flags |= AVFMT_NOFILE ; +// vInputFormatContext->flags |= AVFMT_NOFILE; + vInputFormatContext->iformat=vInputFormat; + + int size = 15000; + unsigned char *buff = (unsigned char*)av_malloc(size); + + AVIOContext *io = avio_alloc_context(buff, size, 0, NULL, &readPacket, &writePacket, NULL); + + vInputFormatContext->pb = io; +// vInputFormatContext->flags |= AVFMT_FLAG_CUSTOM_IO; + vInputFormatContext->video_codec_id = CODEC_ID_H264; + printf("Config %s\n", avformat_configuration()); + int res = avformat_open_input(&vInputFormatContext, "", vInputFormat, NULL); + printf("INPUT OPEN********************************************************%d \n", res); + AVInputFormat *fmt = NULL; + + videoUnpackager = 1; + return true; + +} + +int MediaProcessor::encodeAudio(char *inBuff, int nSamples, char *outBuff) { + + if (audioCoder == 0) { + printf("No se han inicializado los parámetros del audioCoder"); + return -1; + } + + //Puede fallar. Revisar samples. Cogido de libavcodec/utils.c del paso de avcodec_encode_audio a avcodec_encode_audio2 + //avcodec_encode_audio(aCoderContext, (unsigned char*)outBuff, nSamples*2, (short*)inBuff); + + AVPacket pkt; + AVFrame frame0; + AVFrame *frame; + int ret, samples_size, got_packet; + + av_init_packet(&pkt); + pkt.data = (unsigned char*)inBuff; + pkt.size = nSamples*2; + + + frame = &frame0; + avcodec_get_frame_defaults(frame); + + frame->nb_samples = nSamples; + + samples_size = av_samples_get_buffer_size(NULL, aCoderContext->channels, + frame->nb_samples, + aCoderContext->sample_fmt, 1); + + if ((ret = avcodec_fill_audio_frame(frame, aCoderContext->channels, + aCoderContext->sample_fmt, + (const uint8_t *)inBuff, samples_size, 1))) + return ret; + + frame->pts = AV_NOPTS_VALUE; + //aCoderContext->internal->sample_count += frame->nb_samples; + + got_packet = 0; + + ret = avcodec_encode_audio2(aCoderContext, &pkt, frame, &got_packet); + + if (!ret && got_packet && aCoderContext->coded_frame) { + aCoderContext->coded_frame->pts = pkt.pts; + aCoderContext->coded_frame->key_frame = !!(pkt.flags & AV_PKT_FLAG_KEY); + } + //ff_packet_free_side_data(&pkt); + + if (frame && frame->extended_data != frame->data) + av_freep(&frame->extended_data); + + return ret; + +} + +int MediaProcessor::decodeAudio(char *inBuff, int inBuffLen, char *outBuff) { + + if (audioDecoder == 0) { + printf("No se han inicializado los parámetros del audioDecoder\n"); + return -1; + } + + AVPacket avpkt; + int outSize; + int decSize = 0; + int len = -1; + uint8_t *decBuff = (uint8_t*)malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE); + + av_init_packet(&avpkt); + avpkt.data = (unsigned char*)inBuff; + avpkt.size = inBuffLen; + + while (avpkt.size > 0) { + + outSize = AVCODEC_MAX_AUDIO_FRAME_SIZE; + + + //Puede fallar. Cogido de libavcodec/utils.c del paso de avcodec_decode_audio3 a avcodec_decode_audio4 + //avcodec_decode_audio3(aDecoderContext, (short*)decBuff, &outSize, &avpkt); + + AVFrame frame; + int got_frame = 0; + + aDecoderContext->get_buffer = avcodec_default_get_buffer; + aDecoderContext->release_buffer = avcodec_default_release_buffer; + + len = avcodec_decode_audio4(aDecoderContext, &frame, &got_frame, &avpkt); + + if (len >= 0 && got_frame) { + int plane_size; + //int planar = av_sample_fmt_is_planar(aDecoderContext->sample_fmt); + int data_size = av_samples_get_buffer_size(&plane_size, aDecoderContext->channels, + frame.nb_samples, + aDecoderContext->sample_fmt, 1); + if (outSize < data_size) { + printf("output buffer size is too small for the current frame\n"); + return AVERROR(EINVAL); + } + + memcpy(decBuff, frame.extended_data[0], plane_size); + + /* Si hay más de un canal + if (planar && aDecoderContext->channels > 1) { + uint8_t *out = ((uint8_t *)decBuff) + plane_size; + for (int ch = 1; ch < aDecoderContext->channels; ch++) { + memcpy(out, frame.extended_data[ch], plane_size); + out += plane_size; + } + } + */ + + outSize = data_size; + } else { + outSize = 0; + } + + + + if (len < 0) { + printf("Error al decodificar audio\n"); + free(decBuff); + return -1; + } + + avpkt.size -= len; + avpkt.data += len; + + if (outSize <= 0) { + continue; + } + + memcpy(outBuff, decBuff, outSize); + outBuff += outSize; + decSize += outSize; + } + + free(decBuff); + + if (outSize <= 0) { + printf("Error de decodificación de audio debido a tamaño incorrecto"); + return -1; + } + + return decSize; + +} + +int MediaProcessor::encodeVideo(char *inBuff, int inBuffLen, char *outBuff, int outBuffLen) { + + if (videoCoder == 0) { + printf("No se han inicializado los parámetros del videoCoder"); + return -1; + } + + int size = vCoderContext->width * vCoderContext->height; + + cPicture->pts = AV_NOPTS_VALUE; + cPicture->data[0] = (unsigned char*)inBuff; + cPicture->data[1] = (unsigned char*)inBuff + size; + cPicture->data[2] = (unsigned char*)inBuff + size + size / 4; + cPicture->linesize[0] = vCoderContext->width; + cPicture->linesize[1] = vCoderContext->width / 2; + cPicture->linesize[2] = vCoderContext->width / 2; + + AVPacket pkt; + int ret = 0; + int got_packet = 0; + + if(outBuffLen < FF_MIN_BUFFER_SIZE){ + printf("buffer smaller than minimum sizeS"); + return -1; + } + + av_init_packet(&pkt); + pkt.data = (unsigned char*)outBuff; + pkt.size = outBuffLen; + + ret = avcodec_encode_video2(vCoderContext, &pkt, cPicture, &got_packet); + + if (!ret && got_packet && vCoderContext->coded_frame) { + vCoderContext->coded_frame->pts = pkt.pts; + vCoderContext->coded_frame->key_frame = !!(pkt.flags & AV_PKT_FLAG_KEY); + } + + /* free any side data since we cannot return it */ + if (pkt.side_data_elems > 0) { + int i; + for (i = 0; i < pkt.side_data_elems; i++) + av_free(pkt.side_data[i].data); + av_freep(&pkt.side_data); + pkt.side_data_elems = 0; + } + + return ret ? ret : pkt.size; + +} + +int MediaProcessor::decodeVideo(char *inBuff, int inBuffLen, char *outBuff, int outBuffLen, int *gotFrame) { + + if (videoDecoder == 0) { + printf("No se han inicializado los parámetros del videoDecoder"); + return -1; + } + + *gotFrame = 0; + + AVPacket avpkt; + + avpkt.data = (unsigned char*)inBuff; + avpkt.size = inBuffLen; + + int got_picture; + int len; + + while (avpkt.size > 0) { + + len = avcodec_decode_video2(vDecoderContext, dPicture, &got_picture, &avpkt); + + if (len < 0) { + printf("Error al decodificar frame de vídeo"); + return -1; + } + + if (got_picture) { + *gotFrame = 1; + goto decoding; + } + avpkt.size -= len; + avpkt.data += len; + } + + + + if (!got_picture) { + printf("Aún no tengo frame"); + return -1; + } + +decoding: + + int outSize= vDecoderContext->height*vDecoderContext->width; + + + if (outBuffLen < (outSize * 3/2) ) { + printf("No se ha rellenado el buffer???"); + return outSize*3/2; + } + + unsigned char *lum = (unsigned char*)outBuff; + unsigned char *cromU = (unsigned char*)outBuff + outSize; + unsigned char *cromV = (unsigned char*)outBuff + outSize + outSize / 4; + + unsigned char *src= NULL; + int src_linesize, dst_linesize; + + src_linesize= dPicture->linesize[0]; + dst_linesize= vDecoderContext->width; + src= dPicture->data[0]; + + for (int i= vDecoderContext->height; i > 0; i--) { + memcpy(lum, src, dst_linesize); + lum += dst_linesize; + src += src_linesize; + } + + src_linesize= dPicture->linesize[1]; + dst_linesize= vDecoderContext->width / 2; + src= dPicture->data[1]; + + for (int i= vDecoderContext->height / 2; i > 0; i--) { + memcpy(cromU, src, dst_linesize); + cromU += dst_linesize; + src += src_linesize; + } + + src_linesize= dPicture->linesize[2]; + dst_linesize= vDecoderContext->width / 2; + src= dPicture->data[2]; + + for (int i= vDecoderContext->height / 2; i > 0; i--) { + memcpy(cromV, src, dst_linesize); + cromV += dst_linesize; + src += src_linesize; + } + + return outSize*3/2; +} + + +int MediaProcessor::packageAudioRTP(char *inBuff, int inBuffLen, char *outBuff) { + + if (audioPackager == 0) { + printf("No se ha inicializado el codec de output audio RTP"); + return -1; + } + + AVIOContext *c = avio_alloc_context((unsigned char*)outBuff, 2000, 1, NULL, NULL, NULL, NULL); + + aOutputFormatContext->pb = c; + aOutputFormatContext->flags = AVFMT_NOFILE; + + AVPacket pkt; + av_init_packet(&pkt); + pkt.data = (unsigned char*)inBuff; + pkt.size = inBuffLen; + + int ret = av_write_frame(aOutputFormatContext,&pkt); + + av_free_packet(&pkt); + av_free(c); + + return ret; +} + +int MediaProcessor::unpackageAudioRTP(char *inBuff, int inBuffLen, char *outBuff) { + + + /* + if (audioUnpackager == 0) { + printf("No se ha inicializado el codec de input audio RTP"); + return -1; + } + + AVIOContext *c = avio_alloc_context((unsigned char*)inBuff, inBuffLen, 0, NULL, NULL, NULL, NULL); + + aInputFormatContext->pb = c; + //aInputFormatContext->flags = AVFMT_NOFILE; + aInputFormatContext->flags = AVFMT_FLAG_CUSTOM_IO; + + if (avformat_find_stream_info(aInputFormatContext, NULL) < 0) { + return -1; + } + + AVPacket pkt; + av_init_packet(&pkt); + + //aInputFormatContext->iformat->read_packet(aInputFormatContext, &pkt); + + + + + av_read_frame(aInputFormatContext, &pkt); + + + outBuff = (char*)pkt.data; + + int se = pkt.size; + + av_free_packet(&pkt); + av_free(c); + + return se; +*/ + + int l = inBuffLen - RTP_HEADER_LEN; + + inBuff += RTP_HEADER_LEN; + memcpy(outBuff, inBuff, l); + + return l; +} + +int MediaProcessor::packageVideoRTP(char *inBuff, int inBuffLen, char *outBuff) { + + if (videoPackager == 0) { + printf("No se ha inicailizado el codec de output vídeo RTP"); + return -1; + } + + int l = inBuffLen + RTP_HEADER_LEN; + + rtpHeader * head = (rtpHeader*)outBuff; + + timeval time; + gettimeofday(&time, NULL); + long millis = (time.tv_sec * 1000) + (time.tv_usec / 1000); + + head->version = 2; //v = 2 + head->extension = 0; + head->marker = 1; //n?0:1; + head->padding = 0; + head->cc = 0; + head->seqnum = htons(vRTPInfo->seqNum++); + head->timestamp = htonl(millis); + head->ssrc = htonl(vRTPInfo->ssrc); + head->payloadtype = 34;//32; + + outBuff += RTP_HEADER_LEN; + + memcpy(outBuff, inBuff, inBuffLen); + +// AVIOContext *c = avio_alloc_context((unsigned char*)outBuff, l, 1, NULL, NULL, NULL, NULL); +// +// vOutputFormatContext->pb = c; +// vOutputFormatContext->flags = AVFMT_NOFILE; +// +// AVPacket pkt; +// av_init_packet(&pkt); +// pkt.data = (unsigned char*)inBuff; +// pkt.size = inBuffLen; +// +// int ret = av_write_frame(vOutputFormatContext,&pkt); +// +// av_free_packet(&pkt); +// av_free(c); + + return l; +} + + + +int MediaProcessor::unpackageVideoRTP(char *inBuff, int inBuffLen, char *outBuff, int *gotFrame) { +/* + if (videoUnpackager == 0) { + printf("No se ha inicailizado el codec de input vídeo RTP"); + return -1; + } +*/ + *gotFrame = 0; + +// rtpHeader *head = (rtpHeader*)inBuff; +// +// int sec = ntohs(head->seqnum); +// int ssrc = ntohl(head->ssrc); +// unsigned long time = ntohl(head->timestamp); +// +// +// +// +// int l = inBuffLen - RTP_HEADER_LEN; +// +// inBuff += RTP_HEADER_LEN; +// +// memcpy(outBuff, inBuff, l); +// +// if(head->marker) { +// *gotFrame = 1; +// } + +// return l; + + +// if (avformat_find_stream_info(vInputFormatContext, NULL) < 0) { +// return -1; +// } + + AVPacket pkt; + av_init_packet(&pkt); + + //aInputFormatContext->iformat->read_packet(aInputFormatContext, &pkt); + + + int p = av_read_frame(vInputFormatContext, &pkt); + printf("Leido frame %d\n", p); + + + outBuff = (char*)pkt.data; + + int se = pkt.size; + + av_free_packet(&pkt); + + return se; + + +} + diff --git a/src/erizo/media/MediaProcessor.h b/src/erizo/media/MediaProcessor.h new file mode 100644 index 0000000000..901d908683 --- /dev/null +++ b/src/erizo/media/MediaProcessor.h @@ -0,0 +1,119 @@ +#ifndef MEDIAPROCESSOR_H_ +#define MEDIAPROCESSOR_H_ + +#include +#include +#include + + +extern "C" { + #include + #include + +} + +struct audioCodecInfo { + enum CodecID codec; + int bitRate; + int sampleRate; +}; + +struct videoCodecInfo { + enum CodecID codec; + int width; + int height; + int bitRate; + int frameRate; + int maxInter; +}; + +struct RTPInfo { + enum CodecID codec; + int seqNum; + int ssrc; +}; + +typedef struct +{ + uint32_t cc:4; + uint32_t extension:1; + uint32_t padding:1; + uint32_t version:2; + uint32_t payloadtype:7; + uint32_t marker:1; + uint32_t seqnum:16; + uint32_t timestamp; + uint32_t ssrc; +}rtpHeader; + + +#define RTP_HEADER_LEN 12; + +class MediaProcessor { +public: + MediaProcessor(); + virtual ~MediaProcessor(); + + bool initAudioCoder(const audioCodecInfo *audioCodec); + bool initAudioDecoder(const audioCodecInfo *audioCodec); + bool initVideoCoder(const videoCodecInfo *videoCodec); + bool initVideoDecoder(const videoCodecInfo *videoCodec); + + bool initAudioPackagerRTP(const RTPInfo *audioRTP); + bool initAudioUnpackagerRTP(const RTPInfo *audioRTP); + bool initVideoPackagerRTP(const RTPInfo *videoRTP); + bool initVideoUnpackagerRTP(const RTPInfo *videoRTP); + + int encodeAudio(char *inBuff, int nSamples, char *outBuff); + int decodeAudio(char *inBuff, int inBuffLen, char *outBuff); + int encodeVideo(char *inBuff, int inBuffLen, char *outBuff, int outBuffLen); + int decodeVideo(char *inBuff, int inBuffLen, char *outBuff, int outBuffLen, int *gotFrame); + + int packageAudioRTP(char *inBuff, int inBuffLen, char *outBuff); + int unpackageAudioRTP(char *inBuff, int inBuffLen, char *outBuff); + int packageVideoRTP(char *inBuff, int inBuffLen, char *outBuff); + int unpackageVideoRTP(char *inBuff, int inBuffLen, char *outBuff, int *gotFrame); + + //readFromFile + //writeTofile + //Encapsular + //Desencapsular + +private: + int audioCoder; + int audioDecoder; + int videoCoder; + int videoDecoder; + + int audioPackager; + int audioUnpackager; + int videoPackager; + int videoUnpackager; + + AVCodec *aCoder; + AVCodecContext *aCoderContext; + AVCodec *aDecoder; + AVCodecContext *aDecoderContext; + + AVCodec *vCoder; + AVCodecContext *vCoderContext; + AVFrame *cPicture; + AVCodec *vDecoder; + AVCodecContext *vDecoderContext; + AVFrame *dPicture; + + AVFormatContext *aInputFormatContext; + AVInputFormat *aInputFormat; + AVFormatContext *aOutputFormatContext; + AVOutputFormat *aOutputFormat; + + RTPInfo *vRTPInfo; + + AVFormatContext *vInputFormatContext; + AVInputFormat *vInputFormat; + AVFormatContext *vOutputFormatContext; + AVOutputFormat *vOutputFormat; + +}; + +#endif /* MEDIAPROCESSOR_H_ */ diff --git a/src/erizo/media/Test.cpp b/src/erizo/media/Test.cpp new file mode 100644 index 0000000000..08d1516c9d --- /dev/null +++ b/src/erizo/media/Test.cpp @@ -0,0 +1,138 @@ +#include "Test.h" + +Test::Test() { + // TODO Auto-generated constructor stub + mp = new MediaProcessor(); + + + +// audioCodecInfo *i = new audioCodecInfo; +// i->codec = CODEC_ID_AMR_NB; +// i->bitRate = 300000; +// i->sampleRate = 44100; +// mp->initAudioDecoder(i); + +// RTPInfo *r = new RTPInfo; +// r->codec = CODEC_ID_MP3; +// mp->initAudioUnpackagerRTP(r); + + + videoCodecInfo *v = new videoCodecInfo; + v->codec = CODEC_ID_MPEG2VIDEO; + //v->codec = CODEC_ID_MPEG4; + v->width = 176; + v->height = 144; + + mp->initVideoDecoder(v); + + videoCodecInfo *c = new videoCodecInfo; + //c->codec = CODEC_ID_MPEG2VIDEO; + c->codec = CODEC_ID_H263; + c->width = 176; + c->height = 144; + c->frameRate = 24; + c->bitRate = 1024; + c->maxInter = 0; + + mp->initVideoCoder(c); + + RTPInfo *r = new RTPInfo; + //r->codec = CODEC_ID_MPEG2VIDEO; +// r->codec = CODEC_ID_MPEG4; + mp->initVideoPackagerRTP(r); + mp->initVideoUnpackagerRTP(r); + + +// sock = new UDPSocket(5004); + boost::thread t = boost::thread(&Test::rec, this); + t.join(); +} + +Test::~Test() { + // TODO Auto-generated destructor stub + //sock->disconnect(); +} + +void Test::rec() { + + int outBuff2Size = 176*144*3/2; + + void *buff = malloc(2000); + char * outBuff = (char*)malloc(50000); + memset(outBuff, 0, 50000); + char * outBuff2 = (char*)malloc(outBuff2Size); + + int gotFrame = 0; + int size = 0; + int gotDecFrame = 0; + + std::string s; + unsigned short u; + + while(true) { + + memset(buff, 0, 2000); + +// int a = sock->recvFrom(buff, 2000, s, u); + + printf("\n********* RECEPCIÓN *********"); + int a = 5; + printf("\n\nBytes = %d", a); + + int b = mp->unpackageVideoRTP((char*)buff, a, outBuff, &gotFrame); + + printf("\nBytes desem = %d", b); + + size += b; + outBuff += b; + + if(gotFrame) { + + outBuff -= size; + + printf("\nTengo un frame desempaquetado!! Size = %d", size); + + int c; + + c = mp->decodeVideo(outBuff, size, outBuff2, outBuff2Size, &gotDecFrame); + printf("\nBytes dec = %d", c); + + printf("\n*****************************"); + + size = 0; + memset(outBuff, 0, 50000); + gotFrame = 0; + + if(gotDecFrame) { + printf("\nTengo un frame decodificado!!"); + gotDecFrame = 0; + send(outBuff2, c); + } + } + } + +} + +void Test::send(char *buff, int buffSize) { + + printf("\n********* ENVÍO *********"); + + char *buffSend = (char*)malloc(buffSize); + char *buffSend2 = (char*)malloc(buffSize); + + int a = mp->encodeVideo(buff, buffSize, buffSend, buffSize); + + printf("\nBytes codificados = %d", a); + + int b = mp->packageVideoRTP(buffSend, a, buffSend2); + + printf("\nBytes empaquetados = %d", b); + + //sock->sendTo(buffSend2, b, "toronado.dit.upm.es", 5005); + + free(buffSend); + free(buffSend2); + + printf("\n*************************"); +} + diff --git a/src/erizo/media/Test.h b/src/erizo/media/Test.h new file mode 100644 index 0000000000..2a73374384 --- /dev/null +++ b/src/erizo/media/Test.h @@ -0,0 +1,26 @@ +#include +#include +#include + +#include "MediaProcessor.h" + +#include +#include +#include + +#ifndef TEST_H_ +#define TEST_H_ + +class Test { +public: + Test(); + virtual ~Test(); + + void rec(); + void send(char *buff, int buffSize); + + //UDPSocket *sock; + MediaProcessor *mp; +}; + +#endif /* TEST_H_ */ From c4210aeca0d8b183dfd11404b5167afe6e7e473a Mon Sep 17 00:00:00 2001 From: Pedro Rodriguez Date: Mon, 25 Jun 2012 18:11:13 +0200 Subject: [PATCH 02/29] Compile all subdirectories of erizo to test media --- src/erizo/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/erizo/CMakeLists.txt b/src/erizo/CMakeLists.txt index 297c95ab64..f6fa0fb637 100644 --- a/src/erizo/CMakeLists.txt +++ b/src/erizo/CMakeLists.txt @@ -11,7 +11,7 @@ project (ERIZO) set(ERIZO_VERSION_MAJOR 0) set(ERIZO_VERSION_MINOR 1) -file(GLOB ERIZO_SOURCES ${ERIZO_SOURCE_DIR}/*.cpp ${ERIZO_SOURCE_DIR}/*.h) +file(GLOB_RECOURSE ERIZO_SOURCES ${ERIZO_SOURCE_DIR}/*.cpp ${ERIZO_SOURCE_DIR}/*.h) add_library(erizo SHARED ${ERIZO_SOURCES}) find_package(GTK2 REQUIRED gtk) # GTK2 From a98f3e6911841a109cbe03e051ae730c4f4661ca Mon Sep 17 00:00:00 2001 From: Pedro Rodriguez Date: Wed, 27 Jun 2012 11:51:51 +0200 Subject: [PATCH 03/29] Fixed to use asio for sockets --- src/erizo/media/MediaProcessor.cpp | 54 +++++++++++++++++------------- src/erizo/media/MediaProcessor.h | 9 +++++ src/erizo/media/Test.cpp | 47 +++++++++++++++----------- src/erizo/media/Test.h | 13 +++---- 4 files changed, 71 insertions(+), 52 deletions(-) diff --git a/src/erizo/media/MediaProcessor.cpp b/src/erizo/media/MediaProcessor.cpp index 2befb19361..b456561018 100644 --- a/src/erizo/media/MediaProcessor.cpp +++ b/src/erizo/media/MediaProcessor.cpp @@ -1,5 +1,9 @@ -#include "MediaProcessor.h" + #include + + +#include "MediaProcessor.h" + //UDPSocket *sock=NULL; //UDPSocket *out=NULL; std::string s; @@ -19,7 +23,7 @@ MediaProcessor::MediaProcessor() { avcodec_register_all(); av_register_all(); -// avformat_network_init(); + avformat_network_init(); } MediaProcessor::~MediaProcessor() { @@ -735,31 +739,33 @@ int MediaProcessor::unpackageVideoRTP(char *inBuff, int inBuffLen, char *outBuff */ *gotFrame = 0; -// rtpHeader *head = (rtpHeader*)inBuff; -// -// int sec = ntohs(head->seqnum); -// int ssrc = ntohl(head->ssrc); -// unsigned long time = ntohl(head->timestamp); -// -// -// -// -// int l = inBuffLen - RTP_HEADER_LEN; -// -// inBuff += RTP_HEADER_LEN; -// -// memcpy(outBuff, inBuff, l); -// -// if(head->marker) { -// *gotFrame = 1; -// } + rtpHeader* head = (rtpHeader*)inBuff; -// return l; + int sec = ntohs(head->seqnum); + int ssrc = ntohl(head->ssrc); + unsigned long time = ntohl(head->timestamp); -// if (avformat_find_stream_info(vInputFormatContext, NULL) < 0) { -// return -1; -// } + + + int l = inBuffLen - RTP_HEADER_LEN; + + inBuff += RTP_HEADER_LEN; + + memcpy(outBuff, inBuff, l); + vp8RtpHeader* vp8h = (vp8RtpHeader*)outBuff; + printf("Printf R %u, PartID %u , X %u \n\n", vp8h->R, vp8h->partId, vp8h->X); + + if(head->marker) { + *gotFrame = 1; + } + + return l; + + + if (avformat_find_stream_info(vInputFormatContext, NULL) < 0) { + return -1; + } AVPacket pkt; av_init_packet(&pkt); diff --git a/src/erizo/media/MediaProcessor.h b/src/erizo/media/MediaProcessor.h index 901d908683..4794dde1c8 100644 --- a/src/erizo/media/MediaProcessor.h +++ b/src/erizo/media/MediaProcessor.h @@ -46,6 +46,15 @@ typedef struct uint32_t ssrc; }rtpHeader; +typedef struct +{ + uint32_t partId:4; + uint32_t S:1; + uint32_t N:1; + uint32_t R:1; + uint32_t X:1; +}vp8RtpHeader; + #define RTP_HEADER_LEN 12; diff --git a/src/erizo/media/Test.cpp b/src/erizo/media/Test.cpp index 08d1516c9d..afb9615014 100644 --- a/src/erizo/media/Test.cpp +++ b/src/erizo/media/Test.cpp @@ -1,7 +1,15 @@ +#include +#include + +#include +#include + + #include "Test.h" +using boost::asio::ip::udp; + Test::Test() { - // TODO Auto-generated constructor stub mp = new MediaProcessor(); @@ -18,18 +26,18 @@ Test::Test() { videoCodecInfo *v = new videoCodecInfo; - v->codec = CODEC_ID_MPEG2VIDEO; - //v->codec = CODEC_ID_MPEG4; - v->width = 176; - v->height = 144; + v->codec = CODEC_ID_VP8; +// v->codec = CODEC_ID_MPEG4; + v->width = 706; + v->height = 396; mp->initVideoDecoder(v); videoCodecInfo *c = new videoCodecInfo; //c->codec = CODEC_ID_MPEG2VIDEO; - c->codec = CODEC_ID_H263; - c->width = 176; - c->height = 144; + c->codec = CODEC_ID_MPEG2VIDEO; + c->width = v->width; + c->height = v->height; c->frameRate = 24; c->bitRate = 1024; c->maxInter = 0; @@ -43,19 +51,20 @@ Test::Test() { mp->initVideoUnpackagerRTP(r); -// sock = new UDPSocket(5004); + ioservice_ = new boost::asio::io_service; + socket_ = new udp::socket(*ioservice_, udp::endpoint(udp::v4(),40000)); + boost::thread t = boost::thread(&Test::rec, this); t.join(); } Test::~Test() { - // TODO Auto-generated destructor stub //sock->disconnect(); } void Test::rec() { - int outBuff2Size = 176*144*3/2; + int outBuff2Size = 706*396*3/2; void *buff = malloc(2000); char * outBuff = (char*)malloc(50000); @@ -68,20 +77,20 @@ void Test::rec() { std::string s; unsigned short u; - + int a; while(true) { memset(buff, 0, 2000); // int a = sock->recvFrom(buff, 2000, s, u); - - printf("\n********* RECEPCIÓN *********"); - int a = 5; - printf("\n\nBytes = %d", a); + a = socket_->receive(boost::asio::buffer(buff, 2000)); + printf("********* RECEPCIÓN *********\n"); +// int a = 5; + printf("Bytes = %d\n", a); int b = mp->unpackageVideoRTP((char*)buff, a, outBuff, &gotFrame); - printf("\nBytes desem = %d", b); + printf("Bytes desem = %d\n", b); size += b; outBuff += b; @@ -90,12 +99,12 @@ void Test::rec() { outBuff -= size; - printf("\nTengo un frame desempaquetado!! Size = %d", size); + printf("Tengo un frame desempaquetado!! Size = %d\n", size); int c; c = mp->decodeVideo(outBuff, size, outBuff2, outBuff2Size, &gotDecFrame); - printf("\nBytes dec = %d", c); + printf("Bytes dec = %d\n", c); printf("\n*****************************"); diff --git a/src/erizo/media/Test.h b/src/erizo/media/Test.h index 2a73374384..f3be73045a 100644 --- a/src/erizo/media/Test.h +++ b/src/erizo/media/Test.h @@ -1,12 +1,5 @@ -#include -#include -#include - #include "MediaProcessor.h" - -#include -#include -#include +#include #ifndef TEST_H_ #define TEST_H_ @@ -18,8 +11,10 @@ class Test { void rec(); void send(char *buff, int buffSize); +private: - //UDPSocket *sock; + boost::asio::ip::udp::socket* socket_; + boost::asio::io_service* ioservice_; MediaProcessor *mp; }; From 0a81d79aab330ba7d5e7475e14fecf7b166587ab Mon Sep 17 00:00:00 2001 From: Pedro Rodriguez Date: Wed, 27 Jun 2012 11:52:24 +0200 Subject: [PATCH 04/29] Now using libav*: Updated CMake --- src/erizo/CMakeLists.txt | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/erizo/CMakeLists.txt b/src/erizo/CMakeLists.txt index f6fa0fb637..9b89f8b2d7 100644 --- a/src/erizo/CMakeLists.txt +++ b/src/erizo/CMakeLists.txt @@ -11,7 +11,7 @@ project (ERIZO) set(ERIZO_VERSION_MAJOR 0) set(ERIZO_VERSION_MINOR 1) -file(GLOB_RECOURSE ERIZO_SOURCES ${ERIZO_SOURCE_DIR}/*.cpp ${ERIZO_SOURCE_DIR}/*.h) +file(GLOB_RECURSE ERIZO_SOURCES ${ERIZO_SOURCE_DIR}/*.cpp ${ERIZO_SOURCE_DIR}/*.h) add_library(erizo SHARED ${ERIZO_SOURCES}) find_package(GTK2 REQUIRED gtk) # GTK2 @@ -23,9 +23,19 @@ endif(GTK2_FOUND) set (BOOST_LIBS thread regex) find_package(Boost COMPONENTS ${BOOST_LIBS} REQUIRED) target_link_libraries(erizo ${Boost_LIBRARIES}) + +#THE REST find_library(SRTP srtp) test_lib(${SRTP}) +set (LIBS ${LIBS} ${SRTP}) find_library(NICE nice) test_lib(${NICE}) +set (LIBS ${LIBS} ${NICE}) find_library(GTHREAD gthread-2.0) -target_link_libraries(erizo ${SRTP} ${NICE} ${GTHREAD}) +test_lib(${GTHREAD}) +set (LIBS ${LIBS} ${GTHREAD}) +find_library(AVCODEC avcodec) +set (LIBS ${LIBS} ${AVCODEC}) +find_library(AVFORMAT avformat) +set (LIBS ${LIBS} ${AVFORMAT}) +target_link_libraries(erizo ${LIBS}) From fe2e41285d6cfabe81ed02c24ecff893901d7d14 Mon Sep 17 00:00:00 2001 From: Pedro Rodriguez Date: Tue, 3 Jul 2012 11:50:24 +0200 Subject: [PATCH 05/29] Introduced vp8 rtp parsing --- src/CMakeLists.txt | 2 +- src/erizo/media/MediaProcessor.cpp | 328 ++++++++++++++--------------- src/erizo/media/Test.cpp | 11 +- src/erizo/media/Test.h | 3 + src/examples/hsam.cpp | 13 +- 5 files changed, 181 insertions(+), 176 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 801c06c6f7..85771c272d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 2.8) project (ERIZO_ALL) -set (COMPILE_EXAMPLES OFF) +set (COMPILE_EXAMPLES ON) add_subdirectory(${ERIZO_ALL_SOURCES}erizo) find_package (Doxygen) if(DOXYGEN_FOUND) diff --git a/src/erizo/media/MediaProcessor.cpp b/src/erizo/media/MediaProcessor.cpp index b456561018..bdcc44c5e2 100644 --- a/src/erizo/media/MediaProcessor.cpp +++ b/src/erizo/media/MediaProcessor.cpp @@ -1,7 +1,5 @@ - #include - #include "MediaProcessor.h" //UDPSocket *sock=NULL; @@ -53,7 +51,7 @@ MediaProcessor::~MediaProcessor() { bool MediaProcessor::initAudioCoder(const audioCodecInfo *audioCodec) { aCoder = avcodec_find_encoder(audioCodec->codec); - if (!aCoder){ + if (!aCoder) { printf("Encoder de audio no encontrado"); return false; } @@ -81,7 +79,7 @@ bool MediaProcessor::initAudioCoder(const audioCodecInfo *audioCodec) { bool MediaProcessor::initAudioDecoder(const audioCodecInfo *audioCodec) { aDecoder = avcodec_find_decoder(audioCodec->codec); - if (!aDecoder){ + if (!aDecoder) { printf("Decoder de audio no encontrado"); return false; } @@ -110,7 +108,7 @@ bool MediaProcessor::initAudioDecoder(const audioCodecInfo *audioCodec) { bool MediaProcessor::initVideoCoder(const videoCodecInfo *videoCodec) { vCoder = avcodec_find_encoder(videoCodec->codec); - if (!vCoder){ + if (!vCoder) { printf("Encoder de vídeo no encontrado"); return false; } @@ -122,24 +120,26 @@ bool MediaProcessor::initVideoCoder(const videoCodecInfo *videoCodec) { } vCoderContext->bit_rate = videoCodec->bitRate; - vCoderContext->bit_rate_tolerance = 1.1 * videoCodec->bitRate / videoCodec->frameRate; + vCoderContext->bit_rate_tolerance = 1.1 * videoCodec->bitRate + / videoCodec->frameRate; vCoderContext->rc_max_rate = videoCodec->bitRate * 2; if (videoCodec->frameRate >= 1.0) { vCoderContext->rc_buffer_size = videoCodec->bitRate; // 1 second stored, in bps } else { - vCoderContext->rc_buffer_size = 1.1 * videoCodec->bitRate / videoCodec->frameRate; + vCoderContext->rc_buffer_size = 1.1 * videoCodec->bitRate + / videoCodec->frameRate; } vCoderContext->rc_buffer_aggressivity = 1.0; vCoderContext->gop_size = videoCodec->maxInter; - vCoderContext->max_b_frames= 0; - vCoderContext->me_method= ME_EPZS; + vCoderContext->max_b_frames = 0; + vCoderContext->me_method = ME_EPZS; vCoderContext->width = videoCodec->width; vCoderContext->height = videoCodec->height; vCoderContext->pix_fmt = PIX_FMT_YUV420P; - vCoderContext->time_base= (AVRational){1000, 1000*videoCodec->frameRate}; + vCoderContext->time_base = (AVRational) {1000, 1000*videoCodec->frameRate}; if (avcodec_open2(vCoderContext, vCoder, NULL) < 0) { printf("Error al abrir el decoder de vídeo"); @@ -159,7 +159,7 @@ bool MediaProcessor::initVideoCoder(const videoCodecInfo *videoCodec) { bool MediaProcessor::initVideoDecoder(const videoCodecInfo *videoCodec) { vDecoder = avcodec_find_decoder(videoCodec->codec); - if (!vDecoder){ + if (!vDecoder) { printf("Decoder de vídeo no encontrado"); return false; } @@ -191,18 +191,18 @@ bool MediaProcessor::initVideoDecoder(const videoCodecInfo *videoCodec) { bool MediaProcessor::initAudioPackagerRTP(const RTPInfo *audioRTP) { aOutputFormatContext = avformat_alloc_context(); - if (!aOutputFormatContext){ + if (!aOutputFormatContext) { printf("Memory Error al inicializar audioPackager"); return false; } - aOutputFormat = av_guess_format("rtp",NULL,NULL); - if (aOutputFormat == NULL){ - printf("Could not guess format al inicializar audioPackager"); - return false; + aOutputFormat = av_guess_format("rtp", NULL, NULL); + if (aOutputFormat == NULL) { + printf("Could not guess format al inicializar audioPackager"); + return false; } - aOutputFormatContext->oformat=aOutputFormat; + aOutputFormatContext->oformat = aOutputFormat; aOutputFormat->audio_codec = audioRTP->codec; audioPackager = 1; @@ -212,15 +212,15 @@ bool MediaProcessor::initAudioPackagerRTP(const RTPInfo *audioRTP) { bool MediaProcessor::initAudioUnpackagerRTP(const RTPInfo *audioRTP) { aInputFormatContext = avformat_alloc_context(); - if (!aInputFormatContext){ + if (!aInputFormatContext) { printf("Memory Error al inicializar audioUnpackager"); return false; } aInputFormat = av_find_input_format("rtp"); - if (aInputFormat == NULL){ - printf("Could not guess format al inicializar audioUnpackager"); - return false; + if (aInputFormat == NULL) { + printf("Could not guess format al inicializar audioUnpackager"); + return false; } //aInputFormat->flags = AVFMT_NOFILE; @@ -247,7 +247,7 @@ bool MediaProcessor::initVideoPackagerRTP(const RTPInfo *videoRTP) { // vOutputFormatContext->oformat=vOutputFormat; // vOutputFormat->video_codec = videoRTP->codec; - vRTPInfo = (RTPInfo*)videoRTP; + vRTPInfo = (RTPInfo*) videoRTP; vRTPInfo->seqNum = 0; vRTPInfo->ssrc = 5; @@ -257,62 +257,63 @@ bool MediaProcessor::initVideoPackagerRTP(const RTPInfo *videoRTP) { int readPacket(void *opaque, uint8_t *buf, int buf_size) { /* - if (sock==NULL){ - sock = new UDPSocket(5004); - printf("Abierto socket\n"); - } - - int a = sock->recvFrom(buf, buf_size, s, u); - rtpHeader *h = (rtpHeader*)buf; - h->payloadtype = 33; - if (a>12){ - buf = buf+12; - a-=12; - } - printf("Read packet %d, buf_size %d\n", a, buf_size); -*/ + if (sock==NULL){ + sock = new UDPSocket(5004); + printf("Abierto socket\n"); + } + + int a = sock->recvFrom(buf, buf_size, s, u); + rtpHeader *h = (rtpHeader*)buf; + h->payloadtype = 33; + if (a>12){ + buf = buf+12; + a-=12; + } + printf("Read packet %d, buf_size %d\n", a, buf_size); + */ return 0; } - int writePacket(void *opaque, uint8_t *buf, int buf_size) { printf("Write packet\n"); return 0; - } bool MediaProcessor::initVideoUnpackagerRTP(const RTPInfo *videoRTP) { vInputFormatContext = avformat_alloc_context(); - if (!vInputFormatContext){ + if (!vInputFormatContext) { printf("Memory Error al inicializar videoUnpackager"); return false; } vInputFormat = av_find_input_format("rtp"); - if (vInputFormat == NULL){ - printf("Could not find format al inicializar videoUnpackager"); - return false; + if (vInputFormat == NULL) { + printf("Could not find format al inicializar videoUnpackager"); + return false; } // vInputFormat->flags |= AVFMT_NOFILE ; // vInputFormatContext->flags |= AVFMT_NOFILE; - vInputFormatContext->iformat=vInputFormat; + vInputFormatContext->iformat = vInputFormat; int size = 15000; - unsigned char *buff = (unsigned char*)av_malloc(size); + unsigned char *buff = (unsigned char*) av_malloc(size); - AVIOContext *io = avio_alloc_context(buff, size, 0, NULL, &readPacket, &writePacket, NULL); + AVIOContext *io = avio_alloc_context(buff, size, 0, NULL, &readPacket, + &writePacket, NULL); vInputFormatContext->pb = io; // vInputFormatContext->flags |= AVFMT_FLAG_CUSTOM_IO; vInputFormatContext->video_codec_id = CODEC_ID_H264; printf("Config %s\n", avformat_configuration()); int res = avformat_open_input(&vInputFormatContext, "", vInputFormat, NULL); - printf("INPUT OPEN********************************************************%d \n", res); + printf( + "INPUT OPEN********************************************************%d \n", + res); AVInputFormat *fmt = NULL; videoUnpackager = 1; @@ -336,9 +337,8 @@ int MediaProcessor::encodeAudio(char *inBuff, int nSamples, char *outBuff) { int ret, samples_size, got_packet; av_init_packet(&pkt); - pkt.data = (unsigned char*)inBuff; - pkt.size = nSamples*2; - + pkt.data = (unsigned char*) inBuff; + pkt.size = nSamples * 2; frame = &frame0; avcodec_get_frame_defaults(frame); @@ -346,12 +346,11 @@ int MediaProcessor::encodeAudio(char *inBuff, int nSamples, char *outBuff) { frame->nb_samples = nSamples; samples_size = av_samples_get_buffer_size(NULL, aCoderContext->channels, - frame->nb_samples, - aCoderContext->sample_fmt, 1); + frame->nb_samples, aCoderContext->sample_fmt, 1); if ((ret = avcodec_fill_audio_frame(frame, aCoderContext->channels, - aCoderContext->sample_fmt, - (const uint8_t *)inBuff, samples_size, 1))) + aCoderContext->sample_fmt, (const uint8_t *) inBuff, samples_size, + 1))) return ret; frame->pts = AV_NOPTS_VALUE; @@ -385,17 +384,16 @@ int MediaProcessor::decodeAudio(char *inBuff, int inBuffLen, char *outBuff) { int outSize; int decSize = 0; int len = -1; - uint8_t *decBuff = (uint8_t*)malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE); + uint8_t *decBuff = (uint8_t*) malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE); av_init_packet(&avpkt); - avpkt.data = (unsigned char*)inBuff; + avpkt.data = (unsigned char*) inBuff; avpkt.size = inBuffLen; while (avpkt.size > 0) { outSize = AVCODEC_MAX_AUDIO_FRAME_SIZE; - //Puede fallar. Cogido de libavcodec/utils.c del paso de avcodec_decode_audio3 a avcodec_decode_audio4 //avcodec_decode_audio3(aDecoderContext, (short*)decBuff, &outSize, &avpkt); @@ -405,38 +403,38 @@ int MediaProcessor::decodeAudio(char *inBuff, int inBuffLen, char *outBuff) { aDecoderContext->get_buffer = avcodec_default_get_buffer; aDecoderContext->release_buffer = avcodec_default_release_buffer; - len = avcodec_decode_audio4(aDecoderContext, &frame, &got_frame, &avpkt); + len = avcodec_decode_audio4(aDecoderContext, &frame, &got_frame, + &avpkt); if (len >= 0 && got_frame) { int plane_size; //int planar = av_sample_fmt_is_planar(aDecoderContext->sample_fmt); - int data_size = av_samples_get_buffer_size(&plane_size, aDecoderContext->channels, - frame.nb_samples, - aDecoderContext->sample_fmt, 1); + int data_size = av_samples_get_buffer_size(&plane_size, + aDecoderContext->channels, frame.nb_samples, + aDecoderContext->sample_fmt, 1); if (outSize < data_size) { - printf("output buffer size is too small for the current frame\n"); + printf( + "output buffer size is too small for the current frame\n"); return AVERROR(EINVAL); } memcpy(decBuff, frame.extended_data[0], plane_size); /* Si hay más de un canal - if (planar && aDecoderContext->channels > 1) { - uint8_t *out = ((uint8_t *)decBuff) + plane_size; - for (int ch = 1; ch < aDecoderContext->channels; ch++) { - memcpy(out, frame.extended_data[ch], plane_size); - out += plane_size; - } - } - */ + if (planar && aDecoderContext->channels > 1) { + uint8_t *out = ((uint8_t *)decBuff) + plane_size; + for (int ch = 1; ch < aDecoderContext->channels; ch++) { + memcpy(out, frame.extended_data[ch], plane_size); + out += plane_size; + } + } + */ outSize = data_size; } else { outSize = 0; } - - if (len < 0) { printf("Error al decodificar audio\n"); free(decBuff); @@ -466,7 +464,8 @@ int MediaProcessor::decodeAudio(char *inBuff, int inBuffLen, char *outBuff) { } -int MediaProcessor::encodeVideo(char *inBuff, int inBuffLen, char *outBuff, int outBuffLen) { +int MediaProcessor::encodeVideo(char *inBuff, int inBuffLen, char *outBuff, + int outBuffLen) { if (videoCoder == 0) { printf("No se han inicializado los parámetros del videoCoder"); @@ -476,9 +475,9 @@ int MediaProcessor::encodeVideo(char *inBuff, int inBuffLen, char *outBuff, int int size = vCoderContext->width * vCoderContext->height; cPicture->pts = AV_NOPTS_VALUE; - cPicture->data[0] = (unsigned char*)inBuff; - cPicture->data[1] = (unsigned char*)inBuff + size; - cPicture->data[2] = (unsigned char*)inBuff + size + size / 4; + cPicture->data[0] = (unsigned char*) inBuff; + cPicture->data[1] = (unsigned char*) inBuff + size; + cPicture->data[2] = (unsigned char*) inBuff + size + size / 4; cPicture->linesize[0] = vCoderContext->width; cPicture->linesize[1] = vCoderContext->width / 2; cPicture->linesize[2] = vCoderContext->width / 2; @@ -487,19 +486,19 @@ int MediaProcessor::encodeVideo(char *inBuff, int inBuffLen, char *outBuff, int int ret = 0; int got_packet = 0; - if(outBuffLen < FF_MIN_BUFFER_SIZE){ + if (outBuffLen < FF_MIN_BUFFER_SIZE) { printf("buffer smaller than minimum sizeS"); return -1; } av_init_packet(&pkt); - pkt.data = (unsigned char*)outBuff; + pkt.data = (unsigned char*) outBuff; pkt.size = outBuffLen; ret = avcodec_encode_video2(vCoderContext, &pkt, cPicture, &got_packet); if (!ret && got_packet && vCoderContext->coded_frame) { - vCoderContext->coded_frame->pts = pkt.pts; + vCoderContext->coded_frame->pts = pkt.pts; vCoderContext->coded_frame->key_frame = !!(pkt.flags & AV_PKT_FLAG_KEY); } @@ -516,7 +515,8 @@ int MediaProcessor::encodeVideo(char *inBuff, int inBuffLen, char *outBuff, int } -int MediaProcessor::decodeVideo(char *inBuff, int inBuffLen, char *outBuff, int outBuffLen, int *gotFrame) { +int MediaProcessor::decodeVideo(char *inBuff, int inBuffLen, char *outBuff, + int outBuffLen, int *gotFrame) { if (videoDecoder == 0) { printf("No se han inicializado los parámetros del videoDecoder"); @@ -527,7 +527,7 @@ int MediaProcessor::decodeVideo(char *inBuff, int inBuffLen, char *outBuff, int AVPacket avpkt; - avpkt.data = (unsigned char*)inBuff; + avpkt.data = (unsigned char*) inBuff; avpkt.size = inBuffLen; int got_picture; @@ -535,7 +535,8 @@ int MediaProcessor::decodeVideo(char *inBuff, int inBuffLen, char *outBuff, int while (avpkt.size > 0) { - len = avcodec_decode_video2(vDecoderContext, dPicture, &got_picture, &avpkt); + len = avcodec_decode_video2(vDecoderContext, dPicture, &got_picture, + &avpkt); if (len < 0) { printf("Error al decodificar frame de vídeo"); @@ -550,82 +551,80 @@ int MediaProcessor::decodeVideo(char *inBuff, int inBuffLen, char *outBuff, int avpkt.data += len; } - - if (!got_picture) { printf("Aún no tengo frame"); return -1; } -decoding: + decoding: - int outSize= vDecoderContext->height*vDecoderContext->width; + int outSize = vDecoderContext->height * vDecoderContext->width; - - if (outBuffLen < (outSize * 3/2) ) { + if (outBuffLen < (outSize * 3 / 2)) { printf("No se ha rellenado el buffer???"); - return outSize*3/2; + return outSize * 3 / 2; } - unsigned char *lum = (unsigned char*)outBuff; - unsigned char *cromU = (unsigned char*)outBuff + outSize; - unsigned char *cromV = (unsigned char*)outBuff + outSize + outSize / 4; + unsigned char *lum = (unsigned char*) outBuff; + unsigned char *cromU = (unsigned char*) outBuff + outSize; + unsigned char *cromV = (unsigned char*) outBuff + outSize + outSize / 4; - unsigned char *src= NULL; + unsigned char *src = NULL; int src_linesize, dst_linesize; - src_linesize= dPicture->linesize[0]; - dst_linesize= vDecoderContext->width; - src= dPicture->data[0]; + src_linesize = dPicture->linesize[0]; + dst_linesize = vDecoderContext->width; + src = dPicture->data[0]; - for (int i= vDecoderContext->height; i > 0; i--) { + for (int i = vDecoderContext->height; i > 0; i--) { memcpy(lum, src, dst_linesize); lum += dst_linesize; src += src_linesize; } - src_linesize= dPicture->linesize[1]; - dst_linesize= vDecoderContext->width / 2; - src= dPicture->data[1]; + src_linesize = dPicture->linesize[1]; + dst_linesize = vDecoderContext->width / 2; + src = dPicture->data[1]; - for (int i= vDecoderContext->height / 2; i > 0; i--) { + for (int i = vDecoderContext->height / 2; i > 0; i--) { memcpy(cromU, src, dst_linesize); cromU += dst_linesize; - src += src_linesize; + src += src_linesize; } - src_linesize= dPicture->linesize[2]; - dst_linesize= vDecoderContext->width / 2; - src= dPicture->data[2]; + src_linesize = dPicture->linesize[2]; + dst_linesize = vDecoderContext->width / 2; + src = dPicture->data[2]; - for (int i= vDecoderContext->height / 2; i > 0; i--) { + for (int i = vDecoderContext->height / 2; i > 0; i--) { memcpy(cromV, src, dst_linesize); cromV += dst_linesize; - src += src_linesize; + src += src_linesize; } - return outSize*3/2; + return outSize * 3 / 2; } - -int MediaProcessor::packageAudioRTP(char *inBuff, int inBuffLen, char *outBuff) { +int MediaProcessor::packageAudioRTP(char *inBuff, int inBuffLen, + char *outBuff) { if (audioPackager == 0) { printf("No se ha inicializado el codec de output audio RTP"); return -1; } - AVIOContext *c = avio_alloc_context((unsigned char*)outBuff, 2000, 1, NULL, NULL, NULL, NULL); + AVIOContext *c = avio_alloc_context((unsigned char*) outBuff, 2000, 1, NULL, + NULL, NULL, NULL); aOutputFormatContext->pb = c; aOutputFormatContext->flags = AVFMT_NOFILE; AVPacket pkt; av_init_packet(&pkt); - pkt.data = (unsigned char*)inBuff; + pkt.data = (unsigned char*) inBuff; pkt.size = inBuffLen; - int ret = av_write_frame(aOutputFormatContext,&pkt); + int ret = av_write_frame(aOutputFormatContext, &pkt); av_free_packet(&pkt); av_free(c); @@ -633,45 +632,45 @@ int MediaProcessor::packageAudioRTP(char *inBuff, int inBuffLen, char *outBuff) return ret; } -int MediaProcessor::unpackageAudioRTP(char *inBuff, int inBuffLen, char *outBuff) { - +int MediaProcessor::unpackageAudioRTP(char *inBuff, int inBuffLen, + char *outBuff) { /* - if (audioUnpackager == 0) { - printf("No se ha inicializado el codec de input audio RTP"); - return -1; - } + if (audioUnpackager == 0) { + printf("No se ha inicializado el codec de input audio RTP"); + return -1; + } - AVIOContext *c = avio_alloc_context((unsigned char*)inBuff, inBuffLen, 0, NULL, NULL, NULL, NULL); + AVIOContext *c = avio_alloc_context((unsigned char*)inBuff, inBuffLen, 0, NULL, NULL, NULL, NULL); - aInputFormatContext->pb = c; - //aInputFormatContext->flags = AVFMT_NOFILE; - aInputFormatContext->flags = AVFMT_FLAG_CUSTOM_IO; + aInputFormatContext->pb = c; + //aInputFormatContext->flags = AVFMT_NOFILE; + aInputFormatContext->flags = AVFMT_FLAG_CUSTOM_IO; - if (avformat_find_stream_info(aInputFormatContext, NULL) < 0) { - return -1; - } + if (avformat_find_stream_info(aInputFormatContext, NULL) < 0) { + return -1; + } - AVPacket pkt; - av_init_packet(&pkt); + AVPacket pkt; + av_init_packet(&pkt); - //aInputFormatContext->iformat->read_packet(aInputFormatContext, &pkt); + //aInputFormatContext->iformat->read_packet(aInputFormatContext, &pkt); - av_read_frame(aInputFormatContext, &pkt); + av_read_frame(aInputFormatContext, &pkt); - outBuff = (char*)pkt.data; + outBuff = (char*)pkt.data; - int se = pkt.size; + int se = pkt.size; - av_free_packet(&pkt); - av_free(c); + av_free_packet(&pkt); + av_free(c); - return se; -*/ + return se; + */ int l = inBuffLen - RTP_HEADER_LEN; @@ -681,7 +680,8 @@ int MediaProcessor::unpackageAudioRTP(char *inBuff, int inBuffLen, char *outBuff return l; } -int MediaProcessor::packageVideoRTP(char *inBuff, int inBuffLen, char *outBuff) { +int MediaProcessor::packageVideoRTP(char *inBuff, int inBuffLen, + char *outBuff) { if (videoPackager == 0) { printf("No se ha inicailizado el codec de output vídeo RTP"); @@ -690,21 +690,21 @@ int MediaProcessor::packageVideoRTP(char *inBuff, int inBuffLen, char *outBuff) int l = inBuffLen + RTP_HEADER_LEN; - rtpHeader * head = (rtpHeader*)outBuff; + rtpHeader * head = (rtpHeader*) outBuff; timeval time; gettimeofday(&time, NULL); long millis = (time.tv_sec * 1000) + (time.tv_usec / 1000); - head->version = 2; //v = 2 - head->extension = 0; - head->marker = 1; //n?0:1; - head->padding = 0; - head->cc = 0; - head->seqnum = htons(vRTPInfo->seqNum++); - head->timestamp = htonl(millis); - head->ssrc = htonl(vRTPInfo->ssrc); - head->payloadtype = 34;//32; + head->version = 2; //v = 2 + head->extension = 0; + head->marker = 1; //n?0:1; + head->padding = 0; + head->cc = 0; + head->seqnum = htons(vRTPInfo->seqNum++); + head->timestamp = htonl(millis); + head->ssrc = htonl(vRTPInfo->ssrc); + head->payloadtype = 34; //32; outBuff += RTP_HEADER_LEN; @@ -728,41 +728,36 @@ int MediaProcessor::packageVideoRTP(char *inBuff, int inBuffLen, char *outBuff) return l; } - - -int MediaProcessor::unpackageVideoRTP(char *inBuff, int inBuffLen, char *outBuff, int *gotFrame) { -/* - if (videoUnpackager == 0) { - printf("No se ha inicailizado el codec de input vídeo RTP"); - return -1; - } -*/ +int MediaProcessor::unpackageVideoRTP(char *inBuff, int inBuffLen, + char *outBuff, int *gotFrame) { + /* + if (videoUnpackager == 0) { + printf("No se ha inicailizado el codec de input vídeo RTP"); + return -1; + } + */ *gotFrame = 0; - rtpHeader* head = (rtpHeader*)inBuff; + rtpHeader* head = (rtpHeader*) inBuff; int sec = ntohs(head->seqnum); int ssrc = ntohl(head->ssrc); unsigned long time = ntohl(head->timestamp); - - - int l = inBuffLen - RTP_HEADER_LEN; inBuff += RTP_HEADER_LEN; memcpy(outBuff, inBuff, l); - vp8RtpHeader* vp8h = (vp8RtpHeader*)outBuff; - printf("Printf R %u, PartID %u , X %u \n\n", vp8h->R, vp8h->partId, vp8h->X); + vp8RtpHeader* vp8h = (vp8RtpHeader*) outBuff; + printf("R: %u, PartID %u , X %u \n\n", vp8h->R, vp8h->partId, vp8h->X); - if(head->marker) { + if (head->marker) { *gotFrame = 1; } return l; - if (avformat_find_stream_info(vInputFormatContext, NULL) < 0) { return -1; } @@ -772,19 +767,16 @@ int MediaProcessor::unpackageVideoRTP(char *inBuff, int inBuffLen, char *outBuff //aInputFormatContext->iformat->read_packet(aInputFormatContext, &pkt); - int p = av_read_frame(vInputFormatContext, &pkt); printf("Leido frame %d\n", p); + outBuff = (char*) pkt.data; - outBuff = (char*)pkt.data; - - int se = pkt.size; + int se = pkt.size; av_free_packet(&pkt); return se; - } diff --git a/src/erizo/media/Test.cpp b/src/erizo/media/Test.cpp index afb9615014..0172d808c7 100644 --- a/src/erizo/media/Test.cpp +++ b/src/erizo/media/Test.cpp @@ -6,8 +6,10 @@ #include "Test.h" +#include "utils/RtpUtils.h" using boost::asio::ip::udp; +using namespace erizo; Test::Test() { mp = new MediaProcessor(); @@ -88,9 +90,14 @@ void Test::rec() { // int a = 5; printf("Bytes = %d\n", a); - int b = mp->unpackageVideoRTP((char*)buff, a, outBuff, &gotFrame); + int z,b; + z = mp->unpackageVideoRTP((char*)buff, a, outBuff, &gotFrame); - printf("Bytes desem = %d\n", b); + RTPPayloadVP8* parsed = pars.parseVP8((unsigned char*)outBuff, z); + b = parsed->dataLength; + //int c = parsed.dataLength; + + printf("Bytes desem = %d prevp8 %d\n", b, z ); size += b; outBuff += b; diff --git a/src/erizo/media/Test.h b/src/erizo/media/Test.h index f3be73045a..04ce15b219 100644 --- a/src/erizo/media/Test.h +++ b/src/erizo/media/Test.h @@ -1,4 +1,5 @@ #include "MediaProcessor.h" +#include "utils/RtpUtils.h" #include #ifndef TEST_H_ @@ -16,6 +17,8 @@ class Test { boost::asio::ip::udp::socket* socket_; boost::asio::io_service* ioservice_; MediaProcessor *mp; + erizo::RtpParser pars; + }; #endif /* TEST_H_ */ diff --git a/src/examples/hsam.cpp b/src/examples/hsam.cpp index 15b2c315d5..8046f6f71e 100644 --- a/src/examples/hsam.cpp +++ b/src/examples/hsam.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include "pc/Observer.h" @@ -16,11 +17,13 @@ using namespace erizo; int publisherid = 0; int main() { - SDPReceiver* receiver = new SDPReceiver(); - Observer *subscriber = new Observer("subscriber", receiver); - new Observer("publisher", receiver); - subscriber->wait(); - return 0; + new Test(); + +// SDPReceiver* receiver = new SDPReceiver(); +// Observer *subscriber = new Observer("subscriber", receiver); +// new Observer("publisher", receiver); +// subscriber->wait(); +// return 0; } SDPReceiver::SDPReceiver() { From 9d9fb8996c8a9261491afc7aa0a67b849a6c8e1c Mon Sep 17 00:00:00 2001 From: Pedro Rodriguez Date: Wed, 4 Jul 2012 12:59:04 +0200 Subject: [PATCH 06/29] New iteration in developing media processor --- src/erizo/OneToManyProcessor.cpp | 74 ++++++++++ src/erizo/OneToManyProcessor.h | 12 +- src/erizo/media/MediaProcessor.cpp | 50 ++++--- src/erizo/media/utils/RtpUtils.cpp | 197 +++++++++++++++++++++++++ src/erizo/media/utils/RtpUtils.h | 40 +++++ src/{erizo/media => examples}/Test.cpp | 30 ++-- src/{erizo/media => examples}/Test.h | 7 +- src/examples/hsam.cpp | 3 +- src/examples/pc/PCSocket.cpp | 2 +- 9 files changed, 375 insertions(+), 40 deletions(-) create mode 100644 src/erizo/media/utils/RtpUtils.cpp create mode 100644 src/erizo/media/utils/RtpUtils.h rename src/{erizo/media => examples}/Test.cpp (83%) rename src/{erizo/media => examples}/Test.h (66%) diff --git a/src/erizo/OneToManyProcessor.cpp b/src/erizo/OneToManyProcessor.cpp index 7d9e61285b..4751804039 100644 --- a/src/erizo/OneToManyProcessor.cpp +++ b/src/erizo/OneToManyProcessor.cpp @@ -11,8 +11,48 @@ OneToManyProcessor::OneToManyProcessor() : sendVideoBuffer_ = (char*) malloc(2000); sendAudioBuffer_ = (char*) malloc(2000); + publisher = NULL; + // Media processing + + unpackagedBuffer_ = (char*)malloc(50000); + memset(unpackagedBuffer_, 0, 50000); + + + gotFrame_ = 0; + size_ = 0; + gotDecodedFrame_=0; + + + + mp = new MediaProcessor(); + videoCodecInfo *v = new videoCodecInfo; + v->codec = CODEC_ID_VP8; + // v->codec = CODEC_ID_MPEG4; + v->width = 640; + v->height = 480; + decodedBuffer_ = (char*) malloc(v->width*v->height*3/2); + memset(decodedBuffer_,0,v->width*v->height*3/2); + mp->initVideoDecoder(v); + + videoCodecInfo *c = new videoCodecInfo; + //c->codec = CODEC_ID_MPEG2VIDEO; + c->codec = CODEC_ID_VP8; + c->width = v->width; + c->height = v->height; + c->frameRate = 24; + c->bitRate = 1024; + c->maxInter = 0; + + mp->initVideoCoder(c); + + RTPInfo *r = new RTPInfo; + //r->codec = CODEC_ID_MPEG2VIDEO; + // r->codec = CODEC_ID_MPEG4; + mp->initVideoPackagerRTP(r); + mp->initVideoUnpackagerRTP(r); + } OneToManyProcessor::~OneToManyProcessor() { @@ -39,6 +79,40 @@ int OneToManyProcessor::receiveAudioData(char* buf, int len) { } int OneToManyProcessor::receiveVideoData(char* buf, int len) { + + int b; + int x = mp->unpackageVideoRTP(buf,len,unpackagedBuffer_,&gotFrame_); +// if (x>0){ +// RTPPayloadVP8* parsed = pars.parseVP8((unsigned char*)unpackagedBuffer_, x); +// b = parsed->dataLength; +// printf("Bytes desem = %d, sobre %d reciv\n", b, len); +// +// } + size_ += x; + unpackagedBuffer_ += x; + if(gotFrame_) { + + unpackagedBuffer_ -= size_; + + printf("Tengo un frame desempaquetado!! Size = %d\n", size_); + + int c; + + c = mp->decodeVideo(unpackagedBuffer_, size_, decodedBuffer_, 640*480*3/2, &gotDecodedFrame_); + printf("Bytes dec = %d\n", c); + + printf("\n*****************************"); + + size_ = 0; + memset(unpackagedBuffer_, 0, 50000); + gotFrame_ = 0; + + if(gotDecodedFrame_) { + printf("\nTengo un frame decodificado!!"); + gotDecodedFrame_ = 0; + //send(outBuff2, c); + } + } if (subscribers.empty() || len <= 0) return 0; diff --git a/src/erizo/OneToManyProcessor.h b/src/erizo/OneToManyProcessor.h index 903ea2d4af..f17da83742 100644 --- a/src/erizo/OneToManyProcessor.h +++ b/src/erizo/OneToManyProcessor.h @@ -8,11 +8,14 @@ #include #include "MediaDefinitions.h" +#include "media/MediaProcessor.h" +#include "media/utils/RtpUtils.h" -namespace erizo{ +namespace erizo{ class WebRtcConnection; + /** * Represents a One to Many connection. * Receives media from one publisher and retransmits it to every subscriber. @@ -41,11 +44,18 @@ class OneToManyProcessor : public MediaReceiver { int receiveVideoData(char* buf, int len); WebRtcConnection *publisher; + MediaProcessor *mp; std::map subscribers; private: char* sendVideoBuffer_; char* sendAudioBuffer_; + char* unpackagedBuffer_; + char* decodedBuffer_; + char* codedBuffer_; + int gotFrame_,gotDecodedFrame_, size_; + RtpParser pars; + }; } /* namespace erizo */ diff --git a/src/erizo/media/MediaProcessor.cpp b/src/erizo/media/MediaProcessor.cpp index bdcc44c5e2..7c15cc3ea3 100644 --- a/src/erizo/media/MediaProcessor.cpp +++ b/src/erizo/media/MediaProcessor.cpp @@ -743,40 +743,44 @@ int MediaProcessor::unpackageVideoRTP(char *inBuff, int inBuffLen, int sec = ntohs(head->seqnum); int ssrc = ntohl(head->ssrc); unsigned long time = ntohl(head->timestamp); - +// if (ssrc!= 55543) +// return -1; int l = inBuffLen - RTP_HEADER_LEN; inBuff += RTP_HEADER_LEN; + vp8RtpHeader* vp8h = (vp8RtpHeader*) outBuff; + printf("R: %u, PartID %u , X %u \n", vp8h->R, vp8h->partId, vp8h->X); + l--; + inBuff++; memcpy(outBuff, inBuff, l); - vp8RtpHeader* vp8h = (vp8RtpHeader*) outBuff; - printf("R: %u, PartID %u , X %u \n\n", vp8h->R, vp8h->partId, vp8h->X); + if (head->marker) { *gotFrame = 1; } return l; - - if (avformat_find_stream_info(vInputFormatContext, NULL) < 0) { - return -1; - } - - AVPacket pkt; - av_init_packet(&pkt); - - //aInputFormatContext->iformat->read_packet(aInputFormatContext, &pkt); - - int p = av_read_frame(vInputFormatContext, &pkt); - printf("Leido frame %d\n", p); - - outBuff = (char*) pkt.data; - - int se = pkt.size; - - av_free_packet(&pkt); - - return se; +// +// if (avformat_find_stream_info(vInputFormatContext, NULL) < 0) { +// return -1; +// } +// +// AVPacket pkt; +// av_init_packet(&pkt); +// +// //aInputFormatContext->iformat->read_packet(aInputFormatContext, &pkt); +// +// int p = av_read_frame(vInputFormatContext, &pkt); +// printf("Leido frame %d\n", p); +// +// outBuff = (char*) pkt.data; +// +// int se = pkt.size; +// +// av_free_packet(&pkt); +// +// return se; } diff --git a/src/erizo/media/utils/RtpUtils.cpp b/src/erizo/media/utils/RtpUtils.cpp new file mode 100644 index 0000000000..f1de601c4d --- /dev/null +++ b/src/erizo/media/utils/RtpUtils.cpp @@ -0,0 +1,197 @@ +#include +#include +#include + +#include "RtpUtils.h" + +namespace erizo { + +RtpParser::RtpParser() { +} + +RtpParser::~RtpParser() { + +} + +/* namespace erizo */ +// +// VP8 format: +// +// Payload descriptor +// 0 1 2 3 4 5 6 7 +// +-+-+-+-+-+-+-+-+ +// |X|R|N|S|PartID | (REQUIRED) +// +-+-+-+-+-+-+-+-+ +// X: |I|L|T|K| RSV | (OPTIONAL) +// +-+-+-+-+-+-+-+-+ +// I: | PictureID | (OPTIONAL) +// +-+-+-+-+-+-+-+-+ +// L: | TL0PICIDX | (OPTIONAL) +// +-+-+-+-+-+-+-+-+ +// T/K: |TID:Y| KEYIDX | (OPTIONAL) +// +-+-+-+-+-+-+-+-+ +// +// Payload header (considered part of the actual payload, sent to decoder) +// 0 1 2 3 4 5 6 7 +// +-+-+-+-+-+-+-+-+ +// |Size0|H| VER |P| +// +-+-+-+-+-+-+-+-+ +// | ... | +// + + +int ParseVP8PictureID(erizo::RTPPayloadVP8* vp8, const unsigned char** dataPtr, + int* dataLength, int* parsedBytes) { + if (*dataLength <= 0) + return -1; + vp8->pictureID = (**dataPtr & 0x7F); + if (**dataPtr & 0x80) { + (*dataPtr)++; + (*parsedBytes)++; + if (--(*dataLength) <= 0) + return -1; + // PictureID is 15 bits + vp8->pictureID = (vp8->pictureID << 8) + **dataPtr; + } + (*dataPtr)++; + (*parsedBytes)++; + (*dataLength)--; + return 0; +} + +int ParseVP8Tl0PicIdx(erizo::RTPPayloadVP8* vp8, const unsigned char** dataPtr, + int* dataLength, int* parsedBytes) { + if (*dataLength <= 0) + return -1; + vp8->tl0PicIdx = **dataPtr; + (*dataPtr)++; + (*parsedBytes)++; + (*dataLength)--; + return 0; +} + +int ParseVP8TIDAndKeyIdx(erizo::RTPPayloadVP8* vp8, + const unsigned char** dataPtr, int* dataLength, int* parsedBytes) { + if (*dataLength <= 0) + return -1; + if (vp8->hasTID) { + vp8->tID = ((**dataPtr >> 6) & 0x03); + vp8->layerSync = (**dataPtr & 0x20) ? true : false; // Y bit + } + if (vp8->hasKeyIdx) { + vp8->keyIdx = (**dataPtr & 0x1F); + } + (*dataPtr)++; + (*parsedBytes)++; + (*dataLength)--; + return 0; +} + +//int ParseVP8FrameSize(RTPPayload& parsedPacket, +// const unsigned char* dataPtr, +// int dataLength) { +// if (parsedPacket.frameType != kIFrame) { +// // Included in payload header for I-frames. +// return 0; +// } +// if (dataLength < 10) { +// // For an I-frame we should always have the uncompressed VP8 header +// // in the beginning of the partition. +// return -1; +// } +// RTPPayloadVP8* vp8 = &parsedPacket.info.VP8; +// vp8->frameWidth = ((dataPtr[7] << 8) + dataPtr[6]) & 0x3FFF; +// vp8->frameHeight = ((dataPtr[9] << 8) + dataPtr[8]) & 0x3FFF; +// return 0; +//} + +int ParseVP8Extension(erizo::RTPPayloadVP8* vp8, const unsigned char* dataPtr, int dataLength) { + + int parsedBytes = 0; + if (dataLength <= 0) + return -1; + // Optional X field is present + vp8->hasPictureID = (*dataPtr & 0x80) ? true : false; // I bit + vp8->hasTl0PicIdx = (*dataPtr & 0x40) ? true : false; // L bit + vp8->hasTID = (*dataPtr & 0x20) ? true : false; // T bit + vp8->hasKeyIdx = (*dataPtr & 0x10) ? true : false; // K bit + + printf("Parsing extension haspic %d, hastl0 %d, has TID %d, has Key %d \n",vp8->hasPictureID,vp8->hasTl0PicIdx, vp8->hasTID, vp8->hasKeyIdx ); + + // Advance dataPtr and decrease remaining payload size + dataPtr++; + parsedBytes++; + dataLength--; + + if (vp8->hasPictureID) { + if (ParseVP8PictureID(vp8, &dataPtr, &dataLength, &parsedBytes) != 0) { + return -1; + } + } + + if (vp8->hasTl0PicIdx) { + if (ParseVP8Tl0PicIdx(vp8, &dataPtr, &dataLength, &parsedBytes) != 0) { + return -1; + } + } + + if (vp8->hasTID || vp8->hasKeyIdx) { + if (ParseVP8TIDAndKeyIdx(vp8, &dataPtr, &dataLength, &parsedBytes) + != 0) { + return -1; + } + } + return parsedBytes; +} + +RTPPayloadVP8* RtpParser::parseVP8(unsigned char* data, + int dataLength) { + RTPPayloadVP8* vp8 = new RTPPayloadVP8; // = &parsedPacket.info.VP8; + const unsigned char* dataPtr = data; + + // Parse mandatory first byte of payload descriptor + bool extension = (*dataPtr & 0x80) ? true : false; // X bit + vp8->nonReferenceFrame = (*dataPtr & 0x20) ? true : false; // N bit + vp8->beginningOfPartition = (*dataPtr & 0x10) ? true : false; // S bit + vp8->partitionID = (*dataPtr & 0x0F); // PartID field + + printf("X: %d N %d S %d PartID %d\n", extension, vp8->nonReferenceFrame, vp8->beginningOfPartition, vp8->partitionID); + + if (vp8->partitionID > 8) { + // Weak check for corrupt data: PartID MUST NOT be larger than 8. + return vp8; + } + + // Advance dataPtr and decrease remaining payload size + dataPtr++; + dataLength--; + + if (extension) { + const int parsedBytes = ParseVP8Extension(vp8, dataPtr, dataLength); + if (parsedBytes < 0) + return vp8; + dataPtr += parsedBytes; + dataLength -= parsedBytes; + } + + if (dataLength <= 0) { + printf("Error parsing VP8 payload descriptor; payload too short\n"); + return vp8; + } + + std::string frametype; + // Read P bit from payload header (only at beginning of first partition) + if (dataLength > 0 && vp8->beginningOfPartition && vp8->partitionID == 0) { + //parsedPacket.frameType = (*dataPtr & 0x01) ? kPFrame : kIFrame; + frametype = (*dataPtr & 0x01) ? "kPFrame" : "kIFrame"; + } else { + + frametype = "kPFrame"; + } +// if (0 != ParseVP8FrameSize(parsedPacket, dataPtr, dataLength)) { +// return *vp8; +// } + vp8->dataLength = (unsigned int) dataLength; + + return vp8; +} +} + diff --git a/src/erizo/media/utils/RtpUtils.h b/src/erizo/media/utils/RtpUtils.h new file mode 100644 index 0000000000..640e7eb267 --- /dev/null +++ b/src/erizo/media/utils/RtpUtils.h @@ -0,0 +1,40 @@ +#ifndef RTPUTILS_H_ +#define RTPUTILS_H_ + +namespace erizo { + +typedef struct { + bool nonReferenceFrame; + bool beginningOfPartition; + int partitionID; + bool hasPictureID; + bool hasTl0PicIdx; + bool hasTID; + bool hasKeyIdx; + int pictureID; + int tl0PicIdx; + int tID; + bool layerSync; + int keyIdx; + int frameWidth; + int frameHeight; + + const unsigned char* data; + unsigned int dataLength; +} RTPPayloadVP8; + +enum FrameTypes { + kIFrame, // key frame + kPFrame // Delta frame +}; + +class RtpParser { + +public: + RtpParser(); + virtual ~RtpParser(); + erizo::RTPPayloadVP8* parseVP8(unsigned char* data, int datalength); +}; + +} /* namespace erizo */ +#endif /* RTPUTILS_H_ */ diff --git a/src/erizo/media/Test.cpp b/src/examples/Test.cpp similarity index 83% rename from src/erizo/media/Test.cpp rename to src/examples/Test.cpp index 0172d808c7..7108ab2b33 100644 --- a/src/erizo/media/Test.cpp +++ b/src/examples/Test.cpp @@ -6,12 +6,13 @@ #include "Test.h" -#include "utils/RtpUtils.h" + using boost::asio::ip::udp; using namespace erizo; Test::Test() { + mp = new MediaProcessor(); @@ -30,8 +31,10 @@ Test::Test() { videoCodecInfo *v = new videoCodecInfo; v->codec = CODEC_ID_VP8; // v->codec = CODEC_ID_MPEG4; - v->width = 706; - v->height = 396; + //v->width = 706; + //v->height = 396; + v->width = 400; + v->height = 300; mp->initVideoDecoder(v); @@ -54,10 +57,14 @@ Test::Test() { ioservice_ = new boost::asio::io_service; + resolver_ = new udp::resolver(*ioservice_); socket_ = new udp::socket(*ioservice_, udp::endpoint(udp::v4(),40000)); + query_ = new udp::resolver::query(udp::v4(),"127.0.0.1", "50000"); + boost::thread t = boost::thread(&Test::rec, this); t.join(); + } Test::~Test() { @@ -84,23 +91,21 @@ void Test::rec() { memset(buff, 0, 2000); -// int a = sock->recvFrom(buff, 2000, s, u); a = socket_->receive(boost::asio::buffer(buff, 2000)); printf("********* RECEPCIÓN *********\n"); -// int a = 5; printf("Bytes = %d\n", a); int z,b; z = mp->unpackageVideoRTP((char*)buff, a, outBuff, &gotFrame); - RTPPayloadVP8* parsed = pars.parseVP8((unsigned char*)outBuff, z); - b = parsed->dataLength; +// RTPPayloadVP8* parsed = pars.parseVP8((unsigned char*)outBuff, z); +// b = parsed->dataLength; //int c = parsed.dataLength; - printf("Bytes desem = %d prevp8 %d\n", b, z ); +// printf("Bytes desem = %d prevp8 %d\n", b, z ); - size += b; - outBuff += b; + size += z; + outBuff += z; if(gotFrame) { @@ -144,8 +149,11 @@ void Test::send(char *buff, int buffSize) { printf("\nBytes empaquetados = %d", b); - //sock->sendTo(buffSend2, b, "toronado.dit.upm.es", 5005); + udp::resolver::iterator iterator = resolver_->resolve(*query_); + +// socket_->send_to(buffSend2, b, "toronado.dit.upm.es", 5005); + socket_->send_to(boost::asio::buffer(buffSend2,b),*iterator); free(buffSend); free(buffSend2); diff --git a/src/erizo/media/Test.h b/src/examples/Test.h similarity index 66% rename from src/erizo/media/Test.h rename to src/examples/Test.h index 04ce15b219..511c450900 100644 --- a/src/erizo/media/Test.h +++ b/src/examples/Test.h @@ -1,5 +1,5 @@ -#include "MediaProcessor.h" -#include "utils/RtpUtils.h" +#include +#include #include #ifndef TEST_H_ @@ -15,6 +15,9 @@ class Test { private: boost::asio::ip::udp::socket* socket_; + boost::asio::ip::udp::resolver* resolver_; + + boost::asio::ip::udp::resolver::query* query_; boost::asio::io_service* ioservice_; MediaProcessor *mp; erizo::RtpParser pars; diff --git a/src/examples/hsam.cpp b/src/examples/hsam.cpp index 8046f6f71e..fca1d457fa 100644 --- a/src/examples/hsam.cpp +++ b/src/examples/hsam.cpp @@ -8,8 +8,7 @@ #include #include #include -#include - +#include "Test.h" #include "pc/Observer.h" using namespace erizo; diff --git a/src/examples/pc/PCSocket.cpp b/src/examples/pc/PCSocket.cpp index 4f6fdb3bf7..3c0f2f74fe 100644 --- a/src/examples/pc/PCSocket.cpp +++ b/src/examples/pc/PCSocket.cpp @@ -8,7 +8,7 @@ #define PUBLISHER_PORT 8484 #define SUBSCRIBER_PORT 8485 -std::string servAddress = ""; //INSERT NODE SERVER ADDRESS HERE +std::string servAddress = "rocky.dit.upm.es"; //INSERT NODE SERVER ADDRESS HERE using boost::asio::ip::tcp; From a309120bf38d1186e5e7bcabd4b6b97b4d3d852a Mon Sep 17 00:00:00 2001 From: Pedro Rodriguez Date: Thu, 5 Jul 2012 16:05:04 +0200 Subject: [PATCH 07/29] Added fake packet burst at the beginnig of a subscription --- src/erizo/OneToManyProcessor.cpp | 97 ++++++++++++++++++++------------ src/erizo/OneToManyProcessor.h | 8 ++- 2 files changed, 68 insertions(+), 37 deletions(-) diff --git a/src/erizo/OneToManyProcessor.cpp b/src/erizo/OneToManyProcessor.cpp index 4751804039..25b6962eab 100644 --- a/src/erizo/OneToManyProcessor.cpp +++ b/src/erizo/OneToManyProcessor.cpp @@ -16,15 +16,12 @@ OneToManyProcessor::OneToManyProcessor() : // Media processing - unpackagedBuffer_ = (char*)malloc(50000); - memset(unpackagedBuffer_, 0, 50000); - - - gotFrame_ = 0; - size_ = 0; - gotDecodedFrame_=0; - + unpackagedBuffer_ = (char*) malloc(50000); + memset(unpackagedBuffer_, 0, 50000); + gotFrame_ = 0; + size_ = 0; + gotDecodedFrame_ = 0; mp = new MediaProcessor(); videoCodecInfo *v = new videoCodecInfo; @@ -32,8 +29,8 @@ OneToManyProcessor::OneToManyProcessor() : // v->codec = CODEC_ID_MPEG4; v->width = 640; v->height = 480; - decodedBuffer_ = (char*) malloc(v->width*v->height*3/2); - memset(decodedBuffer_,0,v->width*v->height*3/2); + decodedBuffer_ = (char*) malloc(v->width * v->height * 3 / 2); + memset(decodedBuffer_, 0, v->width * v->height * 3 / 2); mp->initVideoDecoder(v); videoCodecInfo *c = new videoCodecInfo; @@ -79,45 +76,64 @@ int OneToManyProcessor::receiveAudioData(char* buf, int len) { } int OneToManyProcessor::receiveVideoData(char* buf, int len) { - + if (head.size() < 50) { + rtpHeader* rtphead = (rtpHeader*)buf; + printf("PT %u\n",rtphead->payloadtype); + if(rtphead->payloadtype==103){ + return 0; + } + + packet* p = new packet; + p->data = buf; + p->length = len; + head.push_back(p); + printf("Storing head %d\n", head.size()); + } +/* int b; - int x = mp->unpackageVideoRTP(buf,len,unpackagedBuffer_,&gotFrame_); -// if (x>0){ -// RTPPayloadVP8* parsed = pars.parseVP8((unsigned char*)unpackagedBuffer_, x); -// b = parsed->dataLength; -// printf("Bytes desem = %d, sobre %d reciv\n", b, len); -// -// } + int x = mp->unpackageVideoRTP(buf, len, unpackagedBuffer_, &gotFrame_); + if (x > 0) { + RTPPayloadVP8* parsed = pars.parseVP8( + (unsigned char*) unpackagedBuffer_, x); + b = parsed->dataLength; + printf("Bytes desem = %d, sobre %d reciv\n", b, len); + + } size_ += x; unpackagedBuffer_ += x; - if(gotFrame_) { - - unpackagedBuffer_ -= size_; + if (gotFrame_) { - printf("Tengo un frame desempaquetado!! Size = %d\n", size_); + unpackagedBuffer_ -= size_; - int c; + printf("Tengo un frame desempaquetado!! Size = %d\n", size_); - c = mp->decodeVideo(unpackagedBuffer_, size_, decodedBuffer_, 640*480*3/2, &gotDecodedFrame_); - printf("Bytes dec = %d\n", c); + int c; - printf("\n*****************************"); + c = mp->decodeVideo(unpackagedBuffer_, size_, decodedBuffer_, + 640 * 480 * 3 / 2, &gotDecodedFrame_); + printf("Bytes dec = %d\n", c); - size_ = 0; - memset(unpackagedBuffer_, 0, 50000); - gotFrame_ = 0; + size_ = 0; + memset(unpackagedBuffer_, 0, 50000); + gotFrame_ = 0; - if(gotDecodedFrame_) { - printf("\nTengo un frame decodificado!!"); - gotDecodedFrame_ = 0; - //send(outBuff2, c); - } - } + if (gotDecodedFrame_) { + printf("Tengo un frame decodificado!!\n"); + gotDecodedFrame_ = 0; + //send(outBuff2, c); + } + } +*/ if (subscribers.empty() || len <= 0) return 0; std::map::iterator it; for (it = subscribers.begin(); it != subscribers.end(); it++) { + if ((*it).second->sentPackets==0){ + printf("******sending Head to %d\n",((*it).first)); + sendHead((*it).second); + } + memset(sendVideoBuffer_, 0, len); memcpy(sendVideoBuffer_, buf, len); (*it).second->receiveVideoData(sendVideoBuffer_, len); @@ -132,8 +148,9 @@ void OneToManyProcessor::setPublisher(WebRtcConnection* webRtcConn) { void OneToManyProcessor::addSubscriber(WebRtcConnection* webRtcConn, int peerId) { - this->subscribers[peerId] = webRtcConn; +// sendHead(webRtcConn); + } void OneToManyProcessor::removeSubscriber(int peerId) { @@ -144,5 +161,13 @@ void OneToManyProcessor::removeSubscriber(int peerId) { } } +void OneToManyProcessor::sendHead(WebRtcConnection* conn) { + int i = 0; + for (i = 0; ireceiveVideoData(head[i]->data, head[i]->length); + } + +} + }/* namespace erizo */ diff --git a/src/erizo/OneToManyProcessor.h b/src/erizo/OneToManyProcessor.h index f17da83742..b89607b09f 100644 --- a/src/erizo/OneToManyProcessor.h +++ b/src/erizo/OneToManyProcessor.h @@ -6,6 +6,7 @@ #define ONETOMANYPROCESSOR_H_ #include +#include #include "MediaDefinitions.h" #include "media/MediaProcessor.h" @@ -15,7 +16,10 @@ namespace erizo{ class WebRtcConnection; - +struct packet{ + char* data; + int length; +}; /** * Represents a One to Many connection. * Receives media from one publisher and retransmits it to every subscriber. @@ -53,7 +57,9 @@ class OneToManyProcessor : public MediaReceiver { char* unpackagedBuffer_; char* decodedBuffer_; char* codedBuffer_; + std::vector head; int gotFrame_,gotDecodedFrame_, size_; + void sendHead(WebRtcConnection* conn); RtpParser pars; }; From ae58013fcd745cac7a14e4f29dac8a100d9bc998 Mon Sep 17 00:00:00 2001 From: Pedro Rodriguez Date: Thu, 5 Jul 2012 16:06:00 +0200 Subject: [PATCH 08/29] Advances in VP8 rtp --- src/erizo/media/MediaProcessor.cpp | 8 ++++---- src/examples/Test.cpp | 3 +-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/erizo/media/MediaProcessor.cpp b/src/erizo/media/MediaProcessor.cpp index 7c15cc3ea3..a01644c979 100644 --- a/src/erizo/media/MediaProcessor.cpp +++ b/src/erizo/media/MediaProcessor.cpp @@ -743,15 +743,15 @@ int MediaProcessor::unpackageVideoRTP(char *inBuff, int inBuffLen, int sec = ntohs(head->seqnum); int ssrc = ntohl(head->ssrc); unsigned long time = ntohl(head->timestamp); -// if (ssrc!= 55543) -// return -1; + if (ssrc!= 55543) + return -1; int l = inBuffLen - RTP_HEADER_LEN; inBuff += RTP_HEADER_LEN; vp8RtpHeader* vp8h = (vp8RtpHeader*) outBuff; printf("R: %u, PartID %u , X %u \n", vp8h->R, vp8h->partId, vp8h->X); - l--; - inBuff++; + //l--; + //inBuff++; memcpy(outBuff, inBuff, l); diff --git a/src/examples/Test.cpp b/src/examples/Test.cpp index 7108ab2b33..f6a1d6b12b 100644 --- a/src/examples/Test.cpp +++ b/src/examples/Test.cpp @@ -118,14 +118,13 @@ void Test::rec() { c = mp->decodeVideo(outBuff, size, outBuff2, outBuff2Size, &gotDecFrame); printf("Bytes dec = %d\n", c); - printf("\n*****************************"); size = 0; memset(outBuff, 0, 50000); gotFrame = 0; if(gotDecFrame) { - printf("\nTengo un frame decodificado!!"); + printf("Tengo un frame decodificado!!"); gotDecFrame = 0; send(outBuff2, c); } From 7d0f8a285e66075dedee80e058bb54e5152b4e8a Mon Sep 17 00:00:00 2001 From: Pedro Rodriguez Date: Mon, 9 Jul 2012 10:55:09 +0200 Subject: [PATCH 09/29] media --- src/erizo/OneToManyProcessor.cpp | 96 ++++++++++++-------------------- src/erizo/OneToManyProcessor.h | 6 +- 2 files changed, 36 insertions(+), 66 deletions(-) diff --git a/src/erizo/OneToManyProcessor.cpp b/src/erizo/OneToManyProcessor.cpp index 25b6962eab..c3f7aa154a 100644 --- a/src/erizo/OneToManyProcessor.cpp +++ b/src/erizo/OneToManyProcessor.cpp @@ -76,64 +76,46 @@ int OneToManyProcessor::receiveAudioData(char* buf, int len) { } int OneToManyProcessor::receiveVideoData(char* buf, int len) { - if (head.size() < 50) { - rtpHeader* rtphead = (rtpHeader*)buf; - printf("PT %u\n",rtphead->payloadtype); - if(rtphead->payloadtype==103){ - return 0; - } - - packet* p = new packet; - p->data = buf; - p->length = len; - head.push_back(p); - printf("Storing head %d\n", head.size()); - } -/* - int b; - int x = mp->unpackageVideoRTP(buf, len, unpackagedBuffer_, &gotFrame_); - if (x > 0) { - RTPPayloadVP8* parsed = pars.parseVP8( - (unsigned char*) unpackagedBuffer_, x); - b = parsed->dataLength; - printf("Bytes desem = %d, sobre %d reciv\n", b, len); - - } - size_ += x; - unpackagedBuffer_ += x; - if (gotFrame_) { - - unpackagedBuffer_ -= size_; - - printf("Tengo un frame desempaquetado!! Size = %d\n", size_); - - int c; - - c = mp->decodeVideo(unpackagedBuffer_, size_, decodedBuffer_, - 640 * 480 * 3 / 2, &gotDecodedFrame_); - printf("Bytes dec = %d\n", c); - - size_ = 0; - memset(unpackagedBuffer_, 0, 50000); - gotFrame_ = 0; - - if (gotDecodedFrame_) { - printf("Tengo un frame decodificado!!\n"); - gotDecodedFrame_ = 0; - //send(outBuff2, c); - } - } -*/ + /* + int b; + int x = mp->unpackageVideoRTP(buf, len, unpackagedBuffer_, &gotFrame_); + if (x > 0) { + RTPPayloadVP8* parsed = pars.parseVP8( + (unsigned char*) unpackagedBuffer_, x); + b = parsed->dataLength; + printf("Bytes desem = %d, sobre %d reciv\n", b, len); + + } + size_ += x; + unpackagedBuffer_ += x; + if (gotFrame_) { + + unpackagedBuffer_ -= size_; + + printf("Tengo un frame desempaquetado!! Size = %d\n", size_); + + int c; + + c = mp->decodeVideo(unpackagedBuffer_, size_, decodedBuffer_, + 640 * 480 * 3 / 2, &gotDecodedFrame_); + printf("Bytes dec = %d\n", c); + + size_ = 0; + memset(unpackagedBuffer_, 0, 50000); + gotFrame_ = 0; + + if (gotDecodedFrame_) { + printf("Tengo un frame decodificado!!\n"); + gotDecodedFrame_ = 0; + //send(outBuff2, c); + } + } + */ if (subscribers.empty() || len <= 0) return 0; std::map::iterator it; for (it = subscribers.begin(); it != subscribers.end(); it++) { - if ((*it).second->sentPackets==0){ - printf("******sending Head to %d\n",((*it).first)); - sendHead((*it).second); - } - memset(sendVideoBuffer_, 0, len); memcpy(sendVideoBuffer_, buf, len); (*it).second->receiveVideoData(sendVideoBuffer_, len); @@ -161,13 +143,5 @@ void OneToManyProcessor::removeSubscriber(int peerId) { } } -void OneToManyProcessor::sendHead(WebRtcConnection* conn) { - int i = 0; - for (i = 0; ireceiveVideoData(head[i]->data, head[i]->length); - } - -} - }/* namespace erizo */ diff --git a/src/erizo/OneToManyProcessor.h b/src/erizo/OneToManyProcessor.h index b89607b09f..389e0c2c9a 100644 --- a/src/erizo/OneToManyProcessor.h +++ b/src/erizo/OneToManyProcessor.h @@ -16,10 +16,6 @@ namespace erizo{ class WebRtcConnection; -struct packet{ - char* data; - int length; -}; /** * Represents a One to Many connection. * Receives media from one publisher and retransmits it to every subscriber. @@ -57,7 +53,7 @@ class OneToManyProcessor : public MediaReceiver { char* unpackagedBuffer_; char* decodedBuffer_; char* codedBuffer_; - std::vector head; + std::vector head; int gotFrame_,gotDecodedFrame_, size_; void sendHead(WebRtcConnection* conn); RtpParser pars; From ca36bff2228fb2b29124a933a31523e92534f461 Mon Sep 17 00:00:00 2001 From: Pedro Rodriguez Date: Tue, 10 Jul 2012 13:14:49 +0200 Subject: [PATCH 10/29] Edited SDP Answer to only support vp8 (not red or fec) --- src/erizo/SdpInfo.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/erizo/SdpInfo.cpp b/src/erizo/SdpInfo.cpp index babe6a6cac..c2ea23372d 100644 --- a/src/erizo/SdpInfo.cpp +++ b/src/erizo/SdpInfo.cpp @@ -32,7 +32,7 @@ void SdpInfo::addCrypto(const CryptoInfo& info) { } std::string SdpInfo::getSdp() { - + printf("1\n"); std::ostringstream sdp; sdp << "v=0\n" << "o=- 0 0 IN IP4 127.0.0.1\n" << "s=\n" << "t=0 0\n"; bool bundle = candidateVector_[0].isBundle; @@ -40,6 +40,7 @@ std::string SdpInfo::getSdp() { if (bundle) { sdp << "a=group:BUNDLE audio video\n"; } + printf("2\n"); //candidates audio bool printedAudio = false, printedVideo = false; for (unsigned int it = 0; it < candidateVector_.size(); it++) { @@ -84,6 +85,7 @@ std::string SdpInfo::getSdp() { } } } + printf("3\n"); //crypto audio if (printedAudio) { sdp << "a=ice-ufrag:" << iceUsername_ << endl; @@ -167,12 +169,13 @@ std::string SdpInfo::getSdp() { } sdp - << "a=rtpmap:100 VP8/90000\na=rtpmap:101 red/90000\na=rtpmap:102 ulpfec/90000\n"; + << "a=rtpmap:100 VP8/90000\n"/*a=rtpmap:101 red/90000\na=rtpmap:102 ulpfec/90000\n"*/; sdp << "a=ssrc:" << videoSsrc << " cname:o/i14u9pJrxRKAsu\na=ssrc:" << videoSsrc << " mslabel:048f838f-2dd1-4a98-ab9e-8eb5f00abab8\na=ssrc:" << videoSsrc << " label:iSight integrada\n"; } + printf("4\n"); return sdp.str(); } From b5b609d375114699b64efdcb924d4e16bd10fa16 Mon Sep 17 00:00:00 2001 From: Pedro Rodriguez Date: Tue, 10 Jul 2012 13:15:51 +0200 Subject: [PATCH 11/29] Fixed Decoding of vp8 --- src/erizo/OneToManyProcessor.cpp | 84 ++++++++++++++---------------- src/erizo/media/MediaProcessor.cpp | 30 +++++++---- src/erizo/media/MediaProcessor.h | 5 ++ src/erizo/media/utils/RtpUtils.cpp | 1 + src/examples/Test.cpp | 63 ++++++++++------------ 5 files changed, 93 insertions(+), 90 deletions(-) diff --git a/src/erizo/OneToManyProcessor.cpp b/src/erizo/OneToManyProcessor.cpp index 792917f081..28fe7e6010 100644 --- a/src/erizo/OneToManyProcessor.cpp +++ b/src/erizo/OneToManyProcessor.cpp @@ -77,53 +77,45 @@ int OneToManyProcessor::receiveAudioData(char* buf, int len) { } int OneToManyProcessor::receiveVideoData(char* buf, int len) { - /* - int b; - int x = mp->unpackageVideoRTP(buf, len, unpackagedBuffer_, &gotFrame_); - if (x > 0) { - RTPPayloadVP8* parsed = pars.parseVP8( - (unsigned char*) unpackagedBuffer_, x); - b = parsed->dataLength; - printf("Bytes desem = %d, sobre %d reciv\n", b, len); - - } - size_ += x; - unpackagedBuffer_ += x; - if (gotFrame_) { - - unpackagedBuffer_ -= size_; - - printf("Tengo un frame desempaquetado!! Size = %d\n", size_); - - int c; - - c = mp->decodeVideo(unpackagedBuffer_, size_, decodedBuffer_, - 640 * 480 * 3 / 2, &gotDecodedFrame_); - printf("Bytes dec = %d\n", c); - - size_ = 0; - memset(unpackagedBuffer_, 0, 50000); - gotFrame_ = 0; - - if (gotDecodedFrame_) { - printf("Tengo un frame decodificado!!\n"); - gotDecodedFrame_ = 0; - //send(outBuff2, c); - } - } - */ - if (subscribers.empty() || len <= 0) - return 0; - if (sentPackets_ % 1000 == 0) { - publisher->sendFirPacket(); - } - std::map::iterator it; - for (it = subscribers.begin(); it != subscribers.end(); it++) { - memset(sendVideoBuffer_, 0, len); - memcpy(sendVideoBuffer_, buf, len); - (*it).second->receiveVideoData(sendVideoBuffer_, len); + int x = mp->unpackageVideoRTP(buf, len, unpackagedBuffer_, &gotFrame_); + size_ += x; + unpackagedBuffer_ += x; + + if (gotFrame_) { + + unpackagedBuffer_ -= size_; + + printf("Tengo un frame desempaquetado!! Size = %d\n", size_); + + int c; + + c = mp->decodeVideo(unpackagedBuffer_, size_, decodedBuffer_, + 640 * 480 * 3 / 2, &gotDecodedFrame_); + printf("Bytes dec = %d\n", c); + + size_ = 0; + + gotFrame_ = 0; + + if (gotDecodedFrame_) { + printf("Tengo un frame decodificado!!\n"); + gotDecodedFrame_ = 0; + memset(unpackagedBuffer_, 0, 50000); + //send(outBuff2, c); + } } - sentPackets_++; +// if (subscribers.empty() || len <= 0) +// return 0; +// if (sentPackets_ % 1000 == 0) { +// publisher->sendFirPacket(); +// } +// std::map::iterator it; +// for (it = subscribers.begin(); it != subscribers.end(); it++) { +// memset(sendVideoBuffer_, 0, len); +// memcpy(sendVideoBuffer_, buf, len); +// (*it).second->receiveVideoData(sendVideoBuffer_, len); +// } +// sentPackets_++; return 0; } diff --git a/src/erizo/media/MediaProcessor.cpp b/src/erizo/media/MediaProcessor.cpp index a01644c979..5a407558fe 100644 --- a/src/erizo/media/MediaProcessor.cpp +++ b/src/erizo/media/MediaProcessor.cpp @@ -743,24 +743,36 @@ int MediaProcessor::unpackageVideoRTP(char *inBuff, int inBuffLen, int sec = ntohs(head->seqnum); int ssrc = ntohl(head->ssrc); unsigned long time = ntohl(head->timestamp); - if (ssrc!= 55543) + printf("PT %d, ssrc %u, extension %d\n", head->payloadtype, ssrc, + head->extension); + if (ssrc != 55543/* && head->payloadtype!=101*/) { return -1; + } + if (head->payloadtype != 100) { + printf("EEEEEEEEEEEEEEOOOOOOOOOOOOOOOOOOOOOOOO %d\n\n\n", + head->payloadtype); + return -1; + } int l = inBuffLen - RTP_HEADER_LEN; - inBuff += RTP_HEADER_LEN; - vp8RtpHeader* vp8h = (vp8RtpHeader*) outBuff; - printf("R: %u, PartID %u , X %u \n", vp8h->R, vp8h->partId, vp8h->X); - //l--; - //inBuff++; - - memcpy(outBuff, inBuff, l); +// vp8RtpHeader* vphead = (vp8RtpHeader*) inBuff; +// printf("MIO X: %u , N:%u PartID %u\n", vphead->X, vphead->N, +// vphead->partId); + erizo::RTPPayloadVP8* parsed = pars.parseVP8((unsigned char*) inBuff, l); + printf("l : %d, parsedDatalength %u\n", l, parsed->dataLength); +// l--; +// inBuff++; +// memcpy(outBuff, inBuff, parsed->dataLength); + memcpy(outBuff, parsed->data, parsed->dataLength); if (head->marker) { + printf("Marker\n"); *gotFrame = 1; } - return l; +// return l; + return parsed->dataLength; // // if (avformat_find_stream_info(vInputFormatContext, NULL) < 0) { // return -1; diff --git a/src/erizo/media/MediaProcessor.h b/src/erizo/media/MediaProcessor.h index 4794dde1c8..1f49afc5c5 100644 --- a/src/erizo/media/MediaProcessor.h +++ b/src/erizo/media/MediaProcessor.h @@ -4,6 +4,8 @@ #include #include #include +#include "utils/RtpUtils.h" + extern "C" { @@ -123,6 +125,9 @@ class MediaProcessor { AVFormatContext *vOutputFormatContext; AVOutputFormat *vOutputFormat; + erizo::RtpParser pars; + + }; #endif /* MEDIAPROCESSOR_H_ */ diff --git a/src/erizo/media/utils/RtpUtils.cpp b/src/erizo/media/utils/RtpUtils.cpp index f1de601c4d..770c5153da 100644 --- a/src/erizo/media/utils/RtpUtils.cpp +++ b/src/erizo/media/utils/RtpUtils.cpp @@ -189,6 +189,7 @@ RTPPayloadVP8* RtpParser::parseVP8(unsigned char* data, // if (0 != ParseVP8FrameSize(parsedPacket, dataPtr, dataLength)) { // return *vp8; // } + vp8->data = dataPtr; vp8->dataLength = (unsigned int) dataLength; return vp8; diff --git a/src/examples/Test.cpp b/src/examples/Test.cpp index f6a1d6b12b..a5113e6a18 100644 --- a/src/examples/Test.cpp +++ b/src/examples/Test.cpp @@ -4,7 +4,6 @@ #include #include - #include "Test.h" using boost::asio::ip::udp; @@ -15,8 +14,6 @@ Test::Test() { mp = new MediaProcessor(); - - // audioCodecInfo *i = new audioCodecInfo; // i->codec = CODEC_ID_AMR_NB; // i->bitRate = 300000; @@ -27,7 +24,6 @@ Test::Test() { // r->codec = CODEC_ID_MP3; // mp->initAudioUnpackagerRTP(r); - videoCodecInfo *v = new videoCodecInfo; v->codec = CODEC_ID_VP8; // v->codec = CODEC_ID_MPEG4; @@ -55,12 +51,10 @@ Test::Test() { mp->initVideoPackagerRTP(r); mp->initVideoUnpackagerRTP(r); - ioservice_ = new boost::asio::io_service; resolver_ = new udp::resolver(*ioservice_); - socket_ = new udp::socket(*ioservice_, udp::endpoint(udp::v4(),40000)); - query_ = new udp::resolver::query(udp::v4(),"127.0.0.1", "50000"); - + socket_ = new udp::socket(*ioservice_, udp::endpoint(udp::v4(), 40000)); + query_ = new udp::resolver::query(udp::v4(), "127.0.0.1", "50000"); boost::thread t = boost::thread(&Test::rec, this); t.join(); @@ -73,41 +67,41 @@ Test::~Test() { void Test::rec() { - int outBuff2Size = 706*396*3/2; + int outBuff2Size = 706 * 396 * 3 / 2; - void *buff = malloc(2000); - char * outBuff = (char*)malloc(50000); - memset(outBuff, 0, 50000); - char * outBuff2 = (char*)malloc(outBuff2Size); + void *buff = malloc(2000); + char * outBuff = (char*) malloc(50000); + memset(outBuff, 0, 50000); + char * outBuff2 = (char*) malloc(outBuff2Size); - int gotFrame = 0; - int size = 0; - int gotDecFrame = 0; + int gotFrame = 0; + int size = 0; + int gotDecFrame = 0; - std::string s; - unsigned short u; - int a; - while(true) { + std::string s; + unsigned short u; + int a; + while (true) { - memset(buff, 0, 2000); + memset(buff, 0, 2000); - a = socket_->receive(boost::asio::buffer(buff, 2000)); - printf("********* RECEPCIÓN *********\n"); + a = socket_->receive(boost::asio::buffer(buff, 2000)); + printf("********* RECEPCIÓN *********\n"); printf("Bytes = %d\n", a); - int z,b; - z = mp->unpackageVideoRTP((char*)buff, a, outBuff, &gotFrame); + int z, b; + z = mp->unpackageVideoRTP((char*) buff, a, outBuff, &gotFrame); // RTPPayloadVP8* parsed = pars.parseVP8((unsigned char*)outBuff, z); // b = parsed->dataLength; - //int c = parsed.dataLength; +// int c = parsed.dataLength; // printf("Bytes desem = %d prevp8 %d\n", b, z ); size += z; outBuff += z; - if(gotFrame) { + if (gotFrame) { outBuff -= size; @@ -115,21 +109,21 @@ void Test::rec() { int c; - c = mp->decodeVideo(outBuff, size, outBuff2, outBuff2Size, &gotDecFrame); + c = mp->decodeVideo(outBuff, size, outBuff2, outBuff2Size, + &gotDecFrame); printf("Bytes dec = %d\n", c); - size = 0; memset(outBuff, 0, 50000); gotFrame = 0; - if(gotDecFrame) { + if (gotDecFrame) { printf("Tengo un frame decodificado!!"); gotDecFrame = 0; send(outBuff2, c); } } - } + } } @@ -137,8 +131,8 @@ void Test::send(char *buff, int buffSize) { printf("\n********* ENVÍO *********"); - char *buffSend = (char*)malloc(buffSize); - char *buffSend2 = (char*)malloc(buffSize); + char *buffSend = (char*) malloc(buffSize); + char *buffSend2 = (char*) malloc(buffSize); int a = mp->encodeVideo(buff, buffSize, buffSend, buffSize); @@ -150,9 +144,8 @@ void Test::send(char *buff, int buffSize) { udp::resolver::iterator iterator = resolver_->resolve(*query_); - // socket_->send_to(buffSend2, b, "toronado.dit.upm.es", 5005); - socket_->send_to(boost::asio::buffer(buffSend2,b),*iterator); + socket_->send_to(boost::asio::buffer(buffSend2, b), *iterator); free(buffSend); free(buffSend2); From 1bbd5593ac934de9983ca9371e62508330f1622c Mon Sep 17 00:00:00 2001 From: Pedro Rodriguez Date: Thu, 12 Jul 2012 13:03:51 +0200 Subject: [PATCH 12/29] Refactoring media --- src/erizo/OneToManyProcessor.cpp | 127 ++-- src/erizo/OneToManyProcessor.h | 6 +- src/erizo/SdpInfo.cpp | 2 +- src/erizo/SdpInfo.h | 2 +- src/erizo/media/MediaProcessor.cpp | 903 ++++++++++++++++------------- src/erizo/media/MediaProcessor.h | 241 +++++--- src/examples/Test.cpp | 236 ++++---- src/examples/Test.h | 8 +- 8 files changed, 840 insertions(+), 685 deletions(-) diff --git a/src/erizo/OneToManyProcessor.cpp b/src/erizo/OneToManyProcessor.cpp index 28fe7e6010..5990933d12 100644 --- a/src/erizo/OneToManyProcessor.cpp +++ b/src/erizo/OneToManyProcessor.cpp @@ -14,42 +14,44 @@ OneToManyProcessor::OneToManyProcessor() : publisher = NULL; sentPackets_ = 0; - + ip = new InputProcessor(); + MediaInfo m; + ip->init(m, this); // Media processing - unpackagedBuffer_ = (char*) malloc(50000); - memset(unpackagedBuffer_, 0, 50000); - - gotFrame_ = 0; - size_ = 0; - gotDecodedFrame_ = 0; - - mp = new MediaProcessor(); - videoCodecInfo *v = new videoCodecInfo; - v->codec = CODEC_ID_VP8; - // v->codec = CODEC_ID_MPEG4; - v->width = 640; - v->height = 480; - decodedBuffer_ = (char*) malloc(v->width * v->height * 3 / 2); - memset(decodedBuffer_, 0, v->width * v->height * 3 / 2); - mp->initVideoDecoder(v); - - videoCodecInfo *c = new videoCodecInfo; - //c->codec = CODEC_ID_MPEG2VIDEO; - c->codec = CODEC_ID_VP8; - c->width = v->width; - c->height = v->height; - c->frameRate = 24; - c->bitRate = 1024; - c->maxInter = 0; - - mp->initVideoCoder(c); - - RTPInfo *r = new RTPInfo; - //r->codec = CODEC_ID_MPEG2VIDEO; - // r->codec = CODEC_ID_MPEG4; - mp->initVideoPackagerRTP(r); - mp->initVideoUnpackagerRTP(r); +// unpackagedBuffer_ = (char*) malloc(50000); +// memset(unpackagedBuffer_, 0, 50000); +// +// gotFrame_ = 0; +// size_ = 0; +// gotDecodedFrame_ = 0; +// +// mp = new MediaProcessor(); +// videoCodecInfo *v = new videoCodecInfo; +// v->codec = CODEC_ID_VP8; +// // v->codec = CODEC_ID_MPEG4; +// v->width = 640; +// v->height = 480; +// decodedBuffer_ = (char*) malloc(v->width * v->height * 3 / 2); +// memset(decodedBuffer_, 0, v->width * v->height * 3 / 2); +// mp->initVideoDecoder(v); +// +// videoCodecInfo *c = new videoCodecInfo; +// //c->codec = CODEC_ID_MPEG2VIDEO; +// c->codec = CODEC_ID_H263P; +// c->width = v->width; +// c->height = v->height; +// c->frameRate = 24; +// c->bitRate = 1024; +// c->maxInter = 0; +// +// mp->initVideoCoder(c); +// +// RTPInfo *r = new RTPInfo; +// r->codec = CODEC_ID_H263P; +// +// mp->initVideoPackagerRTP(r); +// mp->initVideoUnpackagerRTP(r); } @@ -77,48 +79,27 @@ int OneToManyProcessor::receiveAudioData(char* buf, int len) { } int OneToManyProcessor::receiveVideoData(char* buf, int len) { - int x = mp->unpackageVideoRTP(buf, len, unpackagedBuffer_, &gotFrame_); - size_ += x; - unpackagedBuffer_ += x; - - if (gotFrame_) { - - unpackagedBuffer_ -= size_; - - printf("Tengo un frame desempaquetado!! Size = %d\n", size_); - - int c; - - c = mp->decodeVideo(unpackagedBuffer_, size_, decodedBuffer_, - 640 * 480 * 3 / 2, &gotDecodedFrame_); - printf("Bytes dec = %d\n", c); - size_ = 0; - - gotFrame_ = 0; - - if (gotDecodedFrame_) { - printf("Tengo un frame decodificado!!\n"); - gotDecodedFrame_ = 0; - memset(unpackagedBuffer_, 0, 50000); - //send(outBuff2, c); - } - } -// if (subscribers.empty() || len <= 0) -// return 0; -// if (sentPackets_ % 1000 == 0) { -// publisher->sendFirPacket(); -// } -// std::map::iterator it; -// for (it = subscribers.begin(); it != subscribers.end(); it++) { -// memset(sendVideoBuffer_, 0, len); -// memcpy(sendVideoBuffer_, buf, len); -// (*it).second->receiveVideoData(sendVideoBuffer_, len); -// } -// sentPackets_++; - return 0; + ip->receiveVideoData(buf,len); + +//// if (subscribers.empty() || len <= 0) +//// return 0; +//// if (sentPackets_ % 1000 == 0) { +//// publisher->sendFirPacket(); +//// } +//// std::map::iterator it; +//// for (it = subscribers.begin(); it != subscribers.end(); it++) { +//// memset(sendVideoBuffer_, 0, len); +//// memcpy(sendVideoBuffer_, buf, len); +//// (*it).second->receiveVideoData(sendVideoBuffer_, len); +//// } +//// sentPackets_++; +// return 0; } +void OneToManyProcessor::receiveRawData(unsigned char* buf, int len){ + printf("Received %d", len); +} void OneToManyProcessor::setPublisher(WebRtcConnection* webRtcConn) { this->publisher = webRtcConn; diff --git a/src/erizo/OneToManyProcessor.h b/src/erizo/OneToManyProcessor.h index a778766b00..ad9004e77b 100644 --- a/src/erizo/OneToManyProcessor.h +++ b/src/erizo/OneToManyProcessor.h @@ -20,7 +20,7 @@ class WebRtcConnection; * Represents a One to Many connection. * Receives media from one publisher and retransmits it to every subscriber. */ -class OneToManyProcessor : public MediaReceiver { +class OneToManyProcessor : public MediaReceiver, public RawDataReceiver { public: OneToManyProcessor(); virtual ~OneToManyProcessor(); @@ -42,9 +42,11 @@ class OneToManyProcessor : public MediaReceiver { void removeSubscriber(int peerId); int receiveAudioData(char* buf, int len); int receiveVideoData(char* buf, int len); + void receiveRawData (unsigned char* buf, int len); WebRtcConnection *publisher; - MediaProcessor *mp; +// MediaProcessor *mp; + InputProcessor* ip; std::map subscribers; private: diff --git a/src/erizo/SdpInfo.cpp b/src/erizo/SdpInfo.cpp index c2ea23372d..e3553a8e7c 100644 --- a/src/erizo/SdpInfo.cpp +++ b/src/erizo/SdpInfo.cpp @@ -197,7 +197,7 @@ bool SdpInfo::processSdp(const std::string& sdp) { const char *ice_user = "a=ice-ufrag"; const char *ice_pass = "a=ice-pwd"; const char *ssrctag = "a=ssrc"; - MediaType mtype = OTHER; + MediaType mtype = OTHER_MEDIA; bool bundle = false; while (std::getline(iss, strLine)) { diff --git a/src/erizo/SdpInfo.h b/src/erizo/SdpInfo.h index b573b101a9..75b57faa64 100644 --- a/src/erizo/SdpInfo.h +++ b/src/erizo/SdpInfo.h @@ -19,7 +19,7 @@ enum HostType { * Channel types */ enum MediaType { - VIDEO_TYPE, AUDIO_TYPE, OTHER + VIDEO_TYPE, AUDIO_TYPE, BOTH_MEDIA, OTHER_MEDIA }; /** * SRTP info. diff --git a/src/erizo/media/MediaProcessor.cpp b/src/erizo/media/MediaProcessor.cpp index 5a407558fe..1224ba06b0 100644 --- a/src/erizo/media/MediaProcessor.cpp +++ b/src/erizo/media/MediaProcessor.cpp @@ -4,81 +4,110 @@ //UDPSocket *sock=NULL; //UDPSocket *out=NULL; -std::string s; -unsigned short u; -MediaProcessor::MediaProcessor() { +namespace erizo { + +InputProcessor::InputProcessor() { - audioCoder = 0; audioDecoder = 0; - videoCoder = 0; videoDecoder = 0; - audioPackager = 0; audioUnpackager = 0; - videoPackager = 0; videoUnpackager = 0; + gotUnpackagedFrame_ = false; + upackagedSize_ = 0; + + decodedBuffer_ = NULL; avcodec_register_all(); av_register_all(); - avformat_network_init(); } -MediaProcessor::~MediaProcessor() { +InputProcessor::~InputProcessor() { - if (audioCoder == 1) { - avcodec_close(aCoderContext); - av_free(aCoderContext); - } if (audioDecoder == 1) { avcodec_close(aDecoderContext); av_free(aDecoderContext); } - if (videoCoder == 1) { - avcodec_close(vCoderContext); - av_free(vCoderContext); - av_free(cPicture); - } - if (videoDecoder == 1) { avcodec_close(vDecoderContext); av_free(vDecoderContext); av_free(dPicture); } + if (decodedBuffer_ != NULL) { + free(decodedBuffer_); + } } -bool MediaProcessor::initAudioCoder(const audioCodecInfo *audioCodec) { +int InputProcessor::init(const MediaInfo &info, RawDataReceiver* receiver) { + this->mediaInfo = info; + this->rawReceiver_ = receiver; - aCoder = avcodec_find_encoder(audioCodec->codec); - if (!aCoder) { - printf("Encoder de audio no encontrado"); - return false; + if (mediaInfo.hasVideo) { + mediaInfo.videoCodec.codec = CODEC_ID_VP8; + decodedBuffer_ = (unsigned char*) malloc( + info.videoCodec.width * info.videoCodec.height * 3 / 2); + unpackagedBuffer_ = (unsigned char*) malloc(UNPACKAGED_BUFFER_SIZE); + memset(decodedBuffer_, 0, + info.videoCodec.width * info.videoCodec.height * 3 / 2); + this->initVideoDecoder(); + this->initVideoUnpackager(); } - aCoderContext = avcodec_alloc_context3(aCoder); - if (!aCoderContext) { - printf("Error de memoria en coder de audio"); - return false; - } + return 0; +} - aCoderContext->sample_fmt = AV_SAMPLE_FMT_S16; - aCoderContext->bit_rate = audioCodec->bitRate; - aCoderContext->sample_rate = audioCodec->sampleRate; - aCoderContext->channels = 1; +int InputProcessor::receiveAudioData(char* buf, int len) { + return 3; +} +int InputProcessor::receiveVideoData(char* buf, int len) { - if (avcodec_open2(aCoderContext, aCoder, NULL) < 0) { - printf("Error al abrir el coder de audio"); - return false; - } + if (videoUnpackager && videoDecoder) { + int ret = unpackageVideoRTP(reinterpret_cast(buf), len, + unpackagedBuffer_, &gotUnpackagedFrame_); + // int x = mp->unpackageVideoRTP(buf, len, unpackagedBuffer_, &gotFrame_); + upackagedSize_ += ret; + unpackagedBuffer_ += ret; - audioCoder = 1; - return true; + if (gotUnpackagedFrame_) { + + unpackagedBuffer_ -= upackagedSize_; + + printf("Tengo un frame desempaquetado!! Size = %d\n", + upackagedSize_); + + int c; + int gotDecodedFrame = 0; + + c = this->decodeVideo(unpackagedBuffer_, upackagedSize_, + decodedBuffer_, 640 * 480 * 3 / 2, &gotDecodedFrame); + + upackagedSize_ = 0; + gotUnpackagedFrame_ = 0; + + printf("Bytes dec = %d\n", c); + if (gotDecodedFrame) { + printf("Tengo un frame decodificado!!\n"); + gotDecodedFrame = 0; + memset(unpackagedBuffer_, 0, 50000); + unsigned char *buffSend = (unsigned char*) malloc(c); + memcpy(buffSend, decodedBuffer_, c); + +// int a = this->encodeVideo(decodedBuffer_, c, buffSend, +// buffSize); + rawReceiver_->receiveRawData(buffSend, c); + } + + } + return 3; + } + return 7; } -bool MediaProcessor::initAudioDecoder(const audioCodecInfo *audioCodec) { +bool InputProcessor::initAudioDecoder() { - aDecoder = avcodec_find_decoder(audioCodec->codec); + aDecoder = avcodec_find_decoder(mediaInfo.audioCodec.codec); if (!aDecoder) { printf("Decoder de audio no encontrado"); return false; @@ -91,8 +120,8 @@ bool MediaProcessor::initAudioDecoder(const audioCodecInfo *audioCodec) { } aDecoderContext->sample_fmt = AV_SAMPLE_FMT_S16; - aDecoderContext->bit_rate = audioCodec->bitRate; - aDecoderContext->sample_rate = audioCodec->sampleRate; + aDecoderContext->bit_rate = mediaInfo.audioCodec.bitRate; + aDecoderContext->sample_rate = mediaInfo.audioCodec.sampleRate; aDecoderContext->channels = 1; if (avcodec_open2(aDecoderContext, aDecoder, NULL) < 0) { @@ -105,60 +134,10 @@ bool MediaProcessor::initAudioDecoder(const audioCodecInfo *audioCodec) { } -bool MediaProcessor::initVideoCoder(const videoCodecInfo *videoCodec) { - - vCoder = avcodec_find_encoder(videoCodec->codec); - if (!vCoder) { - printf("Encoder de vídeo no encontrado"); - return false; - } - - vCoderContext = avcodec_alloc_context3(vCoder); - if (!vCoderContext) { - printf("Error de memoria en coder de vídeo"); - return false; - } - - vCoderContext->bit_rate = videoCodec->bitRate; - vCoderContext->bit_rate_tolerance = 1.1 * videoCodec->bitRate - / videoCodec->frameRate; - vCoderContext->rc_max_rate = videoCodec->bitRate * 2; - - if (videoCodec->frameRate >= 1.0) { - vCoderContext->rc_buffer_size = videoCodec->bitRate; // 1 second stored, in bps - } else { - vCoderContext->rc_buffer_size = 1.1 * videoCodec->bitRate - / videoCodec->frameRate; - } - - vCoderContext->rc_buffer_aggressivity = 1.0; - vCoderContext->gop_size = videoCodec->maxInter; - vCoderContext->max_b_frames = 0; - vCoderContext->me_method = ME_EPZS; - - vCoderContext->width = videoCodec->width; - vCoderContext->height = videoCodec->height; - vCoderContext->pix_fmt = PIX_FMT_YUV420P; - vCoderContext->time_base = (AVRational) {1000, 1000*videoCodec->frameRate}; - - if (avcodec_open2(vCoderContext, vCoder, NULL) < 0) { - printf("Error al abrir el decoder de vídeo"); - return false; - } - - cPicture = avcodec_alloc_frame(); - if (!cPicture) { - printf("Error de memoria en frame del coder de vídeo"); - return false; - } - - videoCoder = 1; - return true; -} - -bool MediaProcessor::initVideoDecoder(const videoCodecInfo *videoCodec) { +bool InputProcessor::initVideoDecoder() { - vDecoder = avcodec_find_decoder(videoCodec->codec); + videoCodecInfo& videoCodec = mediaInfo.videoCodec; + vDecoder = avcodec_find_decoder(videoCodec.codec); if (!vDecoder) { printf("Decoder de vídeo no encontrado"); return false; @@ -170,8 +149,8 @@ bool MediaProcessor::initVideoDecoder(const videoCodecInfo *videoCodec) { return false; } - vDecoderContext->width = videoCodec->width; - vDecoderContext->height = videoCodec->height; + vDecoderContext->width = videoCodec.width; + vDecoderContext->height = videoCodec.height; if (avcodec_open2(vDecoderContext, vDecoder, NULL) < 0) { printf("Error al abrir el decoder de vídeo"); @@ -188,192 +167,37 @@ bool MediaProcessor::initVideoDecoder(const videoCodecInfo *videoCodec) { return true; } -bool MediaProcessor::initAudioPackagerRTP(const RTPInfo *audioRTP) { - - aOutputFormatContext = avformat_alloc_context(); - if (!aOutputFormatContext) { - printf("Memory Error al inicializar audioPackager"); - return false; - } - - aOutputFormat = av_guess_format("rtp", NULL, NULL); - if (aOutputFormat == NULL) { - printf("Could not guess format al inicializar audioPackager"); - return false; - } - - aOutputFormatContext->oformat = aOutputFormat; - aOutputFormat->audio_codec = audioRTP->codec; +bool InputProcessor::initAudioUnpackagerRTP() { - audioPackager = 1; - return true; -} + if (mediaInfo.proccessorType != RTP_ONLY) { + aInputFormatContext = avformat_alloc_context(); + if (!aInputFormatContext) { + printf("Memory Error al inicializar audioUnpackager"); + return false; + } -bool MediaProcessor::initAudioUnpackagerRTP(const RTPInfo *audioRTP) { + aInputFormat = av_find_input_format("rtp"); + if (aInputFormat == NULL) { + printf("Could not guess format al inicializar audioUnpackager"); + return false; + } - aInputFormatContext = avformat_alloc_context(); - if (!aInputFormatContext) { - printf("Memory Error al inicializar audioUnpackager"); - return false; - } + aInputFormatContext->iformat = aInputFormat; - aInputFormat = av_find_input_format("rtp"); - if (aInputFormat == NULL) { - printf("Could not guess format al inicializar audioUnpackager"); - return false; + audioUnpackager = 1; } - - //aInputFormat->flags = AVFMT_NOFILE; - aInputFormatContext->iformat = aInputFormat; - - audioUnpackager = 1; - return true; -} - -bool MediaProcessor::initVideoPackagerRTP(const RTPInfo *videoRTP) { -// -// vOutputFormatContext = avformat_alloc_context(); -// if (!vOutputFormatContext){ -// printf("Memory Error al inicializar videoPackager"); -// return false; -// } -// -// vOutputFormat = av_guess_format("rtp",NULL,NULL); -// if (vOutputFormat == NULL){ -// printf("Could not guess format al inicializar videoPackager"); -// return false; -// } -// -// vOutputFormatContext->oformat=vOutputFormat; -// vOutputFormat->video_codec = videoRTP->codec; - - vRTPInfo = (RTPInfo*) videoRTP; - vRTPInfo->seqNum = 0; - vRTPInfo->ssrc = 5; - - videoPackager = 1; return true; } -int readPacket(void *opaque, uint8_t *buf, int buf_size) { - /* - if (sock==NULL){ - sock = new UDPSocket(5004); - printf("Abierto socket\n"); - } - - int a = sock->recvFrom(buf, buf_size, s, u); - rtpHeader *h = (rtpHeader*)buf; - h->payloadtype = 33; - if (a>12){ - buf = buf+12; - a-=12; - } - printf("Read packet %d, buf_size %d\n", a, buf_size); - */ - return 0; - -} - -int writePacket(void *opaque, uint8_t *buf, int buf_size) { - - printf("Write packet\n"); - - return 0; - -} -bool MediaProcessor::initVideoUnpackagerRTP(const RTPInfo *videoRTP) { - - vInputFormatContext = avformat_alloc_context(); - if (!vInputFormatContext) { - printf("Memory Error al inicializar videoUnpackager"); - return false; - } - - vInputFormat = av_find_input_format("rtp"); - if (vInputFormat == NULL) { - printf("Could not find format al inicializar videoUnpackager"); - return false; - } - -// vInputFormat->flags |= AVFMT_NOFILE ; -// vInputFormatContext->flags |= AVFMT_NOFILE; - vInputFormatContext->iformat = vInputFormat; - - int size = 15000; - unsigned char *buff = (unsigned char*) av_malloc(size); - - AVIOContext *io = avio_alloc_context(buff, size, 0, NULL, &readPacket, - &writePacket, NULL); - - vInputFormatContext->pb = io; -// vInputFormatContext->flags |= AVFMT_FLAG_CUSTOM_IO; - vInputFormatContext->video_codec_id = CODEC_ID_H264; - printf("Config %s\n", avformat_configuration()); - int res = avformat_open_input(&vInputFormatContext, "", vInputFormat, NULL); - printf( - "INPUT OPEN********************************************************%d \n", - res); - AVInputFormat *fmt = NULL; +bool InputProcessor::initVideoUnpackager() { videoUnpackager = 1; return true; } -int MediaProcessor::encodeAudio(char *inBuff, int nSamples, char *outBuff) { - - if (audioCoder == 0) { - printf("No se han inicializado los parámetros del audioCoder"); - return -1; - } - - //Puede fallar. Revisar samples. Cogido de libavcodec/utils.c del paso de avcodec_encode_audio a avcodec_encode_audio2 - //avcodec_encode_audio(aCoderContext, (unsigned char*)outBuff, nSamples*2, (short*)inBuff); - - AVPacket pkt; - AVFrame frame0; - AVFrame *frame; - int ret, samples_size, got_packet; - - av_init_packet(&pkt); - pkt.data = (unsigned char*) inBuff; - pkt.size = nSamples * 2; - - frame = &frame0; - avcodec_get_frame_defaults(frame); - - frame->nb_samples = nSamples; - - samples_size = av_samples_get_buffer_size(NULL, aCoderContext->channels, - frame->nb_samples, aCoderContext->sample_fmt, 1); - - if ((ret = avcodec_fill_audio_frame(frame, aCoderContext->channels, - aCoderContext->sample_fmt, (const uint8_t *) inBuff, samples_size, - 1))) - return ret; - - frame->pts = AV_NOPTS_VALUE; - //aCoderContext->internal->sample_count += frame->nb_samples; - - got_packet = 0; - - ret = avcodec_encode_audio2(aCoderContext, &pkt, frame, &got_packet); - - if (!ret && got_packet && aCoderContext->coded_frame) { - aCoderContext->coded_frame->pts = pkt.pts; - aCoderContext->coded_frame->key_frame = !!(pkt.flags & AV_PKT_FLAG_KEY); - } - //ff_packet_free_side_data(&pkt); - - if (frame && frame->extended_data != frame->data) - av_freep(&frame->extended_data); - - return ret; - -} - -int MediaProcessor::decodeAudio(char *inBuff, int inBuffLen, char *outBuff) { +int InputProcessor::decodeAudio(unsigned char* inBuff, int inBuffLen, + unsigned char* outBuff) { if (audioDecoder == 0) { printf("No se han inicializado los parámetros del audioDecoder\n"); @@ -464,59 +288,8 @@ int MediaProcessor::decodeAudio(char *inBuff, int inBuffLen, char *outBuff) { } -int MediaProcessor::encodeVideo(char *inBuff, int inBuffLen, char *outBuff, - int outBuffLen) { - - if (videoCoder == 0) { - printf("No se han inicializado los parámetros del videoCoder"); - return -1; - } - - int size = vCoderContext->width * vCoderContext->height; - - cPicture->pts = AV_NOPTS_VALUE; - cPicture->data[0] = (unsigned char*) inBuff; - cPicture->data[1] = (unsigned char*) inBuff + size; - cPicture->data[2] = (unsigned char*) inBuff + size + size / 4; - cPicture->linesize[0] = vCoderContext->width; - cPicture->linesize[1] = vCoderContext->width / 2; - cPicture->linesize[2] = vCoderContext->width / 2; - - AVPacket pkt; - int ret = 0; - int got_packet = 0; - - if (outBuffLen < FF_MIN_BUFFER_SIZE) { - printf("buffer smaller than minimum sizeS"); - return -1; - } - - av_init_packet(&pkt); - pkt.data = (unsigned char*) outBuff; - pkt.size = outBuffLen; - - ret = avcodec_encode_video2(vCoderContext, &pkt, cPicture, &got_packet); - - if (!ret && got_packet && vCoderContext->coded_frame) { - vCoderContext->coded_frame->pts = pkt.pts; - vCoderContext->coded_frame->key_frame = !!(pkt.flags & AV_PKT_FLAG_KEY); - } - - /* free any side data since we cannot return it */ - if (pkt.side_data_elems > 0) { - int i; - for (i = 0; i < pkt.side_data_elems; i++) - av_free(pkt.side_data[i].data); - av_freep(&pkt.side_data); - pkt.side_data_elems = 0; - } - - return ret ? ret : pkt.size; - -} - -int MediaProcessor::decodeVideo(char *inBuff, int inBuffLen, char *outBuff, - int outBuffLen, int *gotFrame) { +int InputProcessor::decodeVideo(unsigned char* inBuff, int inBuffLen, + unsigned char* outBuff, int outBuffLen, int* gotFrame) { if (videoDecoder == 0) { printf("No se han inicializado los parámetros del videoDecoder"); @@ -527,7 +300,7 @@ int MediaProcessor::decodeVideo(char *inBuff, int inBuffLen, char *outBuff, AVPacket avpkt; - avpkt.data = (unsigned char*) inBuff; + avpkt.data = inBuff; avpkt.size = inBuffLen; int got_picture; @@ -565,9 +338,9 @@ int MediaProcessor::decodeVideo(char *inBuff, int inBuffLen, char *outBuff, return outSize * 3 / 2; } - unsigned char *lum = (unsigned char*) outBuff; - unsigned char *cromU = (unsigned char*) outBuff + outSize; - unsigned char *cromV = (unsigned char*) outBuff + outSize + outSize / 4; + unsigned char *lum = outBuff; + unsigned char *cromU = outBuff + outSize; + unsigned char *cromV = outBuff + outSize + outSize / 4; unsigned char *src = NULL; int src_linesize, dst_linesize; @@ -605,35 +378,8 @@ int MediaProcessor::decodeVideo(char *inBuff, int inBuffLen, char *outBuff, return outSize * 3 / 2; } -int MediaProcessor::packageAudioRTP(char *inBuff, int inBuffLen, - char *outBuff) { - - if (audioPackager == 0) { - printf("No se ha inicializado el codec de output audio RTP"); - return -1; - } - - AVIOContext *c = avio_alloc_context((unsigned char*) outBuff, 2000, 1, NULL, - NULL, NULL, NULL); - - aOutputFormatContext->pb = c; - aOutputFormatContext->flags = AVFMT_NOFILE; - - AVPacket pkt; - av_init_packet(&pkt); - pkt.data = (unsigned char*) inBuff; - pkt.size = inBuffLen; - - int ret = av_write_frame(aOutputFormatContext, &pkt); - - av_free_packet(&pkt); - av_free(c); - - return ret; -} - -int MediaProcessor::unpackageAudioRTP(char *inBuff, int inBuffLen, - char *outBuff) { +int InputProcessor::unpackageAudioRTP(unsigned char* inBuff, int inBuffLen, + unsigned char* outBuff) { /* if (audioUnpackager == 0) { @@ -680,56 +426,8 @@ int MediaProcessor::unpackageAudioRTP(char *inBuff, int inBuffLen, return l; } -int MediaProcessor::packageVideoRTP(char *inBuff, int inBuffLen, - char *outBuff) { - - if (videoPackager == 0) { - printf("No se ha inicailizado el codec de output vídeo RTP"); - return -1; - } - - int l = inBuffLen + RTP_HEADER_LEN; - - rtpHeader * head = (rtpHeader*) outBuff; - - timeval time; - gettimeofday(&time, NULL); - long millis = (time.tv_sec * 1000) + (time.tv_usec / 1000); - - head->version = 2; //v = 2 - head->extension = 0; - head->marker = 1; //n?0:1; - head->padding = 0; - head->cc = 0; - head->seqnum = htons(vRTPInfo->seqNum++); - head->timestamp = htonl(millis); - head->ssrc = htonl(vRTPInfo->ssrc); - head->payloadtype = 34; //32; - - outBuff += RTP_HEADER_LEN; - - memcpy(outBuff, inBuff, inBuffLen); - -// AVIOContext *c = avio_alloc_context((unsigned char*)outBuff, l, 1, NULL, NULL, NULL, NULL); -// -// vOutputFormatContext->pb = c; -// vOutputFormatContext->flags = AVFMT_NOFILE; -// -// AVPacket pkt; -// av_init_packet(&pkt); -// pkt.data = (unsigned char*)inBuff; -// pkt.size = inBuffLen; -// -// int ret = av_write_frame(vOutputFormatContext,&pkt); -// -// av_free_packet(&pkt); -// av_free(c); - - return l; -} - -int MediaProcessor::unpackageVideoRTP(char *inBuff, int inBuffLen, - char *outBuff, int *gotFrame) { +int InputProcessor::unpackageVideoRTP(unsigned char* inBuff, int inBuffLen, + unsigned char* outBuff, int *gotFrame) { /* if (videoUnpackager == 0) { printf("No se ha inicailizado el codec de input vídeo RTP"); @@ -745,14 +443,14 @@ int MediaProcessor::unpackageVideoRTP(char *inBuff, int inBuffLen, unsigned long time = ntohl(head->timestamp); printf("PT %d, ssrc %u, extension %d\n", head->payloadtype, ssrc, head->extension); - if (ssrc != 55543/* && head->payloadtype!=101*/) { - return -1; - } - if (head->payloadtype != 100) { - printf("EEEEEEEEEEEEEEOOOOOOOOOOOOOOOOOOOOOOOO %d\n\n\n", - head->payloadtype); - return -1; - } +// if (ssrc != 55543/* && head->payloadtype!=101*/) { +// return -1; +// } +// if (head->payloadtype != 100) { +// printf("EEEEEEEEEEEEEEOOOOOOOOOOOOOOOOOOOOOOOO %d\n\n\n", +// head->payloadtype); +// return -1; +// } int l = inBuffLen - RTP_HEADER_LEN; inBuff += RTP_HEADER_LEN; // vp8RtpHeader* vphead = (vp8RtpHeader*) inBuff; @@ -796,3 +494,380 @@ int MediaProcessor::unpackageVideoRTP(char *inBuff, int inBuffLen, } +OutputProcessor::OutputProcessor() { + + audioCoder = 0; + videoCoder = 0; + + audioPackager = 0; + videoPackager = 0; + + encodedBuffer_ = NULL; + packagedBuffer_ = NULL; + + avcodec_register_all(); + av_register_all(); +} + +OutputProcessor::~OutputProcessor() { + + if (audioCoder == 1) { + avcodec_close(aCoderContext); + av_free(aCoderContext); + } + + if (videoCoder == 1) { + avcodec_close(vCoderContext); + av_free(vCoderContext); + av_free(cPicture); + } + if (encodedBuffer_) { + free(encodedBuffer_); + } + if (packagedBuffer_) { + free(packagedBuffer_); + } +} + +int OutputProcessor::init(const MediaInfo &info) { + this->mediaInfo = info; + + encodedBuffer_ = (unsigned char*) malloc(UNPACKAGED_BUFFER_SIZE); + packagedBuffer_ = (unsigned char*) malloc(UNPACKAGED_BUFFER_SIZE); + + videoCodecInfo c; + c.codec = CODEC_ID_H264; + c.width = 640; + c.height = 480; + c.frameRate = 24; + c.bitRate = 1024; + c.maxInter = 0; + + this->initVideoCoder(c); + + RTPInfo r; + r.codec = CODEC_ID_H263P; + + this->initVideoPackagerRTP(r); + return 0; +} + +void OutputProcessor::receiveRawData(unsigned char* data, int len) { + int a = this->encodeVideo(data, len, encodedBuffer_, + UNPACKAGED_BUFFER_SIZE); + + printf("\nBytes codificados = %d", a); + + int b = this->packageVideoRTP(encodedBuffer_, a, packagedBuffer_); + printf("\nBytes empaquetados = %d", b); +} +bool OutputProcessor::initAudioCoder(const audioCodecInfo& audioCodec) { + + aCoder = avcodec_find_encoder(audioCodec.codec); + if (!aCoder) { + printf("Encoder de audio no encontrado"); + return false; + } + + aCoderContext = avcodec_alloc_context3(aCoder); + if (!aCoderContext) { + printf("Error de memoria en coder de audio"); + return false; + } + + aCoderContext->sample_fmt = AV_SAMPLE_FMT_S16; + aCoderContext->bit_rate = audioCodec.bitRate; + aCoderContext->sample_rate = audioCodec.sampleRate; + aCoderContext->channels = 1; + + if (avcodec_open2(aCoderContext, aCoder, NULL) < 0) { + printf("Error al abrir el coder de audio"); + return false; + } + + audioCoder = 1; + return true; +} + +bool OutputProcessor::initVideoCoder(const videoCodecInfo& videoCodec) { + + vCoder = avcodec_find_encoder(videoCodec.codec); + if (!vCoder) { + printf("Encoder de vídeo no encontrado"); + return false; + } + + vCoderContext = avcodec_alloc_context3(vCoder); + if (!vCoderContext) { + printf("Error de memoria en coder de vídeo"); + return false; + } + + vCoderContext->bit_rate = videoCodec.bitRate; + vCoderContext->bit_rate_tolerance = 1.1 * videoCodec.bitRate + / videoCodec.frameRate; + vCoderContext->rc_max_rate = videoCodec.bitRate * 2; + + if (videoCodec.frameRate >= 1.0) { + vCoderContext->rc_buffer_size = videoCodec.bitRate; // 1 second stored, in bps + } else { + vCoderContext->rc_buffer_size = 1.1 * videoCodec.bitRate + / videoCodec.frameRate; + } + + vCoderContext->rc_buffer_aggressivity = 1.0; + vCoderContext->gop_size = videoCodec.maxInter; + vCoderContext->max_b_frames = 0; + vCoderContext->me_method = ME_EPZS; + + vCoderContext->width = videoCodec.width; + vCoderContext->height = videoCodec.height; + vCoderContext->pix_fmt = PIX_FMT_YUV420P; + vCoderContext->time_base = (AVRational) {1000, 1000*videoCodec.frameRate}; + + if (avcodec_open2(vCoderContext, vCoder, NULL) < 0) { + printf("Error al abrir el decoder de vídeo"); + return false; + } + + cPicture = avcodec_alloc_frame(); + if (!cPicture) { + printf("Error de memoria en frame del coder de vídeo"); + return false; + } + + videoCoder = 1; + return true; +} + +bool OutputProcessor::initAudioPackagerRTP(const RTPInfo& audioRTP) { + + aOutputFormatContext = avformat_alloc_context(); + if (!aOutputFormatContext) { + printf("Memory Error al inicializar audioPackager"); + return false; + } + + aOutputFormat = av_guess_format("rtp", NULL, NULL); + if (aOutputFormat == NULL) { + printf("Could not guess format al inicializar audioPackager"); + return false; + } + + aOutputFormatContext->oformat = aOutputFormat; + aOutputFormat->audio_codec = audioRTP.codec; + + audioPackager = 1; + return true; +} + +bool OutputProcessor::initVideoPackagerRTP(const RTPInfo& videoRTP) { +// +// vOutputFormatContext = avformat_alloc_context(); +// if (!vOutputFormatContext){ +// printf("Memory Error al inicializar videoPackager"); +// return false; +// } +// +// vOutputFormat = av_guess_format("rtp",NULL,NULL); +// if (vOutputFormat == NULL){ +// printf("Could not guess format al inicializar videoPackager"); +// return false; +// } +// +// vOutputFormatContext->oformat=vOutputFormat; +// vOutputFormat->video_codec = videoRTP->codec; + +// vRTPInfo = (RTPInfo*) videoRTP; +// vRTPInfo->seqNum = 0; +// vRTPInfo->ssrc = 5; + + videoPackager = 1; + return true; +} + +int OutputProcessor::packageVideoRTP(unsigned char* inBuff, int inBuffLen, + unsigned char* outBuff) { + + if (videoPackager == 0) { + printf("No se ha inicailizado el codec de output vídeo RTP"); + return -1; + } + + int l = inBuffLen + RTP_HEADER_LEN; + + rtpHeader * head = (rtpHeader*) outBuff; + + timeval time; + gettimeofday(&time, NULL); + long millis = (time.tv_sec * 1000) + (time.tv_usec / 1000); + + head->version = 2; //v = 2 + head->extension = 0; + head->marker = 1; //n?0:1; + head->padding = 0; + head->cc = 0; +// head->seqnum = htons(vRTPInfo->seqNum++); + head->timestamp = htonl(millis); + head->ssrc = htonl(vRTPInfo->ssrc); + head->payloadtype = 34; //32; + + outBuff += RTP_HEADER_LEN; + + memcpy(outBuff, inBuff, inBuffLen); + +// AVIOContext *c = avio_alloc_context((unsigned char*)outBuff, l, 1, NULL, NULL, NULL, NULL); +// +// vOutputFormatContext->pb = c; +// vOutputFormatContext->flags = AVFMT_NOFILE; +// +// AVPacket pkt; +// av_init_packet(&pkt); +// pkt.data = (unsigned char*)inBuff; +// pkt.size = inBuffLen; +// +// int ret = av_write_frame(vOutputFormatContext,&pkt); +// +// av_free_packet(&pkt); +// av_free(c); + + return l; +} + +int OutputProcessor::packageVideoAVF(AVPacket* pkt) { + int ret = av_write_frame(vOutputFormatContext, pkt); + + return ret; +} + +int OutputProcessor::packageAudioRTP(unsigned char* inBuff, int inBuffLen, + unsigned char* outBuff) { + + if (audioPackager == 0) { + printf("No se ha inicializado el codec de output audio RTP"); + return -1; + } + + AVIOContext *c = avio_alloc_context((unsigned char*) outBuff, 2000, 1, NULL, + NULL, NULL, NULL); + + aOutputFormatContext->pb = c; + aOutputFormatContext->flags = AVFMT_NOFILE; + + AVPacket pkt; + av_init_packet(&pkt); + pkt.data = (unsigned char*) inBuff; + pkt.size = inBuffLen; + + int ret = av_write_frame(aOutputFormatContext, &pkt); + + av_free_packet(&pkt); + av_free(c); + + return ret; +} + +int OutputProcessor::encodeAudio(unsigned char* inBuff, int nSamples, + unsigned char* outBuff) { + + if (audioCoder == 0) { + printf("No se han inicializado los parámetros del audioCoder"); + return -1; + } + + //Puede fallar. Revisar samples. Cogido de libavcodec/utils.c del paso de avcodec_encode_audio a avcodec_encode_audio2 + //avcodec_encode_audio(aCoderContext, (unsigned char*)outBuff, nSamples*2, (short*)inBuff); + + AVPacket pkt; + AVFrame frame0; + AVFrame *frame; + int ret, samples_size, got_packet; + + av_init_packet(&pkt); + pkt.data = (unsigned char*) inBuff; + pkt.size = nSamples * 2; + + frame = &frame0; + avcodec_get_frame_defaults(frame); + + frame->nb_samples = nSamples; + + samples_size = av_samples_get_buffer_size(NULL, aCoderContext->channels, + frame->nb_samples, aCoderContext->sample_fmt, 1); + + if ((ret = avcodec_fill_audio_frame(frame, aCoderContext->channels, + aCoderContext->sample_fmt, (const uint8_t *) inBuff, samples_size, + 1))) + return ret; + + frame->pts = AV_NOPTS_VALUE; + //aCoderContext->internal->sample_count += frame->nb_samples; + + got_packet = 0; + + ret = avcodec_encode_audio2(aCoderContext, &pkt, frame, &got_packet); + + if (!ret && got_packet && aCoderContext->coded_frame) { + aCoderContext->coded_frame->pts = pkt.pts; + aCoderContext->coded_frame->key_frame = !!(pkt.flags & AV_PKT_FLAG_KEY); + } + //ff_packet_free_side_data(&pkt); + + if (frame && frame->extended_data != frame->data) + av_freep(&frame->extended_data); + + return ret; + +} + +int OutputProcessor::encodeVideo(unsigned char* inBuff, int inBuffLen, + unsigned char* outBuff, int outBuffLen) { + + if (videoCoder == 0) { + printf("No se han inicializado los parámetros del videoCoder"); + return -1; + } + + int size = vCoderContext->width * vCoderContext->height; + + cPicture->pts = AV_NOPTS_VALUE; + cPicture->data[0] = (unsigned char*) inBuff; + cPicture->data[1] = (unsigned char*) inBuff + size; + cPicture->data[2] = (unsigned char*) inBuff + size + size / 4; + cPicture->linesize[0] = vCoderContext->width; + cPicture->linesize[1] = vCoderContext->width / 2; + cPicture->linesize[2] = vCoderContext->width / 2; + + AVPacket pkt; + int ret = 0; + int got_packet = 0; + + if (outBuffLen < FF_MIN_BUFFER_SIZE) { + printf("buffer smaller than minimum size"); + return -1; + } + + av_init_packet(&pkt); + pkt.data = (unsigned char*) outBuff; + pkt.size = outBuffLen; + + ret = avcodec_encode_video2(vCoderContext, &pkt, cPicture, &got_packet); + + if (!ret && got_packet && vCoderContext->coded_frame) { + vCoderContext->coded_frame->pts = pkt.pts; + vCoderContext->coded_frame->key_frame = !!(pkt.flags & AV_PKT_FLAG_KEY); + } + + /* free any side data since we cannot return it */ + if (pkt.side_data_elems > 0) { + int i; + for (i = 0; i < pkt.side_data_elems; i++) + av_free(pkt.side_data[i].data); + av_freep(&pkt.side_data); + pkt.side_data_elems = 0; + } + + return ret ? ret : pkt.size; + +} +} /* namespace erizo */ diff --git a/src/erizo/media/MediaProcessor.h b/src/erizo/media/MediaProcessor.h index 1f49afc5c5..1970e11d25 100644 --- a/src/erizo/media/MediaProcessor.h +++ b/src/erizo/media/MediaProcessor.h @@ -4,16 +4,19 @@ #include #include #include -#include "utils/RtpUtils.h" - +#include +#include "utils/RtpUtils.h" +#include "../MediaDefinitions.h" extern "C" { - #include - #include +#include +#include } +namespace erizo { + struct audioCodecInfo { enum CodecID codec; int bitRate; @@ -31,103 +34,187 @@ struct videoCodecInfo { struct RTPInfo { enum CodecID codec; - int seqNum; - int ssrc; + unsigned int ssrc; + unsigned int PT; +}; + + +enum ProcessorType{ + RTP_ONLY, AVF }; -typedef struct -{ - uint32_t cc:4; - uint32_t extension:1; - uint32_t padding:1; - uint32_t version:2; - uint32_t payloadtype:7; - uint32_t marker:1; - uint32_t seqnum:16; +struct MediaInfo { + std::string url; + bool hasVideo; + bool hasAudio; + ProcessorType proccessorType; + RTPInfo rtpVideoInfo; + RTPInfo rtpAudioInfo; + videoCodecInfo videoCodec; + audioCodecInfo audioCodec; + +}; + +typedef struct { + uint32_t cc :4; + uint32_t extension :1; + uint32_t padding :1; + uint32_t version :2; + uint32_t payloadtype :7; + uint32_t marker :1; + uint32_t seqnum :16; uint32_t timestamp; uint32_t ssrc; -}rtpHeader; +} rtpHeader; + +typedef struct { + uint32_t partId :4; + uint32_t S :1; + uint32_t N :1; + uint32_t R :1; + uint32_t X :1; +} vp8RtpHeader; + +#define RTP_HEADER_LEN 12 + +#define UNPACKAGED_BUFFER_SIZE 50000 +//class MediaProcessor{ +// MediaProcessor(); +// virtual ~Mediaprocessor(); +//private: +// InputProcessor* input; +// OutputProcessor* output; +//}; + +class RawDataReceiver { +public: + virtual void receiveRawData(unsigned char*data, int len) = 0; + virtual ~RawDataReceiver() { + } + ; -typedef struct -{ - uint32_t partId:4; - uint32_t S:1; - uint32_t N:1; - uint32_t R:1; - uint32_t X:1; -}vp8RtpHeader; +}; +class InputProcessor: MediaReceiver { +public: + InputProcessor(); + virtual ~InputProcessor(); -#define RTP_HEADER_LEN 12; + int init(const MediaInfo& info, RawDataReceiver* receiver); -class MediaProcessor { -public: - MediaProcessor(); - virtual ~MediaProcessor(); - - bool initAudioCoder(const audioCodecInfo *audioCodec); - bool initAudioDecoder(const audioCodecInfo *audioCodec); - bool initVideoCoder(const videoCodecInfo *videoCodec); - bool initVideoDecoder(const videoCodecInfo *videoCodec); - - bool initAudioPackagerRTP(const RTPInfo *audioRTP); - bool initAudioUnpackagerRTP(const RTPInfo *audioRTP); - bool initVideoPackagerRTP(const RTPInfo *videoRTP); - bool initVideoUnpackagerRTP(const RTPInfo *videoRTP); - - int encodeAudio(char *inBuff, int nSamples, char *outBuff); - int decodeAudio(char *inBuff, int inBuffLen, char *outBuff); - int encodeVideo(char *inBuff, int inBuffLen, char *outBuff, int outBuffLen); - int decodeVideo(char *inBuff, int inBuffLen, char *outBuff, int outBuffLen, int *gotFrame); - - int packageAudioRTP(char *inBuff, int inBuffLen, char *outBuff); - int unpackageAudioRTP(char *inBuff, int inBuffLen, char *outBuff); - int packageVideoRTP(char *inBuff, int inBuffLen, char *outBuff); - int unpackageVideoRTP(char *inBuff, int inBuffLen, char *outBuff, int *gotFrame); - - //readFromFile - //writeTofile - //Encapsular - //Desencapsular + int receiveAudioData(char* buf, int len); + int receiveVideoData(char* buf, int len); private: - int audioCoder; + int audioDecoder; - int videoCoder; int videoDecoder; - int audioPackager; + MediaInfo mediaInfo; + int audioUnpackager; - int videoPackager; int videoUnpackager; - AVCodec *aCoder; - AVCodecContext *aCoderContext; - AVCodec *aDecoder; - AVCodecContext *aDecoderContext; + int gotUnpackagedFrame_; + int upackagedSize_; - AVCodec *vCoder; - AVCodecContext *vCoderContext; - AVFrame *cPicture; - AVCodec *vDecoder; - AVCodecContext *vDecoderContext; - AVFrame *dPicture; + unsigned char* decodedBuffer_; + unsigned char* unpackagedBuffer_; - AVFormatContext *aInputFormatContext; - AVInputFormat *aInputFormat; - AVFormatContext *aOutputFormatContext; - AVOutputFormat *aOutputFormat; + AVCodec* aDecoder; + AVCodecContext* aDecoderContext; - RTPInfo *vRTPInfo; + AVCodec* vDecoder; + AVCodecContext* vDecoderContext; + AVFrame* dPicture; - AVFormatContext *vInputFormatContext; - AVInputFormat *vInputFormat; - AVFormatContext *vOutputFormatContext; - AVOutputFormat *vOutputFormat; + AVFormatContext* aInputFormatContext; + AVInputFormat* aInputFormat; + + RTPInfo* vRTPInfo; + + AVFormatContext* vInputFormatContext; + AVInputFormat* vInputFormat; + + RawDataReceiver* rawReceiver_; erizo::RtpParser pars; + bool initAudioDecoder(); + bool initVideoDecoder(); + + bool initAudioUnpackagerRTP(); + bool initVideoUnpackager(); + + int decodeAudio(unsigned char* inBuff, int inBuffLen, + unsigned char* outBuff); + int decodeVideo(unsigned char* inBuff, int inBuffLen, + unsigned char* outBuff, int outBuffLen, int* gotFrame); + + int unpackageAudioRTP(unsigned char* inBuff, int inBuffLen, + unsigned char* outBuff); + int unpackageVideoRTP(unsigned char* inBuff, int inBuffLen, + unsigned char* outBuff, int* gotFrame); + +}; +class OutputProcessor: public RawDataReceiver { +public: + + OutputProcessor(); + virtual ~OutputProcessor(); + int init(const MediaInfo &info); + + void receiveRawData(unsigned char*data, int len); + +private: + + int audioCoder; + int videoCoder; + + int audioPackager; + int videoPackager; + + unsigned char* encodedBuffer_; + unsigned char* packagedBuffer_; + + MediaInfo mediaInfo; + + AVCodec* aCoder; + AVCodecContext* aCoderContext; + + AVCodec* vCoder; + AVCodecContext* vCoderContext; + AVFrame* cPicture; + + AVFormatContext* aOutputFormatContext; + AVOutputFormat* aOutputFormat; + + RTPInfo* vRTPInfo; + + AVFormatContext* vOutputFormatContext; + AVOutputFormat* vOutputFormat; + + MediaReceiver* Receiver; + + RtpParser pars; + + bool initAudioCoder(const audioCodecInfo& audioCodec); + bool initVideoCoder(const videoCodecInfo& videoCodec); + + bool initAudioPackagerRTP(const RTPInfo& audioRTP); + bool initVideoPackagerRTP(const RTPInfo& videoRTP); + + int encodeAudio(unsigned char* inBuff, int nSamples, + unsigned char* outBuff); + int encodeVideo(unsigned char* inBuff, int inBuffLen, + unsigned char* outBuff, int outBuffLen); + int packageAudioRTP(unsigned char* inBuff, int inBuffLen, + unsigned char* outBuff); + int packageVideoRTP(unsigned char* inBuff, int inBuffLen, + unsigned char* outBuff); + int packageVideoAVF(AVPacket* pkt); }; +} /* namespace erizo */ #endif /* MEDIAPROCESSOR_H_ */ diff --git a/src/examples/Test.cpp b/src/examples/Test.cpp index a5113e6a18..dd2f790a64 100644 --- a/src/examples/Test.cpp +++ b/src/examples/Test.cpp @@ -8,49 +8,50 @@ using boost::asio::ip::udp; -using namespace erizo; - +namespace erizo { Test::Test() { - - mp = new MediaProcessor(); - -// audioCodecInfo *i = new audioCodecInfo; -// i->codec = CODEC_ID_AMR_NB; -// i->bitRate = 300000; -// i->sampleRate = 44100; -// mp->initAudioDecoder(i); - + ip = new InputProcessor(); + MediaInfo m; + ip->init(m, this); +// mp = new MediaProcessor(); +// +//// audioCodecInfo *i = new audioCodecInfo; +//// i->codec = CODEC_ID_AMR_NB; +//// i->bitRate = 300000; +//// i->sampleRate = 44100; +//// mp->initAudioDecoder(i); +// +//// RTPInfo *r = new RTPInfo; +//// r->codec = CODEC_ID_MP3; +//// mp->initAudioUnpackagerRTP(r); +// +// videoCodecInfo *v = new videoCodecInfo; +// v->codec = CODEC_ID_VP8; +//// v->codec = CODEC_ID_MPEG4; +// //v->width = 706; +// //v->height = 396; +// v->width = 400; +// v->height = 300; +// +// mp->initVideoDecoder(v); +// +// videoCodecInfo *c = new videoCodecInfo; +// //c->codec = CODEC_ID_MPEG2VIDEO; +// c->codec = CODEC_ID_MPEG2VIDEO; +// c->width = v->width; +// c->height = v->height; +// c->frameRate = 24; +// c->bitRate = 1024; +// c->maxInter = 0; +// +// mp->initVideoCoder(c); +// // RTPInfo *r = new RTPInfo; -// r->codec = CODEC_ID_MP3; -// mp->initAudioUnpackagerRTP(r); - - videoCodecInfo *v = new videoCodecInfo; - v->codec = CODEC_ID_VP8; -// v->codec = CODEC_ID_MPEG4; - //v->width = 706; - //v->height = 396; - v->width = 400; - v->height = 300; - - mp->initVideoDecoder(v); - - videoCodecInfo *c = new videoCodecInfo; - //c->codec = CODEC_ID_MPEG2VIDEO; - c->codec = CODEC_ID_MPEG2VIDEO; - c->width = v->width; - c->height = v->height; - c->frameRate = 24; - c->bitRate = 1024; - c->maxInter = 0; - - mp->initVideoCoder(c); - - RTPInfo *r = new RTPInfo; - //r->codec = CODEC_ID_MPEG2VIDEO; -// r->codec = CODEC_ID_MPEG4; - mp->initVideoPackagerRTP(r); - mp->initVideoUnpackagerRTP(r); - +// //r->codec = CODEC_ID_MPEG2VIDEO; +//// r->codec = CODEC_ID_MPEG4; +// mp->initVideoPackagerRTP(r); +// mp->initVideoUnpackagerRTP(r); +// ioservice_ = new boost::asio::io_service; resolver_ = new udp::resolver(*ioservice_); socket_ = new udp::socket(*ioservice_, udp::endpoint(udp::v4(), 40000)); @@ -65,90 +66,97 @@ Test::~Test() { //sock->disconnect(); } -void Test::rec() { - - int outBuff2Size = 706 * 396 * 3 / 2; - - void *buff = malloc(2000); - char * outBuff = (char*) malloc(50000); - memset(outBuff, 0, 50000); - char * outBuff2 = (char*) malloc(outBuff2Size); +void Test::receiveRawData(unsigned char*data, int len) { + printf("decoded data %d\n", len); + return; +} - int gotFrame = 0; - int size = 0; - int gotDecFrame = 0; +void Test::rec() { - std::string s; - unsigned short u; +// int outBuff2Size = 706 * 396 * 3 / 2; +// + char* buff = (char*)malloc(2000); +// char * outBuff = (char*) malloc(50000); +// memset(outBuff, 0, 50000); +// char * outBuff2 = (char*) malloc(outBuff2Size); +// +// int gotFrame = 0; +// int size = 0; +// int gotDecFrame = 0; +// +// std::string s; +// unsigned short u; int a; while (true) { - +// memset(buff, 0, 2000); - +// a = socket_->receive(boost::asio::buffer(buff, 2000)); - printf("********* RECEPCIÓN *********\n"); - printf("Bytes = %d\n", a); - - int z, b; - z = mp->unpackageVideoRTP((char*) buff, a, outBuff, &gotFrame); - -// RTPPayloadVP8* parsed = pars.parseVP8((unsigned char*)outBuff, z); -// b = parsed->dataLength; -// int c = parsed.dataLength; - -// printf("Bytes desem = %d prevp8 %d\n", b, z ); - - size += z; - outBuff += z; - - if (gotFrame) { - - outBuff -= size; - - printf("Tengo un frame desempaquetado!! Size = %d\n", size); - - int c; - - c = mp->decodeVideo(outBuff, size, outBuff2, outBuff2Size, - &gotDecFrame); - printf("Bytes dec = %d\n", c); - - size = 0; - memset(outBuff, 0, 50000); - gotFrame = 0; - - if (gotDecFrame) { - printf("Tengo un frame decodificado!!"); - gotDecFrame = 0; - send(outBuff2, c); - } - } + ip->receiveVideoData(buff, a); +// printf("********* RECEPCIÓN *********\n"); +// printf("Bytes = %d\n", a); +// +// int z, b; +// z = mp->unpackageVideoRTP((char*) buff, a, outBuff, &gotFrame); +// +//// RTPPayloadVP8* parsed = pars.parseVP8((unsigned char*)outBuff, z); +//// b = parsed->dataLength; +//// int c = parsed.dataLength; +// +//// printf("Bytes desem = %d prevp8 %d\n", b, z ); +// +// size += z; +// outBuff += z; +// +// if (gotFrame) { +// +// outBuff -= size; +// +// printf("Tengo un frame desempaquetado!! Size = %d\n", size); +// +// int c; +// +// c = mp->decodeVideo(outBuff, size, outBuff2, outBuff2Size, +// &gotDecFrame); +// printf("Bytes dec = %d\n", c); +// +// size = 0; +// memset(outBuff, 0, 50000); +// gotFrame = 0; +// +// if (gotDecFrame) { +// printf("Tengo un frame decodificado!!"); +// gotDecFrame = 0; +// send(outBuff2, c); +// } } +// } } void Test::send(char *buff, int buffSize) { - printf("\n********* ENVÍO *********"); - - char *buffSend = (char*) malloc(buffSize); - char *buffSend2 = (char*) malloc(buffSize); - - int a = mp->encodeVideo(buff, buffSize, buffSend, buffSize); - - printf("\nBytes codificados = %d", a); - - int b = mp->packageVideoRTP(buffSend, a, buffSend2); - - printf("\nBytes empaquetados = %d", b); - - udp::resolver::iterator iterator = resolver_->resolve(*query_); - -// socket_->send_to(buffSend2, b, "toronado.dit.upm.es", 5005); - socket_->send_to(boost::asio::buffer(buffSend2, b), *iterator); - free(buffSend); - free(buffSend2); - - printf("\n*************************"); +// printf("\n********* ENVÍO *********"); +// +// char *buffSend = (char*) malloc(buffSize); +// char *buffSend2 = (char*) malloc(buffSize); +// +// int a = mp->encodeVideo(buff, buffSize, buffSend, buffSize); +// +// printf("\nBytes codificados = %d", a); +// +// int b = mp->packageVideoRTP(buffSend, a, buffSend2); +// +// printf("\nBytes empaquetados = %d", b); +// +//// udp::resolver::iterator iterator = resolver_->resolve(*query_); +// +//// socket_->send_to(buffSend2, b, "toronado.dit.upm.es", 5005); +//// socket_->send_to(boost::asio::buffer(buffSend2, b), *iterator); +// free(buffSend); +// free(buffSend2); +// +// printf("\n*************************"); } +} diff --git a/src/examples/Test.h b/src/examples/Test.h index 511c450900..b715a70e44 100644 --- a/src/examples/Test.h +++ b/src/examples/Test.h @@ -4,11 +4,12 @@ #ifndef TEST_H_ #define TEST_H_ - -class Test { +namespace erizo{ +class Test: public RawDataReceiver { public: Test(); virtual ~Test(); + void receiveRawData(unsigned char*data, int len); void rec(); void send(char *buff, int buffSize); @@ -19,9 +20,10 @@ class Test { boost::asio::ip::udp::resolver::query* query_; boost::asio::io_service* ioservice_; - MediaProcessor *mp; + InputProcessor* ip; erizo::RtpParser pars; }; +} #endif /* TEST_H_ */ From 8f9544b1f45671da3255eba321d71b8374916760 Mon Sep 17 00:00:00 2001 From: Pedro Rodriguez Date: Thu, 12 Jul 2012 18:01:34 +0200 Subject: [PATCH 13/29] MediaProcessor Refactoring --- src/erizo/media/MediaProcessor.cpp | 91 ++++++++++++++---------------- src/erizo/media/MediaProcessor.h | 22 ++++---- 2 files changed, 51 insertions(+), 62 deletions(-) diff --git a/src/erizo/media/MediaProcessor.cpp b/src/erizo/media/MediaProcessor.cpp index 1224ba06b0..3c26b485c9 100644 --- a/src/erizo/media/MediaProcessor.cpp +++ b/src/erizo/media/MediaProcessor.cpp @@ -64,7 +64,7 @@ int InputProcessor::receiveAudioData(char* buf, int len) { int InputProcessor::receiveVideoData(char* buf, int len) { if (videoUnpackager && videoDecoder) { - int ret = unpackageVideoRTP(reinterpret_cast(buf), len, + int ret = unpackageVideo(reinterpret_cast(buf), len, unpackagedBuffer_, &gotUnpackagedFrame_); // int x = mp->unpackageVideoRTP(buf, len, unpackagedBuffer_, &gotFrame_); upackagedSize_ += ret; @@ -93,9 +93,6 @@ int InputProcessor::receiveVideoData(char* buf, int len) { memset(unpackagedBuffer_, 0, 50000); unsigned char *buffSend = (unsigned char*) malloc(c); memcpy(buffSend, decodedBuffer_, c); - -// int a = this->encodeVideo(decodedBuffer_, c, buffSend, -// buffSize); rawReceiver_->receiveRawData(buffSend, c); } @@ -167,7 +164,7 @@ bool InputProcessor::initVideoDecoder() { return true; } -bool InputProcessor::initAudioUnpackagerRTP() { +bool InputProcessor::initAudioUnpackager() { if (mediaInfo.proccessorType != RTP_ONLY) { aInputFormatContext = avformat_alloc_context(); @@ -190,7 +187,11 @@ bool InputProcessor::initAudioUnpackagerRTP() { } bool InputProcessor::initVideoUnpackager() { + if (mediaInfo.proccessorType == RTP_ONLY) { + printf("Unpackagin from RTP\n"); + } else { + } videoUnpackager = 1; return true; @@ -378,7 +379,7 @@ int InputProcessor::decodeVideo(unsigned char* inBuff, int inBuffLen, return outSize * 3 / 2; } -int InputProcessor::unpackageAudioRTP(unsigned char* inBuff, int inBuffLen, +int InputProcessor::unpackageAudio(unsigned char* inBuff, int inBuffLen, unsigned char* outBuff) { /* @@ -426,7 +427,7 @@ int InputProcessor::unpackageAudioRTP(unsigned char* inBuff, int inBuffLen, return l; } -int InputProcessor::unpackageVideoRTP(unsigned char* inBuff, int inBuffLen, +int InputProcessor::unpackageVideo(unsigned char* inBuff, int inBuffLen, unsigned char* outBuff, int *gotFrame) { /* if (videoUnpackager == 0) { @@ -535,20 +536,16 @@ int OutputProcessor::init(const MediaInfo &info) { encodedBuffer_ = (unsigned char*) malloc(UNPACKAGED_BUFFER_SIZE); packagedBuffer_ = (unsigned char*) malloc(UNPACKAGED_BUFFER_SIZE); - videoCodecInfo c; - c.codec = CODEC_ID_H264; - c.width = 640; - c.height = 480; - c.frameRate = 24; - c.bitRate = 1024; - c.maxInter = 0; - - this->initVideoCoder(c); - - RTPInfo r; - r.codec = CODEC_ID_H263P; +// videoCodecInfo c; +// c.codec = CODEC_ID_H264; +// c.width = 640; +// c.height = 480; +// c.frameRate = 24; +// c.bitRate = 1024; +// c.maxInter = 0; - this->initVideoPackagerRTP(r); + this->initVideoCoder(); + this->initVideoPackager(); return 0; } @@ -558,12 +555,12 @@ void OutputProcessor::receiveRawData(unsigned char* data, int len) { printf("\nBytes codificados = %d", a); - int b = this->packageVideoRTP(encodedBuffer_, a, packagedBuffer_); + int b = this->packageVideo(encodedBuffer_, a, packagedBuffer_); printf("\nBytes empaquetados = %d", b); } -bool OutputProcessor::initAudioCoder(const audioCodecInfo& audioCodec) { +bool OutputProcessor::initAudioCoder() { - aCoder = avcodec_find_encoder(audioCodec.codec); + aCoder = avcodec_find_encoder(mediaInfo.audioCodec.codec); if (!aCoder) { printf("Encoder de audio no encontrado"); return false; @@ -576,8 +573,8 @@ bool OutputProcessor::initAudioCoder(const audioCodecInfo& audioCodec) { } aCoderContext->sample_fmt = AV_SAMPLE_FMT_S16; - aCoderContext->bit_rate = audioCodec.bitRate; - aCoderContext->sample_rate = audioCodec.sampleRate; + aCoderContext->bit_rate = mediaInfo.audioCodec.bitRate; + aCoderContext->sample_rate = mediaInfo.audioCodec.sampleRate; aCoderContext->channels = 1; if (avcodec_open2(aCoderContext, aCoder, NULL) < 0) { @@ -589,9 +586,9 @@ bool OutputProcessor::initAudioCoder(const audioCodecInfo& audioCodec) { return true; } -bool OutputProcessor::initVideoCoder(const videoCodecInfo& videoCodec) { +bool OutputProcessor::initVideoCoder() { - vCoder = avcodec_find_encoder(videoCodec.codec); + vCoder = avcodec_find_encoder(mediaInfo.videoCodec.codec); if (!vCoder) { printf("Encoder de vídeo no encontrado"); return false; @@ -603,27 +600,27 @@ bool OutputProcessor::initVideoCoder(const videoCodecInfo& videoCodec) { return false; } - vCoderContext->bit_rate = videoCodec.bitRate; - vCoderContext->bit_rate_tolerance = 1.1 * videoCodec.bitRate - / videoCodec.frameRate; - vCoderContext->rc_max_rate = videoCodec.bitRate * 2; + vCoderContext->bit_rate = mediaInfo.videoCodec.bitRate; + vCoderContext->bit_rate_tolerance = 1.1 * mediaInfo.videoCodec.bitRate + / mediaInfo.videoCodec.frameRate; + vCoderContext->rc_max_rate = mediaInfo.videoCodec.bitRate * 2; - if (videoCodec.frameRate >= 1.0) { - vCoderContext->rc_buffer_size = videoCodec.bitRate; // 1 second stored, in bps + if (mediaInfo.videoCodec.frameRate >= 1.0) { + vCoderContext->rc_buffer_size = mediaInfo.videoCodec.bitRate; // 1 second stored, in bps } else { - vCoderContext->rc_buffer_size = 1.1 * videoCodec.bitRate - / videoCodec.frameRate; + vCoderContext->rc_buffer_size = 1.1 * mediaInfo.videoCodec.bitRate + / mediaInfo.videoCodec.frameRate; } vCoderContext->rc_buffer_aggressivity = 1.0; - vCoderContext->gop_size = videoCodec.maxInter; + vCoderContext->gop_size = mediaInfo.videoCodec.maxInter; vCoderContext->max_b_frames = 0; vCoderContext->me_method = ME_EPZS; - vCoderContext->width = videoCodec.width; - vCoderContext->height = videoCodec.height; + vCoderContext->width = mediaInfo.videoCodec.width; + vCoderContext->height = mediaInfo.videoCodec.height; vCoderContext->pix_fmt = PIX_FMT_YUV420P; - vCoderContext->time_base = (AVRational) {1000, 1000*videoCodec.frameRate}; + vCoderContext->time_base = (AVRational) {1000, 1000*mediaInfo.videoCodec.frameRate}; if (avcodec_open2(vCoderContext, vCoder, NULL) < 0) { printf("Error al abrir el decoder de vídeo"); @@ -640,7 +637,7 @@ bool OutputProcessor::initVideoCoder(const videoCodecInfo& videoCodec) { return true; } -bool OutputProcessor::initAudioPackagerRTP(const RTPInfo& audioRTP) { +bool OutputProcessor::initAudioPackager() { aOutputFormatContext = avformat_alloc_context(); if (!aOutputFormatContext) { @@ -655,13 +652,13 @@ bool OutputProcessor::initAudioPackagerRTP(const RTPInfo& audioRTP) { } aOutputFormatContext->oformat = aOutputFormat; - aOutputFormat->audio_codec = audioRTP.codec; + aOutputFormat->audio_codec = mediaInfo.audioCodec.codec; audioPackager = 1; return true; } -bool OutputProcessor::initVideoPackagerRTP(const RTPInfo& videoRTP) { +bool OutputProcessor::initVideoPackager() { // // vOutputFormatContext = avformat_alloc_context(); // if (!vOutputFormatContext){ @@ -686,7 +683,7 @@ bool OutputProcessor::initVideoPackagerRTP(const RTPInfo& videoRTP) { return true; } -int OutputProcessor::packageVideoRTP(unsigned char* inBuff, int inBuffLen, +int OutputProcessor::packageVideo(unsigned char* inBuff, int inBuffLen, unsigned char* outBuff) { if (videoPackager == 0) { @@ -734,13 +731,7 @@ int OutputProcessor::packageVideoRTP(unsigned char* inBuff, int inBuffLen, return l; } -int OutputProcessor::packageVideoAVF(AVPacket* pkt) { - int ret = av_write_frame(vOutputFormatContext, pkt); - - return ret; -} - -int OutputProcessor::packageAudioRTP(unsigned char* inBuff, int inBuffLen, +int OutputProcessor::packageAudio(unsigned char* inBuff, int inBuffLen, unsigned char* outBuff) { if (audioPackager == 0) { diff --git a/src/erizo/media/MediaProcessor.h b/src/erizo/media/MediaProcessor.h index 1970e11d25..21a0952caa 100644 --- a/src/erizo/media/MediaProcessor.h +++ b/src/erizo/media/MediaProcessor.h @@ -38,8 +38,7 @@ struct RTPInfo { unsigned int PT; }; - -enum ProcessorType{ +enum ProcessorType { RTP_ONLY, AVF }; @@ -143,7 +142,7 @@ class InputProcessor: MediaReceiver { bool initAudioDecoder(); bool initVideoDecoder(); - bool initAudioUnpackagerRTP(); + bool initAudioUnpackager(); bool initVideoUnpackager(); int decodeAudio(unsigned char* inBuff, int inBuffLen, @@ -151,9 +150,9 @@ class InputProcessor: MediaReceiver { int decodeVideo(unsigned char* inBuff, int inBuffLen, unsigned char* outBuff, int outBuffLen, int* gotFrame); - int unpackageAudioRTP(unsigned char* inBuff, int inBuffLen, + int unpackageAudio(unsigned char* inBuff, int inBuffLen, unsigned char* outBuff); - int unpackageVideoRTP(unsigned char* inBuff, int inBuffLen, + int unpackageVideo(unsigned char* inBuff, int inBuffLen, unsigned char* outBuff, int* gotFrame); }; @@ -198,22 +197,21 @@ class OutputProcessor: public RawDataReceiver { RtpParser pars; - bool initAudioCoder(const audioCodecInfo& audioCodec); - bool initVideoCoder(const videoCodecInfo& videoCodec); + bool initAudioCoder(); + bool initVideoCoder(); - bool initAudioPackagerRTP(const RTPInfo& audioRTP); - bool initVideoPackagerRTP(const RTPInfo& videoRTP); + bool initAudioPackager(); + bool initVideoPackager(); int encodeAudio(unsigned char* inBuff, int nSamples, unsigned char* outBuff); int encodeVideo(unsigned char* inBuff, int inBuffLen, unsigned char* outBuff, int outBuffLen); - int packageAudioRTP(unsigned char* inBuff, int inBuffLen, + int packageAudio(unsigned char* inBuff, int inBuffLen, unsigned char* outBuff); - int packageVideoRTP(unsigned char* inBuff, int inBuffLen, + int packageVideo(unsigned char* inBuff, int inBuffLen, unsigned char* outBuff); - int packageVideoAVF(AVPacket* pkt); }; } /* namespace erizo */ From 015409612c7a869da92137e079b35503127e4872 Mon Sep 17 00:00:00 2001 From: Pedro Rodriguez Date: Thu, 12 Jul 2012 19:17:31 +0200 Subject: [PATCH 14/29] Fixed decoding crashes --- src/erizo/OneToManyProcessor.cpp | 8 +++++++- src/erizo/media/MediaProcessor.cpp | 27 ++++++++++++++------------- src/erizo/media/MediaProcessor.h | 1 + 3 files changed, 22 insertions(+), 14 deletions(-) diff --git a/src/erizo/OneToManyProcessor.cpp b/src/erizo/OneToManyProcessor.cpp index 5990933d12..211dea3040 100644 --- a/src/erizo/OneToManyProcessor.cpp +++ b/src/erizo/OneToManyProcessor.cpp @@ -16,6 +16,11 @@ OneToManyProcessor::OneToManyProcessor() : sentPackets_ = 0; ip = new InputProcessor(); MediaInfo m; + printf("initiating mediaInfo\n"); + m.videoCodec.bitRate =2000000; + printf("m.videoCodec.bitrate %d\n\n", m.videoCodec.bitRate); + m.videoCodec.height = 480; + m.videoCodec.width = 640; ip->init(m, this); // Media processing @@ -98,7 +103,8 @@ int OneToManyProcessor::receiveVideoData(char* buf, int len) { } void OneToManyProcessor::receiveRawData(unsigned char* buf, int len){ - printf("Received %d", len); + printf("Received %d\n", len); +// free(buf); } void OneToManyProcessor::setPublisher(WebRtcConnection* webRtcConn) { diff --git a/src/erizo/media/MediaProcessor.cpp b/src/erizo/media/MediaProcessor.cpp index 3c26b485c9..d29432d36d 100644 --- a/src/erizo/media/MediaProcessor.cpp +++ b/src/erizo/media/MediaProcessor.cpp @@ -66,7 +66,6 @@ int InputProcessor::receiveVideoData(char* buf, int len) { if (videoUnpackager && videoDecoder) { int ret = unpackageVideo(reinterpret_cast(buf), len, unpackagedBuffer_, &gotUnpackagedFrame_); - // int x = mp->unpackageVideoRTP(buf, len, unpackagedBuffer_, &gotFrame_); upackagedSize_ += ret; unpackagedBuffer_ += ret; @@ -90,10 +89,12 @@ int InputProcessor::receiveVideoData(char* buf, int len) { if (gotDecodedFrame) { printf("Tengo un frame decodificado!!\n"); gotDecodedFrame = 0; + rawReceiver_->receiveRawData(decodedBuffer_, c); memset(unpackagedBuffer_, 0, 50000); - unsigned char *buffSend = (unsigned char*) malloc(c); - memcpy(buffSend, decodedBuffer_, c); - rawReceiver_->receiveRawData(buffSend, c); + +// unsigned char *buffSend = (unsigned char*) malloc(c); +// memcpy(buffSend, decodedBuffer_, c); + } } @@ -188,7 +189,7 @@ bool InputProcessor::initAudioUnpackager() { bool InputProcessor::initVideoUnpackager() { if (mediaInfo.proccessorType == RTP_ONLY) { - printf("Unpackagin from RTP\n"); + printf("Unpackaging from RTP\n"); } else { } @@ -444,14 +445,14 @@ int InputProcessor::unpackageVideo(unsigned char* inBuff, int inBuffLen, unsigned long time = ntohl(head->timestamp); printf("PT %d, ssrc %u, extension %d\n", head->payloadtype, ssrc, head->extension); -// if (ssrc != 55543/* && head->payloadtype!=101*/) { -// return -1; -// } -// if (head->payloadtype != 100) { -// printf("EEEEEEEEEEEEEEOOOOOOOOOOOOOOOOOOOOOOOO %d\n\n\n", -// head->payloadtype); -// return -1; -// } + if (ssrc != 55543/* && head->payloadtype!=101*/) { + return -1; + } + if (head->payloadtype != 100) { + printf("EEEEEEEEEEEEEEOOOOOOOOOOOOOOOOOOOOOOOO %d\n\n\n", + head->payloadtype); + return -1; + } int l = inBuffLen - RTP_HEADER_LEN; inBuff += RTP_HEADER_LEN; // vp8RtpHeader* vphead = (vp8RtpHeader*) inBuff; diff --git a/src/erizo/media/MediaProcessor.h b/src/erizo/media/MediaProcessor.h index 21a0952caa..e531a32964 100644 --- a/src/erizo/media/MediaProcessor.h +++ b/src/erizo/media/MediaProcessor.h @@ -120,6 +120,7 @@ class InputProcessor: MediaReceiver { unsigned char* decodedBuffer_; unsigned char* unpackagedBuffer_; + AVCodec* aDecoder; AVCodecContext* aDecoderContext; From d36d29a75e65130f2ff9a8beabf70597239b924a Mon Sep 17 00:00:00 2001 From: Pedro Rodriguez Date: Tue, 17 Jul 2012 13:20:19 +0200 Subject: [PATCH 15/29] Modifications to MediaProcessor --- src/erizo/OneToManyProcessor.cpp | 74 +++------ src/erizo/OneToManyProcessor.h | 1 + src/erizo/media/MediaProcessor.cpp | 256 +++++++++++++++-------------- 3 files changed, 158 insertions(+), 173 deletions(-) diff --git a/src/erizo/OneToManyProcessor.cpp b/src/erizo/OneToManyProcessor.cpp index 211dea3040..1d09117a42 100644 --- a/src/erizo/OneToManyProcessor.cpp +++ b/src/erizo/OneToManyProcessor.cpp @@ -16,47 +16,24 @@ OneToManyProcessor::OneToManyProcessor() : sentPackets_ = 0; ip = new InputProcessor(); MediaInfo m; - printf("initiating mediaInfo\n"); + m.proccessorType= RTP_ONLY; m.videoCodec.bitRate =2000000; printf("m.videoCodec.bitrate %d\n\n", m.videoCodec.bitRate); m.videoCodec.height = 480; m.videoCodec.width = 640; ip->init(m, this); - // Media processing - -// unpackagedBuffer_ = (char*) malloc(50000); -// memset(unpackagedBuffer_, 0, 50000); -// -// gotFrame_ = 0; -// size_ = 0; -// gotDecodedFrame_ = 0; -// -// mp = new MediaProcessor(); -// videoCodecInfo *v = new videoCodecInfo; -// v->codec = CODEC_ID_VP8; -// // v->codec = CODEC_ID_MPEG4; -// v->width = 640; -// v->height = 480; -// decodedBuffer_ = (char*) malloc(v->width * v->height * 3 / 2); -// memset(decodedBuffer_, 0, v->width * v->height * 3 / 2); -// mp->initVideoDecoder(v); -// -// videoCodecInfo *c = new videoCodecInfo; -// //c->codec = CODEC_ID_MPEG2VIDEO; -// c->codec = CODEC_ID_H263P; -// c->width = v->width; -// c->height = v->height; -// c->frameRate = 24; -// c->bitRate = 1024; -// c->maxInter = 0; -// -// mp->initVideoCoder(c); -// -// RTPInfo *r = new RTPInfo; -// r->codec = CODEC_ID_H263P; -// -// mp->initVideoPackagerRTP(r); -// mp->initVideoUnpackagerRTP(r); + + + MediaInfo om; + om.proccessorType = RTP_ONLY; + om.videoCodec.bitRate =2000000; + printf("m.videoCodec.bitrate %d\n\n", om.videoCodec.bitRate); + om.videoCodec.height = 480; + om.videoCodec.width = 640; + printf("Initiation outputprocessor\n"); + op = new OutputProcessor(); + op->init(om); + printf("OutputProcessor initiated successfully\n"); } @@ -87,18 +64,18 @@ int OneToManyProcessor::receiveVideoData(char* buf, int len) { ip->receiveVideoData(buf,len); -//// if (subscribers.empty() || len <= 0) -//// return 0; -//// if (sentPackets_ % 1000 == 0) { -//// publisher->sendFirPacket(); -//// } -//// std::map::iterator it; -//// for (it = subscribers.begin(); it != subscribers.end(); it++) { -//// memset(sendVideoBuffer_, 0, len); -//// memcpy(sendVideoBuffer_, buf, len); -//// (*it).second->receiveVideoData(sendVideoBuffer_, len); -//// } -//// sentPackets_++; +// if (subscribers.empty() || len <= 0) +// return 0; +// if (sentPackets_ % 1000 == 0) { +// publisher->sendFirPacket(); +// } +// std::map::iterator it; +// for (it = subscribers.begin(); it != subscribers.end(); it++) { +// memset(sendVideoBuffer_, 0, len); +// memcpy(sendVideoBuffer_, buf, len); +// (*it).second->receiveVideoData(sendVideoBuffer_, len); +// } +// sentPackets_++; // return 0; } @@ -114,7 +91,6 @@ void OneToManyProcessor::setPublisher(WebRtcConnection* webRtcConn) { void OneToManyProcessor::addSubscriber(WebRtcConnection* webRtcConn, int peerId) { this->subscribers[peerId] = webRtcConn; -// sendHead(webRtcConn); } diff --git a/src/erizo/OneToManyProcessor.h b/src/erizo/OneToManyProcessor.h index ad9004e77b..4ff41195bb 100644 --- a/src/erizo/OneToManyProcessor.h +++ b/src/erizo/OneToManyProcessor.h @@ -47,6 +47,7 @@ class OneToManyProcessor : public MediaReceiver, public RawDataReceiver { WebRtcConnection *publisher; // MediaProcessor *mp; InputProcessor* ip; + OutputProcessor* op; std::map subscribers; private: diff --git a/src/erizo/media/MediaProcessor.cpp b/src/erizo/media/MediaProcessor.cpp index d29432d36d..53d8a0dc23 100644 --- a/src/erizo/media/MediaProcessor.cpp +++ b/src/erizo/media/MediaProcessor.cpp @@ -24,7 +24,6 @@ InputProcessor::InputProcessor() { } InputProcessor::~InputProcessor() { - if (audioDecoder == 1) { avcodec_close(aDecoderContext); av_free(aDecoderContext); @@ -430,69 +429,72 @@ int InputProcessor::unpackageAudio(unsigned char* inBuff, int inBuffLen, int InputProcessor::unpackageVideo(unsigned char* inBuff, int inBuffLen, unsigned char* outBuff, int *gotFrame) { - /* - if (videoUnpackager == 0) { - printf("No se ha inicailizado el codec de input vídeo RTP"); - return -1; - } - */ - *gotFrame = 0; - - rtpHeader* head = (rtpHeader*) inBuff; - int sec = ntohs(head->seqnum); - int ssrc = ntohl(head->ssrc); - unsigned long time = ntohl(head->timestamp); - printf("PT %d, ssrc %u, extension %d\n", head->payloadtype, ssrc, - head->extension); - if (ssrc != 55543/* && head->payloadtype!=101*/) { + if (videoUnpackager == 0) { + printf("Unpackager not correctly initialized"); return -1; } - if (head->payloadtype != 100) { - printf("EEEEEEEEEEEEEEOOOOOOOOOOOOOOOOOOOOOOOO %d\n\n\n", - head->payloadtype); - return -1; - } - int l = inBuffLen - RTP_HEADER_LEN; - inBuff += RTP_HEADER_LEN; -// vp8RtpHeader* vphead = (vp8RtpHeader*) inBuff; -// printf("MIO X: %u , N:%u PartID %u\n", vphead->X, vphead->N, + *gotFrame = 0; + if (mediaInfo.proccessorType == RTP_ONLY) { + rtpHeader* head = (rtpHeader*) inBuff; + + int sec = ntohs(head->seqnum); + int ssrc = ntohl(head->ssrc); + unsigned long time = ntohl(head->timestamp); + printf("PT %d, ssrc %u, extension %d\n", head->payloadtype, ssrc, + head->extension); + if (ssrc != 55543 /*&& head->payloadtype!=101*/) { + return -1; + } + if (head->payloadtype != 100) { + printf("EEEEEEEEEEEEEEOOOOOOOOOOOOOOOOOOOOOOOO %d\n\n\n", + head->payloadtype); + return -1; + } + int l = inBuffLen - RTP_HEADER_LEN; + inBuff += RTP_HEADER_LEN; +// vp8RtpHeader* vphead = (vp8RtpHeader*) inBuff; +// printf("MIO X: %u , N:%u PartID %u\n", vphead->X, vphead->N, // vphead->partId); - erizo::RTPPayloadVP8* parsed = pars.parseVP8((unsigned char*) inBuff, l); - printf("l : %d, parsedDatalength %u\n", l, parsed->dataLength); -// l--; -// inBuff++; + erizo::RTPPayloadVP8* parsed = pars.parseVP8((unsigned char*) inBuff, + l); + printf("l : %d, parsedDatalength %u\n", l, parsed->dataLength); +// l--; +// inBuff++; // memcpy(outBuff, inBuff, parsed->dataLength); - memcpy(outBuff, parsed->data, parsed->dataLength); - if (head->marker) { - printf("Marker\n"); - *gotFrame = 1; - } + memcpy(outBuff, parsed->data, parsed->dataLength); + if (head->marker) { + printf("Marker\n"); + *gotFrame = 1; + } // return l; - return parsed->dataLength; -// -// if (avformat_find_stream_info(vInputFormatContext, NULL) < 0) { -// return -1; -// } -// -// AVPacket pkt; -// av_init_packet(&pkt); -// -// //aInputFormatContext->iformat->read_packet(aInputFormatContext, &pkt); -// -// int p = av_read_frame(vInputFormatContext, &pkt); -// printf("Leido frame %d\n", p); -// -// outBuff = (char*) pkt.data; -// -// int se = pkt.size; -// -// av_free_packet(&pkt); -// -// return se; + return parsed->dataLength; + } else { + + if (avformat_find_stream_info(vInputFormatContext, NULL) < 0) { + return -1; + } + + AVPacket pkt; + av_init_packet(&pkt); + + //aInputFormatContext->iformat->read_packet(aInputFormatContext, &pkt); + + int p = av_read_frame(vInputFormatContext, &pkt); + printf("Leido frame %d\n", p); + + outBuff = pkt.data; + + int se = pkt.size; + + av_free_packet(&pkt); + + return se; + + } } @@ -544,6 +546,7 @@ int OutputProcessor::init(const MediaInfo &info) { // c.frameRate = 24; // c.bitRate = 1024; // c.maxInter = 0; + this->mediaInfo.videoCodec.codec = CODEC_ID_H263P; this->initVideoCoder(); this->initVideoPackager(); @@ -559,6 +562,7 @@ void OutputProcessor::receiveRawData(unsigned char* data, int len) { int b = this->packageVideo(encodedBuffer_, a, packagedBuffer_); printf("\nBytes empaquetados = %d", b); } + bool OutputProcessor::initAudioCoder() { aCoder = avcodec_find_encoder(mediaInfo.audioCodec.codec); @@ -621,7 +625,8 @@ bool OutputProcessor::initVideoCoder() { vCoderContext->width = mediaInfo.videoCodec.width; vCoderContext->height = mediaInfo.videoCodec.height; vCoderContext->pix_fmt = PIX_FMT_YUV420P; - vCoderContext->time_base = (AVRational) {1000, 1000*mediaInfo.videoCodec.frameRate}; + vCoderContext->time_base = + (AVRational) {1000, 1000*mediaInfo.videoCodec.frameRate}; if (avcodec_open2(vCoderContext, vCoder, NULL) < 0) { printf("Error al abrir el decoder de vídeo"); @@ -660,78 +665,28 @@ bool OutputProcessor::initAudioPackager() { } bool OutputProcessor::initVideoPackager() { -// -// vOutputFormatContext = avformat_alloc_context(); -// if (!vOutputFormatContext){ -// printf("Memory Error al inicializar videoPackager"); -// return false; -// } -// -// vOutputFormat = av_guess_format("rtp",NULL,NULL); -// if (vOutputFormat == NULL){ -// printf("Could not guess format al inicializar videoPackager"); -// return false; -// } -// -// vOutputFormatContext->oformat=vOutputFormat; -// vOutputFormat->video_codec = videoRTP->codec; + if (mediaInfo.proccessorType == RTP_ONLY) { + printf("RTP ONLY OutputProcessor\n"); + } else { + vOutputFormatContext = avformat_alloc_context(); + if (!vOutputFormatContext) { + printf("videoPackager: Error creating avformat context \n"); + return false; + } -// vRTPInfo = (RTPInfo*) videoRTP; -// vRTPInfo->seqNum = 0; -// vRTPInfo->ssrc = 5; + vOutputFormat = av_guess_format(mediaInfo.url.c_str(), NULL, NULL); + if (vOutputFormat == NULL) { + printf("videoPackager: Could not guess format"); + return false; + } + vOutputFormatContext->oformat = vOutputFormat; + vOutputFormat->video_codec = mediaInfo.videoCodec.codec; + } videoPackager = 1; return true; } -int OutputProcessor::packageVideo(unsigned char* inBuff, int inBuffLen, - unsigned char* outBuff) { - - if (videoPackager == 0) { - printf("No se ha inicailizado el codec de output vídeo RTP"); - return -1; - } - - int l = inBuffLen + RTP_HEADER_LEN; - - rtpHeader * head = (rtpHeader*) outBuff; - - timeval time; - gettimeofday(&time, NULL); - long millis = (time.tv_sec * 1000) + (time.tv_usec / 1000); - - head->version = 2; //v = 2 - head->extension = 0; - head->marker = 1; //n?0:1; - head->padding = 0; - head->cc = 0; -// head->seqnum = htons(vRTPInfo->seqNum++); - head->timestamp = htonl(millis); - head->ssrc = htonl(vRTPInfo->ssrc); - head->payloadtype = 34; //32; - - outBuff += RTP_HEADER_LEN; - - memcpy(outBuff, inBuff, inBuffLen); - -// AVIOContext *c = avio_alloc_context((unsigned char*)outBuff, l, 1, NULL, NULL, NULL, NULL); -// -// vOutputFormatContext->pb = c; -// vOutputFormatContext->flags = AVFMT_NOFILE; -// -// AVPacket pkt; -// av_init_packet(&pkt); -// pkt.data = (unsigned char*)inBuff; -// pkt.size = inBuffLen; -// -// int ret = av_write_frame(vOutputFormatContext,&pkt); -// -// av_free_packet(&pkt); -// av_free(c); - - return l; -} - int OutputProcessor::packageAudio(unsigned char* inBuff, int inBuffLen, unsigned char* outBuff) { @@ -743,8 +698,8 @@ int OutputProcessor::packageAudio(unsigned char* inBuff, int inBuffLen, AVIOContext *c = avio_alloc_context((unsigned char*) outBuff, 2000, 1, NULL, NULL, NULL, NULL); - aOutputFormatContext->pb = c; - aOutputFormatContext->flags = AVFMT_NOFILE; +// aOutputFormatContext->pb = c; +// aOutputFormatContext->flags = AVFMT_NOFILE; AVPacket pkt; av_init_packet(&pkt); @@ -759,6 +714,59 @@ int OutputProcessor::packageAudio(unsigned char* inBuff, int inBuffLen, return ret; } +int OutputProcessor::packageVideo(unsigned char* inBuff, int inBuffLen, + unsigned char* outBuff) { + + if (videoPackager == 0) { + printf("No se ha inicailizado el codec de output vídeo RTP"); + return -1; + } + + if (mediaInfo.proccessorType == RTP_ONLY) { + + int l = inBuffLen + RTP_HEADER_LEN; + + rtpHeader * head = (rtpHeader*) outBuff; + + timeval time; + gettimeofday(&time, NULL); + long millis = (time.tv_sec * 1000) + (time.tv_usec / 1000); + + head->version = 2; //v = 2 + head->extension = 0; + head->marker = 1; //n?0:1; + head->padding = 0; + head->cc = 0; +// head->seqnum = htons(vRTPInfo->seqNum++); + head->timestamp = htonl(millis); + head->ssrc = htonl(vRTPInfo->ssrc); + head->payloadtype = 34; //32; + + outBuff += RTP_HEADER_LEN; + + memcpy(outBuff, inBuff, inBuffLen); + return l; + + } else { +// AVIOContext *c = avio_alloc_context((unsigned char*) outBuff, l, 1, +// NULL, NULL, NULL, NULL); +// +// vOutputFormatContext->pb = c; +// vOutputFormatContext->flags = AVFMT_NOFILE; + + AVPacket pkt; + av_init_packet(&pkt); + pkt.data = (unsigned char*) inBuff; + pkt.size = inBuffLen; + + int ret = av_write_frame(vOutputFormatContext, &pkt); + + av_free_packet(&pkt); +// av_free(c); + } + +} + int OutputProcessor::encodeAudio(unsigned char* inBuff, int nSamples, unsigned char* outBuff) { From 9bde21b211cbac7ee8e24fec407538fd8ed21ea5 Mon Sep 17 00:00:00 2001 From: Pedro Rodriguez Date: Tue, 7 Aug 2012 14:56:22 +0200 Subject: [PATCH 16/29] Added RTPSink and renamed RtpUtils to RtpParser --- src/CMakeLists.txt | 2 +- src/erizo/CMakeLists.txt | 2 +- src/erizo/OneToManyProcessor.cpp | 4 +- src/erizo/OneToManyProcessor.h | 1 - src/erizo/RTPSink.cpp | 39 ++++++ src/erizo/RTPSink.h | 34 +++++ src/erizo/media/MediaProcessor.cpp | 121 ++++++++++++++++-- src/erizo/media/MediaProcessor.h | 7 +- .../utils/{RtpUtils.cpp => RtpParser.cpp} | 2 +- .../media/utils/{RtpUtils.h => RtpParser.h} | 0 10 files changed, 198 insertions(+), 14 deletions(-) create mode 100644 src/erizo/RTPSink.cpp create mode 100644 src/erizo/RTPSink.h rename src/erizo/media/utils/{RtpUtils.cpp => RtpParser.cpp} (99%) rename src/erizo/media/utils/{RtpUtils.h => RtpParser.h} (100%) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 85771c272d..801c06c6f7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 2.8) project (ERIZO_ALL) -set (COMPILE_EXAMPLES ON) +set (COMPILE_EXAMPLES OFF) add_subdirectory(${ERIZO_ALL_SOURCES}erizo) find_package (Doxygen) if(DOXYGEN_FOUND) diff --git a/src/erizo/CMakeLists.txt b/src/erizo/CMakeLists.txt index 9b89f8b2d7..b0d0a88450 100644 --- a/src/erizo/CMakeLists.txt +++ b/src/erizo/CMakeLists.txt @@ -20,7 +20,7 @@ if (GTK2_FOUND) target_link_libraries(erizo ${GTK2_LIBRARIES}) endif(GTK2_FOUND) # BOOST -set (BOOST_LIBS thread regex) +set (BOOST_LIBS thread regex system) find_package(Boost COMPONENTS ${BOOST_LIBS} REQUIRED) target_link_libraries(erizo ${Boost_LIBRARIES}) diff --git a/src/erizo/OneToManyProcessor.cpp b/src/erizo/OneToManyProcessor.cpp index 22dd313dc8..bb89bd0612 100644 --- a/src/erizo/OneToManyProcessor.cpp +++ b/src/erizo/OneToManyProcessor.cpp @@ -25,11 +25,12 @@ OneToManyProcessor::OneToManyProcessor() : MediaInfo om; - om.proccessorType = RTP_ONLY; + om.proccessorType = AVF; om.videoCodec.bitRate =2000000; printf("m.videoCodec.bitrate %d\n\n", om.videoCodec.bitRate); om.videoCodec.height = 480; om.videoCodec.width = 640; + om.url = "file://tmp/test.mp4"; printf("Initiation outputprocessor\n"); op = new OutputProcessor(); op->init(om); @@ -81,6 +82,7 @@ int OneToManyProcessor::receiveVideoData(char* buf, int len) { void OneToManyProcessor::receiveRawData(unsigned char* buf, int len){ printf("Received %d\n", len); + op->receiveRawData(buf,len); // free(buf); } void OneToManyProcessor::setPublisher(WebRtcConnection* webRtcConn) { diff --git a/src/erizo/OneToManyProcessor.h b/src/erizo/OneToManyProcessor.h index f98a0cebbd..9571bafaf0 100644 --- a/src/erizo/OneToManyProcessor.h +++ b/src/erizo/OneToManyProcessor.h @@ -10,7 +10,6 @@ #include "MediaDefinitions.h" #include "media/MediaProcessor.h" -#include "media/utils/RtpUtils.h" namespace erizo{ diff --git a/src/erizo/RTPSink.cpp b/src/erizo/RTPSink.cpp new file mode 100644 index 0000000000..11f762a8c4 --- /dev/null +++ b/src/erizo/RTPSink.cpp @@ -0,0 +1,39 @@ +/* + * RTPSink.cpp + * + * Created on: Aug 2, 2012 + * Author: pedro + */ + +#include "RTPSink.h" +using boost::asio::ip::udp; + +namespace erizo { + +RTPSink::RTPSink(const std::string& url, const std::string& port) { + + ioservice_ = new boost::asio::io_service; + resolver_ = new udp::resolver(*ioservice_); + socket_ = new udp::socket(*ioservice_, udp::endpoint(udp::v4(), 40000)); + query_ = new udp::resolver::query(udp::v4(), url.c_str(), port.c_str()); + *iterator_ = resolver_->resolve(*query_); + +} + +RTPSink::~RTPSink() { + + free(ioservice_); + free(resolver_); + free(socket_); + free(query_); + +} + +int RTPSink::sendData(unsigned char* buffer, int len) { + + socket_->send_to(boost::asio::buffer(buffer, len), **iterator_); + + return len; +} + +} /* namespace erizo */ diff --git a/src/erizo/RTPSink.h b/src/erizo/RTPSink.h new file mode 100644 index 0000000000..b2bba804bb --- /dev/null +++ b/src/erizo/RTPSink.h @@ -0,0 +1,34 @@ +/* + * RTPSink.h + * + * Created on: Aug 2, 2012 + * Author: pedro + */ + +#ifndef RTPSINK_H_ +#define RTPSINK_H_ + +#include + + +namespace erizo { + +class RTPSink { +public: + RTPSink(const std::string& url, const std::string& port); + int sendData(unsigned char* buffer, int len); + virtual ~RTPSink(); + +private: + + boost::asio::ip::udp::socket* socket_; + boost::asio::ip::udp::resolver* resolver_; + + boost::asio::ip::udp::resolver::query* query_; + boost::asio::io_service* ioservice_; + boost::asio::ip::udp::resolver::iterator* iterator_; +}; + + +} /* namespace erizo */ +#endif /* RTPSINK_H_ */ diff --git a/src/erizo/media/MediaProcessor.cpp b/src/erizo/media/MediaProcessor.cpp index 53d8a0dc23..3be166bcf4 100644 --- a/src/erizo/media/MediaProcessor.cpp +++ b/src/erizo/media/MediaProcessor.cpp @@ -451,18 +451,28 @@ int InputProcessor::unpackageVideo(unsigned char* inBuff, int inBuffLen, head->payloadtype); return -1; } + int extoffset = 0; + if (head->extension) { + extoffset++; + extoffset += ntohs(head->extLength); + extoffset = extoffset * 4; + unsigned int extId = ntohs(head->extId); + printf("There is extension length: %u , id: %u\n", extoffset, + extId); + } int l = inBuffLen - RTP_HEADER_LEN; + l -= extoffset; inBuff += RTP_HEADER_LEN; -// vp8RtpHeader* vphead = (vp8RtpHeader*) inBuff; -// printf("MIO X: %u , N:%u PartID %u\n", vphead->X, vphead->N, -// vphead->partId); + inBuff += extoffset; + vp8RtpHeader* vphead = (vp8RtpHeader*) inBuff; + printf("MIO X: %u , N:%u PartID %u\n", vphead->X, vphead->N, + vphead->partId); erizo::RTPPayloadVP8* parsed = pars.parseVP8((unsigned char*) inBuff, l); printf("l : %d, parsedDatalength %u\n", l, parsed->dataLength); // l--; // inBuff++; - // memcpy(outBuff, inBuff, parsed->dataLength); memcpy(outBuff, parsed->data, parsed->dataLength); if (head->marker) { @@ -554,12 +564,19 @@ int OutputProcessor::init(const MediaInfo &info) { } void OutputProcessor::receiveRawData(unsigned char* data, int len) { - int a = this->encodeVideo(data, len, encodedBuffer_, - UNPACKAGED_BUFFER_SIZE); + AVPacket pkt; + av_init_packet(&pkt); + pkt.data = encodedBuffer_; + pkt.size = UNPACKAGED_BUFFER_SIZE; + +// int a = this->encodeVideo(data, len, encodedBuffer_, +// UNPACKAGED_BUFFER_SIZE); + int a = this->encodeVideo(data, len, &pkt); printf("\nBytes codificados = %d", a); - int b = this->packageVideo(encodedBuffer_, a, packagedBuffer_); +// int b = this->packageVideo(encodedBuffer_, a, packagedBuffer_); + int b = this->packageVideo(&pkt, packagedBuffer_); printf("\nBytes empaquetados = %d", b); } @@ -668,13 +685,14 @@ bool OutputProcessor::initVideoPackager() { if (mediaInfo.proccessorType == RTP_ONLY) { printf("RTP ONLY OutputProcessor\n"); } else { + printf("FILE ONLY OutputProcessor: %s\n", mediaInfo.url.c_str()); vOutputFormatContext = avformat_alloc_context(); if (!vOutputFormatContext) { printf("videoPackager: Error creating avformat context \n"); return false; } - vOutputFormat = av_guess_format(mediaInfo.url.c_str(), NULL, NULL); + vOutputFormat = av_guess_format(NULL, mediaInfo.url.c_str(), NULL); if (vOutputFormat == NULL) { printf("videoPackager: Could not guess format"); return false; @@ -682,6 +700,7 @@ bool OutputProcessor::initVideoPackager() { vOutputFormatContext->oformat = vOutputFormat; vOutputFormat->video_codec = mediaInfo.videoCodec.codec; + } videoPackager = 1; return true; @@ -766,6 +785,53 @@ int OutputProcessor::packageVideo(unsigned char* inBuff, int inBuffLen, } } +int OutputProcessor::packageVideo(AVPacket* pkt, unsigned char* outBuff) { + if (videoPackager == 0) { + printf("No se ha inicailizado el codec de output vídeo RTP"); + return -1; + } + + if (mediaInfo.proccessorType == RTP_ONLY) { + + int l = pkt->size + RTP_HEADER_LEN; + + rtpHeader * head = (rtpHeader*) pkt->data; + + timeval time; + gettimeofday(&time, NULL); + long millis = (time.tv_sec * 1000) + (time.tv_usec / 1000); + + head->version = 2; //v = 2 + head->extension = 0; + head->marker = 1; //n?0:1; + head->padding = 0; + head->cc = 0; +// head->seqnum = htons(vRTPInfo->seqNum++); + head->timestamp = htonl(millis); + head->ssrc = htonl(vRTPInfo->ssrc); + head->payloadtype = 34; //32; + + outBuff += RTP_HEADER_LEN; + + memcpy(outBuff, pkt->data, pkt->size); + return l; + + } else { +// AVIOContext *c = avio_alloc_context((unsigned char*) outBuff, l, 1, +// NULL, NULL, NULL, NULL); +// +// vOutputFormatContext->pb = c; +// vOutputFormatContext->flags = AVFMT_NOFILE; + + printf("por aqui\n"); + pkt->stream_index = 0; + int ret = av_write_frame(vOutputFormatContext, pkt); + + //av_free_packet(&pkt); +// av_free(c); + } + return 0; +} int OutputProcessor::encodeAudio(unsigned char* inBuff, int nSamples, unsigned char* outBuff) { @@ -870,4 +936,43 @@ int OutputProcessor::encodeVideo(unsigned char* inBuff, int inBuffLen, return ret ? ret : pkt.size; } + +int OutputProcessor::encodeVideo(unsigned char* inBuff, int inBuffLen, + AVPacket* pkt) { + if (videoCoder == 0) { + printf("No se han inicializado los parámetros del videoCoder"); + return -1; + } + + int size = vCoderContext->width * vCoderContext->height; + + cPicture->pts = AV_NOPTS_VALUE; + cPicture->data[0] = (unsigned char*) inBuff; + cPicture->data[1] = (unsigned char*) inBuff + size; + cPicture->data[2] = (unsigned char*) inBuff + size + size / 4; + cPicture->linesize[0] = vCoderContext->width; + cPicture->linesize[1] = vCoderContext->width / 2; + cPicture->linesize[2] = vCoderContext->width / 2; + + int ret = 0; + int got_packet = 0; + + ret = avcodec_encode_video2(vCoderContext, pkt, cPicture, &got_packet); + + if (!ret && got_packet && vCoderContext->coded_frame) { + vCoderContext->coded_frame->pts = pkt->pts; + vCoderContext->coded_frame->key_frame = + !!(pkt->flags & AV_PKT_FLAG_KEY); + } + + /* free any side data since we cannot return it */ +// if (pkt.side_data_elems > 0) { +// int i; +// for (i = 0; i < pkt.side_data_elems; i++) +// av_free(pkt.side_data[i].data); +// av_freep(&pkt.side_data); +// pkt.side_data_elems = 0; +// } + return ret ? ret : pkt->size; +} } /* namespace erizo */ diff --git a/src/erizo/media/MediaProcessor.h b/src/erizo/media/MediaProcessor.h index e531a32964..4aa3da92c6 100644 --- a/src/erizo/media/MediaProcessor.h +++ b/src/erizo/media/MediaProcessor.h @@ -6,7 +6,7 @@ #include #include -#include "utils/RtpUtils.h" +#include "utils/RtpParser.h" #include "../MediaDefinitions.h" extern "C" { @@ -64,6 +64,8 @@ typedef struct { uint32_t seqnum :16; uint32_t timestamp; uint32_t ssrc; + uint32_t extId:16; + uint32_t extLength:16; } rtpHeader; typedef struct { @@ -209,10 +211,13 @@ class OutputProcessor: public RawDataReceiver { int encodeVideo(unsigned char* inBuff, int inBuffLen, unsigned char* outBuff, int outBuffLen); + int encodeVideo(unsigned char* inBuff, int inBuffLen, AVPacket* pkt); + int packageAudio(unsigned char* inBuff, int inBuffLen, unsigned char* outBuff); int packageVideo(unsigned char* inBuff, int inBuffLen, unsigned char* outBuff); + int packageVideo(AVPacket* pkt, unsigned char* outBuff); }; } /* namespace erizo */ diff --git a/src/erizo/media/utils/RtpUtils.cpp b/src/erizo/media/utils/RtpParser.cpp similarity index 99% rename from src/erizo/media/utils/RtpUtils.cpp rename to src/erizo/media/utils/RtpParser.cpp index 770c5153da..165cec4e32 100644 --- a/src/erizo/media/utils/RtpUtils.cpp +++ b/src/erizo/media/utils/RtpParser.cpp @@ -2,7 +2,7 @@ #include #include -#include "RtpUtils.h" +#include "RtpParser.h" namespace erizo { diff --git a/src/erizo/media/utils/RtpUtils.h b/src/erizo/media/utils/RtpParser.h similarity index 100% rename from src/erizo/media/utils/RtpUtils.h rename to src/erizo/media/utils/RtpParser.h From dd62fe8a3217daa0ae0e6419114733eb62f9ee56 Mon Sep 17 00:00:00 2001 From: Pedro Rodriguez Date: Wed, 5 Sep 2012 12:27:51 +0200 Subject: [PATCH 17/29] Last media version --- src/erizo/OneToManyProcessor.cpp | 23 +- src/erizo/RTPSink.cpp | 8 +- src/erizo/RTPSink.h | 2 +- src/erizo/media/MediaProcessor.cpp | 321 ++++++++++++------------ src/erizo/media/MediaProcessor.h | 19 +- src/erizo/media/utils/RtpFragmenter.cpp | 67 +++++ src/erizo/media/utils/RtpFragmenter.h | 30 +++ src/erizo/media/utils/RtpParser.cpp | 1 - 8 files changed, 291 insertions(+), 180 deletions(-) create mode 100644 src/erizo/media/utils/RtpFragmenter.cpp create mode 100644 src/erizo/media/utils/RtpFragmenter.h diff --git a/src/erizo/OneToManyProcessor.cpp b/src/erizo/OneToManyProcessor.cpp index bb89bd0612..f019d55a02 100644 --- a/src/erizo/OneToManyProcessor.cpp +++ b/src/erizo/OneToManyProcessor.cpp @@ -16,20 +16,20 @@ OneToManyProcessor::OneToManyProcessor() : sentPackets_ = 0; ip = new InputProcessor(); MediaInfo m; - m.proccessorType= RTP_ONLY; - m.videoCodec.bitRate =2000000; + m.proccessorType = RTP_ONLY; + m.videoCodec.bitRate = 2000000; printf("m.videoCodec.bitrate %d\n\n", m.videoCodec.bitRate); m.videoCodec.height = 480; m.videoCodec.width = 640; ip->init(m, this); - MediaInfo om; - om.proccessorType = AVF; - om.videoCodec.bitRate =2000000; + om.proccessorType = RTP_ONLY; + om.videoCodec.bitRate = 500000; printf("m.videoCodec.bitrate %d\n\n", om.videoCodec.bitRate); om.videoCodec.height = 480; om.videoCodec.width = 640; + om.videoCodec.frameRate = 24; om.url = "file://tmp/test.mp4"; printf("Initiation outputprocessor\n"); op = new OutputProcessor(); @@ -62,8 +62,9 @@ int OneToManyProcessor::receiveAudioData(char* buf, int len) { } int OneToManyProcessor::receiveVideoData(char* buf, int len) { - - ip->receiveVideoData(buf,len); +// memset(sendVideoBuffer_, 0, len); + memcpy(sendVideoBuffer_, buf, len); + ip->receiveVideoData(sendVideoBuffer_, len); // if (subscribers.empty() || len <= 0) // return 0; @@ -80,24 +81,20 @@ int OneToManyProcessor::receiveVideoData(char* buf, int len) { // return 0; } -void OneToManyProcessor::receiveRawData(unsigned char* buf, int len){ +void OneToManyProcessor::receiveRawData(unsigned char* buf, int len) { printf("Received %d\n", len); - op->receiveRawData(buf,len); -// free(buf); + op->receiveRawData(buf, len); } void OneToManyProcessor::setPublisher(WebRtcConnection* webRtcConn) { - this->publisher = webRtcConn; } void OneToManyProcessor::addSubscriber(WebRtcConnection* webRtcConn, int peerId) { this->subscribers[peerId] = webRtcConn; - } void OneToManyProcessor::removeSubscriber(int peerId) { - if (this->subscribers.find(peerId) != subscribers.end()) { this->subscribers[peerId]->close(); this->subscribers.erase(peerId); diff --git a/src/erizo/RTPSink.cpp b/src/erizo/RTPSink.cpp index 11f762a8c4..9b5dc38bef 100644 --- a/src/erizo/RTPSink.cpp +++ b/src/erizo/RTPSink.cpp @@ -11,13 +11,11 @@ using boost::asio::ip::udp; namespace erizo { RTPSink::RTPSink(const std::string& url, const std::string& port) { - ioservice_ = new boost::asio::io_service; resolver_ = new udp::resolver(*ioservice_); socket_ = new udp::socket(*ioservice_, udp::endpoint(udp::v4(), 40000)); query_ = new udp::resolver::query(udp::v4(), url.c_str(), port.c_str()); - *iterator_ = resolver_->resolve(*query_); - + iterator_ = resolver_->resolve(*query_); } RTPSink::~RTPSink() { @@ -30,8 +28,8 @@ RTPSink::~RTPSink() { } int RTPSink::sendData(unsigned char* buffer, int len) { - - socket_->send_to(boost::asio::buffer(buffer, len), **iterator_); + printf("sending %u bytes\n", len); + socket_->send_to(boost::asio::buffer(buffer, len), *iterator_); return len; } diff --git a/src/erizo/RTPSink.h b/src/erizo/RTPSink.h index b2bba804bb..f4007ca268 100644 --- a/src/erizo/RTPSink.h +++ b/src/erizo/RTPSink.h @@ -26,7 +26,7 @@ class RTPSink { boost::asio::ip::udp::resolver::query* query_; boost::asio::io_service* ioservice_; - boost::asio::ip::udp::resolver::iterator* iterator_; + boost::asio::ip::udp::resolver::iterator iterator_; }; diff --git a/src/erizo/media/MediaProcessor.cpp b/src/erizo/media/MediaProcessor.cpp index 3be166bcf4..008ce18952 100644 --- a/src/erizo/media/MediaProcessor.cpp +++ b/src/erizo/media/MediaProcessor.cpp @@ -1,6 +1,8 @@ #include #include "MediaProcessor.h" +#include "../RTPSink.h" +#include "utils/RtpFragmenter.h" //UDPSocket *sock=NULL; //UDPSocket *out=NULL; @@ -39,7 +41,7 @@ InputProcessor::~InputProcessor() { } } -int InputProcessor::init(const MediaInfo &info, RawDataReceiver* receiver) { +int InputProcessor::init(const MediaInfo& info, RawDataReceiver* receiver) { this->mediaInfo = info; this->rawReceiver_ = receiver; @@ -65,16 +67,14 @@ int InputProcessor::receiveVideoData(char* buf, int len) { if (videoUnpackager && videoDecoder) { int ret = unpackageVideo(reinterpret_cast(buf), len, unpackagedBuffer_, &gotUnpackagedFrame_); + if (ret < 0) + return 0; upackagedSize_ += ret; unpackagedBuffer_ += ret; - if (gotUnpackagedFrame_) { - unpackagedBuffer_ -= upackagedSize_; - printf("Tengo un frame desempaquetado!! Size = %d\n", upackagedSize_); - int c; int gotDecodedFrame = 0; @@ -83,19 +83,12 @@ int InputProcessor::receiveVideoData(char* buf, int len) { upackagedSize_ = 0; gotUnpackagedFrame_ = 0; - printf("Bytes dec = %d\n", c); - if (gotDecodedFrame) { + if (gotDecodedFrame && c > 0) { printf("Tengo un frame decodificado!!\n"); gotDecodedFrame = 0; rawReceiver_->receiveRawData(decodedBuffer_, c); - memset(unpackagedBuffer_, 0, 50000); - -// unsigned char *buffSend = (unsigned char*) malloc(c); -// memcpy(buffSend, decodedBuffer_, c); - } - } return 3; } @@ -300,6 +293,7 @@ int InputProcessor::decodeVideo(unsigned char* inBuff, int inBuffLen, *gotFrame = 0; AVPacket avpkt; + av_init_packet(&avpkt); avpkt.data = inBuff; avpkt.size = inBuffLen; @@ -313,7 +307,7 @@ int InputProcessor::decodeVideo(unsigned char* inBuff, int inBuffLen, &avpkt); if (len < 0) { - printf("Error al decodificar frame de vídeo"); + printf("Error al decodificar frame de vídeo\n"); return -1; } @@ -375,6 +369,7 @@ int InputProcessor::decodeVideo(unsigned char* inBuff, int inBuffLen, cromV += dst_linesize; src += src_linesize; } + av_free_packet(&avpkt); return outSize * 3 / 2; } @@ -434,6 +429,7 @@ int InputProcessor::unpackageVideo(unsigned char* inBuff, int inBuffLen, printf("Unpackager not correctly initialized"); return -1; } + int inBuffOffset = 0; *gotFrame = 0; if (mediaInfo.proccessorType == RTP_ONLY) { rtpHeader* head = (rtpHeader*) inBuff; @@ -462,14 +458,14 @@ int InputProcessor::unpackageVideo(unsigned char* inBuff, int inBuffLen, } int l = inBuffLen - RTP_HEADER_LEN; l -= extoffset; - inBuff += RTP_HEADER_LEN; - inBuff += extoffset; - vp8RtpHeader* vphead = (vp8RtpHeader*) inBuff; + inBuffOffset += RTP_HEADER_LEN; + inBuffOffset += extoffset; + vp8RtpHeader* vphead = (vp8RtpHeader*) &inBuff[inBuffOffset]; printf("MIO X: %u , N:%u PartID %u\n", vphead->X, vphead->N, vphead->partId); - erizo::RTPPayloadVP8* parsed = pars.parseVP8((unsigned char*) inBuff, - l); + erizo::RTPPayloadVP8* parsed = pars.parseVP8( + (unsigned char*) &inBuff[inBuffOffset], l); printf("l : %d, parsedDatalength %u\n", l, parsed->dataLength); // l--; // inBuff++; @@ -541,13 +537,20 @@ OutputProcessor::~OutputProcessor() { if (packagedBuffer_) { free(packagedBuffer_); } + if (rtpBuffer_) { + free(rtpBuffer_); + } } -int OutputProcessor::init(const MediaInfo &info) { +int OutputProcessor::init(const MediaInfo& info) { this->mediaInfo = info; encodedBuffer_ = (unsigned char*) malloc(UNPACKAGED_BUFFER_SIZE); - packagedBuffer_ = (unsigned char*) malloc(UNPACKAGED_BUFFER_SIZE); + packagedBuffer_ = (unsigned char*) malloc(PACKAGED_BUFFER_SIZE); + rtpBuffer_ = (unsigned char*) malloc(PACKAGED_BUFFER_SIZE); + +// sink_ = new RTPSink("138.4.4.143", "50000"); + sink_ = new RTPSink("127.0.0.1", "50000"); // videoCodecInfo c; // c.codec = CODEC_ID_H264; @@ -556,9 +559,11 @@ int OutputProcessor::init(const MediaInfo &info) { // c.frameRate = 24; // c.bitRate = 1024; // c.maxInter = 0; - this->mediaInfo.videoCodec.codec = CODEC_ID_H263P; - - this->initVideoCoder(); + this->mediaInfo.videoCodec.codec = CODEC_ID_VP8; + if(!this->initVideoCoder()){ + printf("Fallo aqui\n"); + exit(0); + } this->initVideoPackager(); return 0; } @@ -573,11 +578,13 @@ void OutputProcessor::receiveRawData(unsigned char* data, int len) { // UNPACKAGED_BUFFER_SIZE); int a = this->encodeVideo(data, len, &pkt); - printf("\nBytes codificados = %d", a); +// printf("Bytes codificados = %d\n", a); -// int b = this->packageVideo(encodedBuffer_, a, packagedBuffer_); +// int b = this->packageVideo(encodedBuffer_, a, packagedBuffer_); int b = this->packageVideo(&pkt, packagedBuffer_); - printf("\nBytes empaquetados = %d", b); +// av_free_packet(&pkt); +// printf("Bytes empaquetados = %d\n", b); + av_free_packet(&pkt); } bool OutputProcessor::initAudioCoder() { @@ -637,7 +644,7 @@ bool OutputProcessor::initVideoCoder() { vCoderContext->rc_buffer_aggressivity = 1.0; vCoderContext->gop_size = mediaInfo.videoCodec.maxInter; vCoderContext->max_b_frames = 0; - vCoderContext->me_method = ME_EPZS; +// vCoderContext->me_method = ME_EPZS; vCoderContext->width = mediaInfo.videoCodec.width; vCoderContext->height = mediaInfo.videoCodec.height; @@ -684,6 +691,7 @@ bool OutputProcessor::initAudioPackager() { bool OutputProcessor::initVideoPackager() { if (mediaInfo.proccessorType == RTP_ONLY) { printf("RTP ONLY OutputProcessor\n"); + seqnum_ = 0; } else { printf("FILE ONLY OutputProcessor: %s\n", mediaInfo.url.c_str()); vOutputFormatContext = avformat_alloc_context(); @@ -733,58 +741,58 @@ int OutputProcessor::packageAudio(unsigned char* inBuff, int inBuffLen, return ret; } -int OutputProcessor::packageVideo(unsigned char* inBuff, int inBuffLen, - unsigned char* outBuff) { - - if (videoPackager == 0) { - printf("No se ha inicailizado el codec de output vídeo RTP"); - return -1; - } - - if (mediaInfo.proccessorType == RTP_ONLY) { - - int l = inBuffLen + RTP_HEADER_LEN; - - rtpHeader * head = (rtpHeader*) outBuff; - - timeval time; - gettimeofday(&time, NULL); - long millis = (time.tv_sec * 1000) + (time.tv_usec / 1000); - - head->version = 2; //v = 2 - head->extension = 0; - head->marker = 1; //n?0:1; - head->padding = 0; - head->cc = 0; -// head->seqnum = htons(vRTPInfo->seqNum++); - head->timestamp = htonl(millis); - head->ssrc = htonl(vRTPInfo->ssrc); - head->payloadtype = 34; //32; - - outBuff += RTP_HEADER_LEN; +//int OutputProcessor::packageVideo(unsigned char* inBuff, int inBuffLen, +// unsigned char* outBuff) { - memcpy(outBuff, inBuff, inBuffLen); - return l; - - } else { -// AVIOContext *c = avio_alloc_context((unsigned char*) outBuff, l, 1, -// NULL, NULL, NULL, NULL); +// if (videoPackager == 0) { +// printf("No se ha inicailizado el codec de output vídeo RTP"); +// return -1; +// } // -// vOutputFormatContext->pb = c; -// vOutputFormatContext->flags = AVFMT_NOFILE; - - AVPacket pkt; - av_init_packet(&pkt); - pkt.data = (unsigned char*) inBuff; - pkt.size = inBuffLen; - - int ret = av_write_frame(vOutputFormatContext, &pkt); - - av_free_packet(&pkt); -// av_free(c); - } +// if (mediaInfo.proccessorType == RTP_ONLY) { +// +// int l = inBuffLen + RTP_HEADER_LEN; +// +// rtpHeader * head = (rtpHeader*) outBuff; +// +// timeval time; +// gettimeofday(&time, NULL); +// long millis = (time.tv_sec * 1000) + (time.tv_usec / 1000); +// +// head->version = 2; //v = 2 +// head->extension = 0; +// head->marker = 1; //n?0:1; +// head->padding = 0; +// head->cc = 0; +//// head->seqnum = htons(vRTPInfo->seqNum++); +// head->timestamp = htonl(millis); +// head->ssrc = htonl(vRTPInfo->ssrc); +// head->payloadtype = 34; //32; +// +// outBuff += RTP_HEADER_LEN; +// +// memcpy(outBuff, inBuff, inBuffLen); +// return l; +// +// } else { +//// AVIOContext *c = avio_alloc_context((unsigned char*) outBuff, l, 1, +//// NULL, NULL, NULL, NULL); +//// +//// vOutputFormatContext->pb = c; +//// vOutputFormatContext->flags = AVFMT_NOFILE; +// +// AVPacket pkt; +// av_init_packet(&pkt); +// pkt.data = (unsigned char*) inBuff; +// pkt.size = inBuffLen; +// +// int ret = av_write_frame(vOutputFormatContext, &pkt); +// +// av_free_packet(&pkt); +//// av_free(c); +// } -} +//} int OutputProcessor::packageVideo(AVPacket* pkt, unsigned char* outBuff) { if (videoPackager == 0) { printf("No se ha inicailizado el codec de output vídeo RTP"); @@ -793,37 +801,44 @@ int OutputProcessor::packageVideo(AVPacket* pkt, unsigned char* outBuff) { if (mediaInfo.proccessorType == RTP_ONLY) { - int l = pkt->size + RTP_HEADER_LEN; - - rtpHeader * head = (rtpHeader*) pkt->data; - - timeval time; - gettimeofday(&time, NULL); - long millis = (time.tv_sec * 1000) + (time.tv_usec / 1000); - - head->version = 2; //v = 2 - head->extension = 0; - head->marker = 1; //n?0:1; - head->padding = 0; - head->cc = 0; -// head->seqnum = htons(vRTPInfo->seqNum++); - head->timestamp = htonl(millis); - head->ssrc = htonl(vRTPInfo->ssrc); - head->payloadtype = 34; //32; - - outBuff += RTP_HEADER_LEN; - - memcpy(outBuff, pkt->data, pkt->size); - return l; +// return l; + printf("To packetize %u\n", pkt->size); + if (pkt->size <= 0) + return -1; + RtpFragmenter frag(pkt->data, pkt->size); + bool lastFrame = false; + unsigned int outlen = 0; + do { + outlen = 0; + frag.getPacket(outBuff, &outlen, &lastFrame); + unsigned int l = outlen + RTP_HEADER_LEN; +// memset(rtpBuffer_,0,PACKAGED_BUFFER_SIZE); + rtpHeader * head = (rtpHeader*) rtpBuffer_; + timeval time; + gettimeofday(&time, NULL); + long millis = (time.tv_sec * 1000) + (time.tv_usec / 1000); + + head->version = 2; //v = 2 + head->extension = 0; + head->marker = lastFrame ? 1 : 0; + head->padding = 0; + head->cc = 0; + head->seqnum = htons(seqnum_++); + head->timestamp = htonl(millis);//pkt->pts; + head->ssrc = htonl(5554); + head->payloadtype = 96;//100; //32; + //rtpBuffer_ += RTP_HEADER_LEN; + printf("outlen to write %u, lastframe %d\n", outlen, lastFrame, pkt->dts); + memcpy(&rtpBuffer_[RTP_HEADER_LEN], outBuff, outlen); + sink_->sendData(rtpBuffer_, l); + } while (!lastFrame); } else { // AVIOContext *c = avio_alloc_context((unsigned char*) outBuff, l, 1, // NULL, NULL, NULL, NULL); -// // vOutputFormatContext->pb = c; // vOutputFormatContext->flags = AVFMT_NOFILE; - printf("por aqui\n"); pkt->stream_index = 0; int ret = av_write_frame(vOutputFormatContext, pkt); @@ -886,56 +901,55 @@ int OutputProcessor::encodeAudio(unsigned char* inBuff, int nSamples, } -int OutputProcessor::encodeVideo(unsigned char* inBuff, int inBuffLen, - unsigned char* outBuff, int outBuffLen) { - - if (videoCoder == 0) { - printf("No se han inicializado los parámetros del videoCoder"); - return -1; - } - - int size = vCoderContext->width * vCoderContext->height; - - cPicture->pts = AV_NOPTS_VALUE; - cPicture->data[0] = (unsigned char*) inBuff; - cPicture->data[1] = (unsigned char*) inBuff + size; - cPicture->data[2] = (unsigned char*) inBuff + size + size / 4; - cPicture->linesize[0] = vCoderContext->width; - cPicture->linesize[1] = vCoderContext->width / 2; - cPicture->linesize[2] = vCoderContext->width / 2; - - AVPacket pkt; - int ret = 0; - int got_packet = 0; - - if (outBuffLen < FF_MIN_BUFFER_SIZE) { - printf("buffer smaller than minimum size"); - return -1; - } - - av_init_packet(&pkt); - pkt.data = (unsigned char*) outBuff; - pkt.size = outBuffLen; - - ret = avcodec_encode_video2(vCoderContext, &pkt, cPicture, &got_packet); - - if (!ret && got_packet && vCoderContext->coded_frame) { - vCoderContext->coded_frame->pts = pkt.pts; - vCoderContext->coded_frame->key_frame = !!(pkt.flags & AV_PKT_FLAG_KEY); - } - - /* free any side data since we cannot return it */ - if (pkt.side_data_elems > 0) { - int i; - for (i = 0; i < pkt.side_data_elems; i++) - av_free(pkt.side_data[i].data); - av_freep(&pkt.side_data); - pkt.side_data_elems = 0; - } - - return ret ? ret : pkt.size; - -} +//int OutputProcessor::encodeVideo(unsigned char* inBuff, int inBuffLen, +// unsigned char* outBuff, int outBuffLen) { +// +// if (videoCoder == 0) { +// printf("No se han inicializado los parámetros del videoCoder"); +// return -1; +// } +// +// int size = vCoderContext->width * vCoderContext->height; +// +// cPicture->pts = AV_NOPTS_VALUE; +// cPicture->data[0] = (unsigned char*) inBuff; +// cPicture->data[1] = (unsigned char*) inBuff + size; +// cPicture->data[2] = (unsigned char*) inBuff + size + size / 4; +// cPicture->linesize[0] = vCoderContext->width; +// cPicture->linesize[1] = vCoderContext->width / 2; +// cPicture->linesize[2] = vCoderContext->width / 2; +// +// AVPacket pkt; +// int ret = 0; +// int got_packet = 0; +// +// if (outBuffLen < FF_MIN_BUFFER_SIZE) { +// printf("buffer smaller than minimum size"); +// return -1; +// } +// +// av_init_packet(&pkt); +// pkt.data = (unsigned char*) outBuff; +// pkt.size = outBuffLen; +// +// ret = avcodec_encode_video2(vCoderContext, &pkt, cPicture, &got_packet); +// +// if (!ret && got_packet && vCoderContext->coded_frame) { +// vCoderContext->coded_frame->pts = pkt.pts; +// vCoderContext->coded_frame->key_frame = !!(pkt.flags & AV_PKT_FLAG_KEY); +// } +// +// /* free any side data since we cannot return it */ +//// if (pkt.side_data_elems > 0) { +//// int i; +//// for (i = 0; i < pkt.side_data_elems; i++) +//// av_free(pkt.side_data[i].data); +//// av_freep(&pkt.side_data); +//// pkt.side_data_elems = 0; +//// } +// return ret ? ret : pkt.size; +// +//} int OutputProcessor::encodeVideo(unsigned char* inBuff, int inBuffLen, AVPacket* pkt) { @@ -943,7 +957,6 @@ int OutputProcessor::encodeVideo(unsigned char* inBuff, int inBuffLen, printf("No se han inicializado los parámetros del videoCoder"); return -1; } - int size = vCoderContext->width * vCoderContext->height; cPicture->pts = AV_NOPTS_VALUE; @@ -956,9 +969,9 @@ int OutputProcessor::encodeVideo(unsigned char* inBuff, int inBuffLen, int ret = 0; int got_packet = 0; - + printf("Before encoding\n"); ret = avcodec_encode_video2(vCoderContext, pkt, cPicture, &got_packet); - + printf("Encoded video size %u, ret %d, got_packet %d\n", pkt->size, ret, got_packet); if (!ret && got_packet && vCoderContext->coded_frame) { vCoderContext->coded_frame->pts = pkt->pts; vCoderContext->coded_frame->key_frame = diff --git a/src/erizo/media/MediaProcessor.h b/src/erizo/media/MediaProcessor.h index 4aa3da92c6..4fc05f1d0d 100644 --- a/src/erizo/media/MediaProcessor.h +++ b/src/erizo/media/MediaProcessor.h @@ -79,6 +79,7 @@ typedef struct { #define RTP_HEADER_LEN 12 #define UNPACKAGED_BUFFER_SIZE 50000 +#define PACKAGED_BUFFER_SIZE 1300 //class MediaProcessor{ // MediaProcessor(); // virtual ~Mediaprocessor(); @@ -96,6 +97,8 @@ class RawDataReceiver { }; +class RTPSink; + class InputProcessor: MediaReceiver { public: InputProcessor(); @@ -164,7 +167,7 @@ class OutputProcessor: public RawDataReceiver { OutputProcessor(); virtual ~OutputProcessor(); - int init(const MediaInfo &info); + int init(const MediaInfo& info); void receiveRawData(unsigned char*data, int len); @@ -176,8 +179,11 @@ class OutputProcessor: public RawDataReceiver { int audioPackager; int videoPackager; + unsigned int seqnum_; + unsigned char* encodedBuffer_; unsigned char* packagedBuffer_; + unsigned char* rtpBuffer_; MediaInfo mediaInfo; @@ -191,7 +197,8 @@ class OutputProcessor: public RawDataReceiver { AVFormatContext* aOutputFormatContext; AVOutputFormat* aOutputFormat; - RTPInfo* vRTPInfo; + RTPInfo* vRTPInfo_; + RTPSink* sink_; AVFormatContext* vOutputFormatContext; AVOutputFormat* vOutputFormat; @@ -208,15 +215,15 @@ class OutputProcessor: public RawDataReceiver { int encodeAudio(unsigned char* inBuff, int nSamples, unsigned char* outBuff); - int encodeVideo(unsigned char* inBuff, int inBuffLen, - unsigned char* outBuff, int outBuffLen); +// int encodeVideo(unsigned char* inBuff, int inBuffLen, +// unsigned char* outBuff, int outBuffLen); int encodeVideo(unsigned char* inBuff, int inBuffLen, AVPacket* pkt); int packageAudio(unsigned char* inBuff, int inBuffLen, unsigned char* outBuff); - int packageVideo(unsigned char* inBuff, int inBuffLen, - unsigned char* outBuff); +// int packageVideo(unsigned char* inBuff, int inBuffLen, +// unsigned char* outBuff); int packageVideo(AVPacket* pkt, unsigned char* outBuff); }; } /* namespace erizo */ diff --git a/src/erizo/media/utils/RtpFragmenter.cpp b/src/erizo/media/utils/RtpFragmenter.cpp new file mode 100644 index 0000000000..b2e63e1d7e --- /dev/null +++ b/src/erizo/media/utils/RtpFragmenter.cpp @@ -0,0 +1,67 @@ +#include +#include +#include "RtpFragmenter.h" + +#define MAX_SIZE 1180 //max size including vp8 payload descriptor +#define VP8 1 +namespace erizo { + +RtpFragmenter::RtpFragmenter(unsigned char* data, unsigned int length) : + totalData_(data), totalLenth_(length) { + calculatePackets(); + printf("Packets calculated successfully\n"); +} + +RtpFragmenter::~RtpFragmenter() { +} + +int RtpFragmenter::getPacket(unsigned char* data, unsigned int* length, + bool* lastPacket) { + if (fragmentQueue_.size() > 0) { + const Fragment& test = fragmentQueue_.front(); + printf("writing fragment, length %u\n", *length); + + *length = writeFragment(test, data, length); + fragmentQueue_.pop(); + if (fragmentQueue_.empty()) + *lastPacket = true; + + printf("lastPacket %d\n", *lastPacket); + + } + return 0; +} +void RtpFragmenter::calculatePackets() { + unsigned int remaining = totalLenth_; + unsigned int currentPos = 0; + while (remaining > 0) { + printf("Packetizing, remaining %u\n", remaining); + Fragment newFragment; + newFragment.first = false; + newFragment.position = currentPos; + if (currentPos == 0) + newFragment.first = true; + newFragment.size = remaining > MAX_SIZE - 1 ? MAX_SIZE - 1 : remaining; + printf("New fragment size %u, position %u\n", newFragment.size, + newFragment.position); + currentPos += newFragment.size; + remaining -= newFragment.size; + fragmentQueue_.push(newFragment); + } +} +unsigned int RtpFragmenter::writeFragment(const Fragment& fragment, + unsigned char* buffer, unsigned int* length) { + + if (VP8) { + buffer[0] = 0x0; + if (fragment.first) + buffer[0] |= 0x01; // S bit 1 // era 10 + memcpy(&buffer[1], &totalData_[fragment.position], fragment.size); + return (fragment.size + 1); + }else{ + memcpy(&buffer[0], &totalData_[fragment.position], fragment.size); + return fragment.size; + } +} + +} /* namespace erizo */ diff --git a/src/erizo/media/utils/RtpFragmenter.h b/src/erizo/media/utils/RtpFragmenter.h new file mode 100644 index 0000000000..a0e9498be0 --- /dev/null +++ b/src/erizo/media/utils/RtpFragmenter.h @@ -0,0 +1,30 @@ +#ifndef RTPFRAGMENTER_H_ +#define RTPFRAGMENTER_H_ + +#include + +namespace erizo { + +class RtpFragmenter { +public: + RtpFragmenter(unsigned char* data, unsigned int length); + virtual ~RtpFragmenter(); + + int getPacket(unsigned char* data, unsigned int* length, bool* lastPacket); + +private: + struct Fragment { + unsigned int position; + unsigned int size; + bool first; + }; + void calculatePackets(); + unsigned int writeFragment(const Fragment& fragment, unsigned char* buffer, + unsigned int* length); + unsigned char* totalData_; + unsigned int totalLenth_; + std::queue fragmentQueue_; +}; + +} /* namespace erizo */ +#endif /* RTPFRAGMENTER_H_ */ diff --git a/src/erizo/media/utils/RtpParser.cpp b/src/erizo/media/utils/RtpParser.cpp index 165cec4e32..45313f0a88 100644 --- a/src/erizo/media/utils/RtpParser.cpp +++ b/src/erizo/media/utils/RtpParser.cpp @@ -13,7 +13,6 @@ RtpParser::~RtpParser() { } -/* namespace erizo */ // // VP8 format: // From 877f37e15d6f1787aa75aec53c67aa12762296ec Mon Sep 17 00:00:00 2001 From: Pedro Rodriguez Date: Thu, 13 Sep 2012 16:05:11 +0200 Subject: [PATCH 18/29] First commit with transcoding working! --- src/erizo/OneToManyProcessor.cpp | 60 +++++-- src/erizo/OneToManyProcessor.h | 5 +- src/erizo/RTPSink.cpp | 2 +- src/erizo/SdpInfo.cpp | 2 +- src/erizo/WebRtcConnection.cpp | 1 - src/erizo/media/MediaProcessor.cpp | 228 ++++++------------------ src/erizo/media/MediaProcessor.h | 24 ++- src/erizo/media/utils/RtpFragmenter.cpp | 16 +- 8 files changed, 131 insertions(+), 207 deletions(-) diff --git a/src/erizo/OneToManyProcessor.cpp b/src/erizo/OneToManyProcessor.cpp index f019d55a02..1a888c85ba 100644 --- a/src/erizo/OneToManyProcessor.cpp +++ b/src/erizo/OneToManyProcessor.cpp @@ -4,6 +4,7 @@ #include "OneToManyProcessor.h" #include "WebRtcConnection.h" +#include "RTPSink.h" namespace erizo { OneToManyProcessor::OneToManyProcessor() : @@ -15,26 +16,26 @@ OneToManyProcessor::OneToManyProcessor() : publisher = NULL; sentPackets_ = 0; ip = new InputProcessor(); + sink_ = new RTPSink("127.0.0.1", "50000"); MediaInfo m; m.proccessorType = RTP_ONLY; - m.videoCodec.bitRate = 2000000; - printf("m.videoCodec.bitrate %d\n\n", m.videoCodec.bitRate); - m.videoCodec.height = 480; +// m.videoCodec.bitRate = 2000000; +// printf("m.videoCodec.bitrate %d\n\n", m.videoCodec.bitRate); + m.hasVideo = true; m.videoCodec.width = 640; + m.videoCodec.height = 480; ip->init(m, this); MediaInfo om; om.proccessorType = RTP_ONLY; - om.videoCodec.bitRate = 500000; - printf("m.videoCodec.bitrate %d\n\n", om.videoCodec.bitRate); - om.videoCodec.height = 480; + om.videoCodec.bitRate = 2000000; om.videoCodec.width = 640; - om.videoCodec.frameRate = 24; - om.url = "file://tmp/test.mp4"; - printf("Initiation outputprocessor\n"); + om.videoCodec.height = 480; + om.videoCodec.frameRate = 30; + om.hasVideo = true; +// om.url = "file://tmp/test.mp4"; op = new OutputProcessor(); - op->init(om); - printf("OutputProcessor initiated successfully\n"); + op->init(om, this); } @@ -44,6 +45,9 @@ OneToManyProcessor::~OneToManyProcessor() { delete sendVideoBuffer_; if (sendAudioBuffer_) delete sendAudioBuffer_; + if(sink_){ + delete sink_; + } } int OneToManyProcessor::receiveAudioData(char* buf, int len) { @@ -62,8 +66,13 @@ int OneToManyProcessor::receiveAudioData(char* buf, int len) { } int OneToManyProcessor::receiveVideoData(char* buf, int len) { -// memset(sendVideoBuffer_, 0, len); + memset(sendVideoBuffer_, 0, len); memcpy(sendVideoBuffer_, buf, len); +// ip->receiveVideoData(buf, len); + rtpHeader* head = (rtpHeader*) buf; + if (head->payloadtype!=100) + return 0; + ip->receiveVideoData(sendVideoBuffer_, len); // if (subscribers.empty() || len <= 0) @@ -77,14 +86,37 @@ int OneToManyProcessor::receiveVideoData(char* buf, int len) { // memcpy(sendVideoBuffer_, buf, len); // (*it).second->receiveVideoData(sendVideoBuffer_, len); // } -// sentPackets_++; -// return 0; +// memset(sendVideoBuffer_, 0, len); +// memcpy(sendVideoBuffer_, buf, len); +// sink_->sendData((unsigned char*)sendVideoBuffer_,len); + + sentPackets_++; + return 0; } void OneToManyProcessor::receiveRawData(unsigned char* buf, int len) { printf("Received %d\n", len); op->receiveRawData(buf, len); } + +void OneToManyProcessor::receiveRtpData(unsigned char*rtpdata, int len) { + printf("Received rtp data %d\n", len); + memcpy(sendVideoBuffer_, rtpdata, len); + + if (subscribers.empty() || len <= 0) + return; +// if (sentPackets_ % 500 == 0) { +// publisher->sendFirPacket(); +// } + std::map::iterator it; + for (it = subscribers.begin(); it != subscribers.end(); it++) { +// memset(sendVideoBuffer_, 0, len); + memcpy(sendVideoBuffer_, rtpdata, len); + (*it).second->receiveVideoData(sendVideoBuffer_, len); + } + sentPackets_++; +} + void OneToManyProcessor::setPublisher(WebRtcConnection* webRtcConn) { this->publisher = webRtcConn; } diff --git a/src/erizo/OneToManyProcessor.h b/src/erizo/OneToManyProcessor.h index 9571bafaf0..4b3d208e9f 100644 --- a/src/erizo/OneToManyProcessor.h +++ b/src/erizo/OneToManyProcessor.h @@ -14,12 +14,13 @@ namespace erizo{ class WebRtcConnection; +class RTPSink; /** * Represents a One to Many connection. * Receives media from one publisher and retransmits it to every subscriber. */ -class OneToManyProcessor : public MediaReceiver, public RawDataReceiver { +class OneToManyProcessor : public MediaReceiver, public RawDataReceiver, public RTPDataReceiver { public: WebRtcConnection *publisher; std::map subscribers; @@ -45,6 +46,7 @@ class OneToManyProcessor : public MediaReceiver, public RawDataReceiver { int receiveAudioData(char* buf, int len); int receiveVideoData(char* buf, int len); void receiveRawData (unsigned char* buf, int len); + void receiveRtpData(unsigned char*rtpdata, int len); // MediaProcessor *mp; InputProcessor* ip; @@ -60,6 +62,7 @@ class OneToManyProcessor : public MediaReceiver, public RawDataReceiver { char* unpackagedBuffer_; char* decodedBuffer_; char* codedBuffer_; + RTPSink* sink_; std::vector head; int gotFrame_,gotDecodedFrame_, size_; void sendHead(WebRtcConnection* conn); diff --git a/src/erizo/RTPSink.cpp b/src/erizo/RTPSink.cpp index 9b5dc38bef..8ef45661ed 100644 --- a/src/erizo/RTPSink.cpp +++ b/src/erizo/RTPSink.cpp @@ -28,7 +28,7 @@ RTPSink::~RTPSink() { } int RTPSink::sendData(unsigned char* buffer, int len) { - printf("sending %u bytes\n", len); +// printf("sending %u bytes\n", len); socket_->send_to(boost::asio::buffer(buffer, len), *iterator_); return len; diff --git a/src/erizo/SdpInfo.cpp b/src/erizo/SdpInfo.cpp index e3553a8e7c..b8442dfd89 100644 --- a/src/erizo/SdpInfo.cpp +++ b/src/erizo/SdpInfo.cpp @@ -134,7 +134,7 @@ std::string SdpInfo::getSdp() { } if (cand.mediaType == VIDEO_TYPE) { if (!printedVideo) { - sdp << "m=video " << cand.hostPort << " RTP/SAVPF 100 101 102\n" + sdp << "m=video " << cand.hostPort << " RTP/SAVPF 100 101 102\n"//" RTP/SAVPF 100 101 102\n" << "c=IN IP4 " << cand.hostAddress << endl << "a=rtcp:" << candidateVector_[0].hostPort << " IN IP4 " << cand.hostAddress diff --git a/src/erizo/WebRtcConnection.cpp b/src/erizo/WebRtcConnection.cpp index 5ee3773b13..30ec4e0037 100644 --- a/src/erizo/WebRtcConnection.cpp +++ b/src/erizo/WebRtcConnection.cpp @@ -260,7 +260,6 @@ int WebRtcConnection::receiveVideoData(char* buf, int len) { int res = -1; int length = len; if (videoSrtp_ && videoNice_->iceState == READY) { - // printf("protect\n"); videoSrtp_->protectRtp(buf, &length); } if (length <= 10) diff --git a/src/erizo/media/MediaProcessor.cpp b/src/erizo/media/MediaProcessor.cpp index 008ce18952..fa49b564c0 100644 --- a/src/erizo/media/MediaProcessor.cpp +++ b/src/erizo/media/MediaProcessor.cpp @@ -44,8 +44,10 @@ InputProcessor::~InputProcessor() { int InputProcessor::init(const MediaInfo& info, RawDataReceiver* receiver) { this->mediaInfo = info; this->rawReceiver_ = receiver; - + printf("INIT\n"); if (mediaInfo.hasVideo) { + printf("INIT\n"); + mediaInfo.videoCodec.codec = CODEC_ID_VP8; decodedBuffer_ = (unsigned char*) malloc( info.videoCodec.width * info.videoCodec.height * 3 / 2); @@ -63,8 +65,8 @@ int InputProcessor::receiveAudioData(char* buf, int len) { return 3; } int InputProcessor::receiveVideoData(char* buf, int len) { - if (videoUnpackager && videoDecoder) { + printf("elo\n"); int ret = unpackageVideo(reinterpret_cast(buf), len, unpackagedBuffer_, &gotUnpackagedFrame_); if (ret < 0) @@ -79,7 +81,9 @@ int InputProcessor::receiveVideoData(char* buf, int len) { int gotDecodedFrame = 0; c = this->decodeVideo(unpackagedBuffer_, upackagedSize_, - decodedBuffer_, 640 * 480 * 3 / 2, &gotDecodedFrame); + decodedBuffer_, + mediaInfo.videoCodec.width * mediaInfo.videoCodec.height * 3 + / 2, &gotDecodedFrame); upackagedSize_ = 0; gotUnpackagedFrame_ = 0; @@ -326,10 +330,11 @@ int InputProcessor::decodeVideo(unsigned char* inBuff, int inBuffLen, decoding: - int outSize = vDecoderContext->height * vDecoderContext->width; +// int outSize = vDecoderContext->height * vDecoderContext->width; + int outSize = mediaInfo.videoCodec.height * mediaInfo.videoCodec.width; if (outBuffLen < (outSize * 3 / 2)) { - printf("No se ha rellenado el buffer???"); + printf("No se ha rellenado el buffer??? outBuffLen = %d\n", outBuffLen); return outSize * 3 / 2; } @@ -382,9 +387,7 @@ int InputProcessor::unpackageAudio(unsigned char* inBuff, int inBuffLen, printf("No se ha inicializado el codec de input audio RTP"); return -1; } - AVIOContext *c = avio_alloc_context((unsigned char*)inBuff, inBuffLen, 0, NULL, NULL, NULL, NULL); - aInputFormatContext->pb = c; //aInputFormatContext->flags = AVFMT_NOFILE; aInputFormatContext->flags = AVFMT_FLAG_CUSTOM_IO; @@ -397,15 +400,9 @@ int InputProcessor::unpackageAudio(unsigned char* inBuff, int inBuffLen, av_init_packet(&pkt); //aInputFormatContext->iformat->read_packet(aInputFormatContext, &pkt); - - - - av_read_frame(aInputFormatContext, &pkt); - outBuff = (char*)pkt.data; - int se = pkt.size; av_free_packet(&pkt); @@ -413,9 +410,7 @@ int InputProcessor::unpackageAudio(unsigned char* inBuff, int inBuffLen, return se; */ - int l = inBuffLen - RTP_HEADER_LEN; - inBuff += RTP_HEADER_LEN; memcpy(outBuff, inBuff, l); @@ -429,6 +424,7 @@ int InputProcessor::unpackageVideo(unsigned char* inBuff, int inBuffLen, printf("Unpackager not correctly initialized"); return -1; } + int inBuffOffset = 0; *gotFrame = 0; if (mediaInfo.proccessorType == RTP_ONLY) { @@ -453,26 +449,26 @@ int InputProcessor::unpackageVideo(unsigned char* inBuff, int inBuffLen, extoffset += ntohs(head->extLength); extoffset = extoffset * 4; unsigned int extId = ntohs(head->extId); - printf("There is extension length: %u , id: %u\n", extoffset, - extId); +// printf("There is extension length: %u , id: %u\n", extoffset, +// extId); } int l = inBuffLen - RTP_HEADER_LEN; l -= extoffset; inBuffOffset += RTP_HEADER_LEN; inBuffOffset += extoffset; vp8RtpHeader* vphead = (vp8RtpHeader*) &inBuff[inBuffOffset]; - printf("MIO X: %u , N:%u PartID %u\n", vphead->X, vphead->N, - vphead->partId); +// printf("MIO X: %u , N:%u PartID %u\n", vphead->X, vphead->N, +// vphead->partId); erizo::RTPPayloadVP8* parsed = pars.parseVP8( (unsigned char*) &inBuff[inBuffOffset], l); - printf("l : %d, parsedDatalength %u\n", l, parsed->dataLength); +// printf("l : %d, parsedDatalength %u\n", l, parsed->dataLength); // l--; // inBuff++; // memcpy(outBuff, inBuff, parsed->dataLength); memcpy(outBuff, parsed->data, parsed->dataLength); if (head->marker) { - printf("Marker\n"); +// printf("Marker\n"); *gotFrame = 1; } @@ -511,6 +507,7 @@ OutputProcessor::OutputProcessor() { audioPackager = 0; videoPackager = 0; + timestamp_ = 0; encodedBuffer_ = NULL; packagedBuffer_ = NULL; @@ -542,25 +539,16 @@ OutputProcessor::~OutputProcessor() { } } -int OutputProcessor::init(const MediaInfo& info) { +int OutputProcessor::init(const MediaInfo& info, RTPDataReceiver* rtpReceiver) { this->mediaInfo = info; + this->rtpReceiver_ = rtpReceiver; encodedBuffer_ = (unsigned char*) malloc(UNPACKAGED_BUFFER_SIZE); packagedBuffer_ = (unsigned char*) malloc(PACKAGED_BUFFER_SIZE); rtpBuffer_ = (unsigned char*) malloc(PACKAGED_BUFFER_SIZE); -// sink_ = new RTPSink("138.4.4.143", "50000"); - sink_ = new RTPSink("127.0.0.1", "50000"); - -// videoCodecInfo c; -// c.codec = CODEC_ID_H264; -// c.width = 640; -// c.height = 480; -// c.frameRate = 24; -// c.bitRate = 1024; -// c.maxInter = 0; this->mediaInfo.videoCodec.codec = CODEC_ID_VP8; - if(!this->initVideoCoder()){ + if (!this->initVideoCoder()) { printf("Fallo aqui\n"); exit(0); } @@ -574,16 +562,9 @@ void OutputProcessor::receiveRawData(unsigned char* data, int len) { pkt.data = encodedBuffer_; pkt.size = UNPACKAGED_BUFFER_SIZE; -// int a = this->encodeVideo(data, len, encodedBuffer_, -// UNPACKAGED_BUFFER_SIZE); int a = this->encodeVideo(data, len, &pkt); - -// printf("Bytes codificados = %d\n", a); - -// int b = this->packageVideo(encodedBuffer_, a, packagedBuffer_); - int b = this->packageVideo(&pkt, packagedBuffer_); -// av_free_packet(&pkt); -// printf("Bytes empaquetados = %d\n", b); + if (a > 0) + int b = this->packageVideo(&pkt, packagedBuffer_); av_free_packet(&pkt); } @@ -630,27 +611,20 @@ bool OutputProcessor::initVideoCoder() { } vCoderContext->bit_rate = mediaInfo.videoCodec.bitRate; - vCoderContext->bit_rate_tolerance = 1.1 * mediaInfo.videoCodec.bitRate - / mediaInfo.videoCodec.frameRate; - vCoderContext->rc_max_rate = mediaInfo.videoCodec.bitRate * 2; - - if (mediaInfo.videoCodec.frameRate >= 1.0) { - vCoderContext->rc_buffer_size = mediaInfo.videoCodec.bitRate; // 1 second stored, in bps - } else { - vCoderContext->rc_buffer_size = 1.1 * mediaInfo.videoCodec.bitRate - / mediaInfo.videoCodec.frameRate; - } - - vCoderContext->rc_buffer_aggressivity = 1.0; - vCoderContext->gop_size = mediaInfo.videoCodec.maxInter; - vCoderContext->max_b_frames = 0; -// vCoderContext->me_method = ME_EPZS; - + vCoderContext->rc_min_rate = mediaInfo.videoCodec.bitRate; // + vCoderContext->rc_max_rate = mediaInfo.videoCodec.bitRate; // VPX_CBR + vCoderContext->qmin = 8; + vCoderContext->qmax = 56; // rc_quantifiers +// vCoderContext->frame_skip_threshold = 30; + vCoderContext->rc_buffer_aggressivity = 1; + vCoderContext->rc_buffer_size = vCoderContext->bit_rate; + vCoderContext->rc_initial_buffer_occupancy = vCoderContext->bit_rate / 2; vCoderContext->width = mediaInfo.videoCodec.width; vCoderContext->height = mediaInfo.videoCodec.height; vCoderContext->pix_fmt = PIX_FMT_YUV420P; - vCoderContext->time_base = - (AVRational) {1000, 1000*mediaInfo.videoCodec.frameRate}; + vCoderContext->time_base = (AVRational) {1, 90000}; + vCoderContext->sample_aspect_ratio = + (AVRational) {mediaInfo.videoCodec.width,mediaInfo.videoCodec.height}; if (avcodec_open2(vCoderContext, vCoder, NULL) < 0) { printf("Error al abrir el decoder de vídeo"); @@ -664,6 +638,8 @@ bool OutputProcessor::initVideoCoder() { } videoCoder = 1; + printf("videoCoder configured successfully %d x %d\n", vCoderContext->width, + vCoderContext->height); return true; } @@ -741,58 +717,6 @@ int OutputProcessor::packageAudio(unsigned char* inBuff, int inBuffLen, return ret; } -//int OutputProcessor::packageVideo(unsigned char* inBuff, int inBuffLen, -// unsigned char* outBuff) { - -// if (videoPackager == 0) { -// printf("No se ha inicailizado el codec de output vídeo RTP"); -// return -1; -// } -// -// if (mediaInfo.proccessorType == RTP_ONLY) { -// -// int l = inBuffLen + RTP_HEADER_LEN; -// -// rtpHeader * head = (rtpHeader*) outBuff; -// -// timeval time; -// gettimeofday(&time, NULL); -// long millis = (time.tv_sec * 1000) + (time.tv_usec / 1000); -// -// head->version = 2; //v = 2 -// head->extension = 0; -// head->marker = 1; //n?0:1; -// head->padding = 0; -// head->cc = 0; -//// head->seqnum = htons(vRTPInfo->seqNum++); -// head->timestamp = htonl(millis); -// head->ssrc = htonl(vRTPInfo->ssrc); -// head->payloadtype = 34; //32; -// -// outBuff += RTP_HEADER_LEN; -// -// memcpy(outBuff, inBuff, inBuffLen); -// return l; -// -// } else { -//// AVIOContext *c = avio_alloc_context((unsigned char*) outBuff, l, 1, -//// NULL, NULL, NULL, NULL); -//// -//// vOutputFormatContext->pb = c; -//// vOutputFormatContext->flags = AVFMT_NOFILE; -// -// AVPacket pkt; -// av_init_packet(&pkt); -// pkt.data = (unsigned char*) inBuff; -// pkt.size = inBuffLen; -// -// int ret = av_write_frame(vOutputFormatContext, &pkt); -// -// av_free_packet(&pkt); -//// av_free(c); -// } - -//} int OutputProcessor::packageVideo(AVPacket* pkt, unsigned char* outBuff) { if (videoPackager == 0) { printf("No se ha inicailizado el codec de output vídeo RTP"); @@ -808,15 +732,17 @@ int OutputProcessor::packageVideo(AVPacket* pkt, unsigned char* outBuff) { RtpFragmenter frag(pkt->data, pkt->size); bool lastFrame = false; unsigned int outlen = 0; + timeval time; + gettimeofday(&time, NULL); + long millis = (time.tv_sec * 1000) + (time.tv_usec / 1000); + timestamp_ += 90000 / mediaInfo.videoCodec.frameRate; + do { outlen = 0; frag.getPacket(outBuff, &outlen, &lastFrame); unsigned int l = outlen + RTP_HEADER_LEN; // memset(rtpBuffer_,0,PACKAGED_BUFFER_SIZE); rtpHeader * head = (rtpHeader*) rtpBuffer_; - timeval time; - gettimeofday(&time, NULL); - long millis = (time.tv_sec * 1000) + (time.tv_usec / 1000); head->version = 2; //v = 2 head->extension = 0; @@ -824,13 +750,16 @@ int OutputProcessor::packageVideo(AVPacket* pkt, unsigned char* outBuff) { head->padding = 0; head->cc = 0; head->seqnum = htons(seqnum_++); - head->timestamp = htonl(millis);//pkt->pts; - head->ssrc = htonl(5554); - head->payloadtype = 96;//100; //32; + head->timestamp = htonl(millis * 90); //pkt->pts; +// head->timestamp = htonl(timestamp_); + head->ssrc = htonl(55543); + head->payloadtype = 100; //rtpBuffer_ += RTP_HEADER_LEN; - printf("outlen to write %u, lastframe %d\n", outlen, lastFrame, pkt->dts); + printf("outlen to write %u, lastframe %d\n", outlen, lastFrame, + pkt->dts); memcpy(&rtpBuffer_[RTP_HEADER_LEN], outBuff, outlen); - sink_->sendData(rtpBuffer_, l); +// sink_->sendData(rtpBuffer_, l); + rtpReceiver_->receiveRtpData(rtpBuffer_, l); } while (!lastFrame); } else { @@ -901,56 +830,6 @@ int OutputProcessor::encodeAudio(unsigned char* inBuff, int nSamples, } -//int OutputProcessor::encodeVideo(unsigned char* inBuff, int inBuffLen, -// unsigned char* outBuff, int outBuffLen) { -// -// if (videoCoder == 0) { -// printf("No se han inicializado los parámetros del videoCoder"); -// return -1; -// } -// -// int size = vCoderContext->width * vCoderContext->height; -// -// cPicture->pts = AV_NOPTS_VALUE; -// cPicture->data[0] = (unsigned char*) inBuff; -// cPicture->data[1] = (unsigned char*) inBuff + size; -// cPicture->data[2] = (unsigned char*) inBuff + size + size / 4; -// cPicture->linesize[0] = vCoderContext->width; -// cPicture->linesize[1] = vCoderContext->width / 2; -// cPicture->linesize[2] = vCoderContext->width / 2; -// -// AVPacket pkt; -// int ret = 0; -// int got_packet = 0; -// -// if (outBuffLen < FF_MIN_BUFFER_SIZE) { -// printf("buffer smaller than minimum size"); -// return -1; -// } -// -// av_init_packet(&pkt); -// pkt.data = (unsigned char*) outBuff; -// pkt.size = outBuffLen; -// -// ret = avcodec_encode_video2(vCoderContext, &pkt, cPicture, &got_packet); -// -// if (!ret && got_packet && vCoderContext->coded_frame) { -// vCoderContext->coded_frame->pts = pkt.pts; -// vCoderContext->coded_frame->key_frame = !!(pkt.flags & AV_PKT_FLAG_KEY); -// } -// -// /* free any side data since we cannot return it */ -//// if (pkt.side_data_elems > 0) { -//// int i; -//// for (i = 0; i < pkt.side_data_elems; i++) -//// av_free(pkt.side_data[i].data); -//// av_freep(&pkt.side_data); -//// pkt.side_data_elems = 0; -//// } -// return ret ? ret : pkt.size; -// -//} - int OutputProcessor::encodeVideo(unsigned char* inBuff, int inBuffLen, AVPacket* pkt) { if (videoCoder == 0) { @@ -958,6 +837,7 @@ int OutputProcessor::encodeVideo(unsigned char* inBuff, int inBuffLen, return -1; } int size = vCoderContext->width * vCoderContext->height; + printf("vCoderContext width %d\n", vCoderContext->width); cPicture->pts = AV_NOPTS_VALUE; cPicture->data[0] = (unsigned char*) inBuff; @@ -969,15 +849,17 @@ int OutputProcessor::encodeVideo(unsigned char* inBuff, int inBuffLen, int ret = 0; int got_packet = 0; - printf("Before encoding\n"); + printf( + "Before encoding inBufflen %d, size %d, codecontext width %d pkt->size%d\n", + inBuffLen, size, vCoderContext->width, pkt->size); ret = avcodec_encode_video2(vCoderContext, pkt, cPicture, &got_packet); - printf("Encoded video size %u, ret %d, got_packet %d\n", pkt->size, ret, got_packet); + printf("Encoded video size %u, ret %d, got_packet %d, pts %lld, dts %lld\n", + pkt->size, ret, got_packet, pkt->pts, pkt->dts); if (!ret && got_packet && vCoderContext->coded_frame) { vCoderContext->coded_frame->pts = pkt->pts; vCoderContext->coded_frame->key_frame = !!(pkt->flags & AV_PKT_FLAG_KEY); } - /* free any side data since we cannot return it */ // if (pkt.side_data_elems > 0) { // int i; diff --git a/src/erizo/media/MediaProcessor.h b/src/erizo/media/MediaProcessor.h index 4fc05f1d0d..3f59892a13 100644 --- a/src/erizo/media/MediaProcessor.h +++ b/src/erizo/media/MediaProcessor.h @@ -64,8 +64,8 @@ typedef struct { uint32_t seqnum :16; uint32_t timestamp; uint32_t ssrc; - uint32_t extId:16; - uint32_t extLength:16; + uint32_t extId :16; + uint32_t extLength :16; } rtpHeader; typedef struct { @@ -78,8 +78,8 @@ typedef struct { #define RTP_HEADER_LEN 12 -#define UNPACKAGED_BUFFER_SIZE 50000 -#define PACKAGED_BUFFER_SIZE 1300 +#define UNPACKAGED_BUFFER_SIZE 150000 +#define PACKAGED_BUFFER_SIZE 2000 //class MediaProcessor{ // MediaProcessor(); // virtual ~Mediaprocessor(); @@ -94,7 +94,14 @@ class RawDataReceiver { virtual ~RawDataReceiver() { } ; +}; +class RTPDataReceiver { +public: + virtual void receiveRtpData(unsigned char*rtpdata, int len) = 0; + virtual ~RTPDataReceiver() { + } + ; }; class RTPSink; @@ -125,7 +132,6 @@ class InputProcessor: MediaReceiver { unsigned char* decodedBuffer_; unsigned char* unpackagedBuffer_; - AVCodec* aDecoder; AVCodecContext* aDecoderContext; @@ -167,7 +173,7 @@ class OutputProcessor: public RawDataReceiver { OutputProcessor(); virtual ~OutputProcessor(); - int init(const MediaInfo& info); + int init(const MediaInfo& info, RTPDataReceiver* rtpReceiver); void receiveRawData(unsigned char*data, int len); @@ -181,12 +187,16 @@ class OutputProcessor: public RawDataReceiver { unsigned int seqnum_; + unsigned long timestamp_; + unsigned char* encodedBuffer_; unsigned char* packagedBuffer_; unsigned char* rtpBuffer_; MediaInfo mediaInfo; + RTPDataReceiver* rtpReceiver_; + AVCodec* aCoder; AVCodecContext* aCoderContext; @@ -203,8 +213,6 @@ class OutputProcessor: public RawDataReceiver { AVFormatContext* vOutputFormatContext; AVOutputFormat* vOutputFormat; - MediaReceiver* Receiver; - RtpParser pars; bool initAudioCoder(); diff --git a/src/erizo/media/utils/RtpFragmenter.cpp b/src/erizo/media/utils/RtpFragmenter.cpp index b2e63e1d7e..cce99cd5a5 100644 --- a/src/erizo/media/utils/RtpFragmenter.cpp +++ b/src/erizo/media/utils/RtpFragmenter.cpp @@ -2,14 +2,14 @@ #include #include "RtpFragmenter.h" -#define MAX_SIZE 1180 //max size including vp8 payload descriptor +#define MAX_SIZE 1100 //max fragment size including vp8 payload descriptor #define VP8 1 namespace erizo { RtpFragmenter::RtpFragmenter(unsigned char* data, unsigned int length) : totalData_(data), totalLenth_(length) { calculatePackets(); - printf("Packets calculated successfully\n"); +// printf("Packets calculated successfully\n"); } RtpFragmenter::~RtpFragmenter() { @@ -19,14 +19,14 @@ int RtpFragmenter::getPacket(unsigned char* data, unsigned int* length, bool* lastPacket) { if (fragmentQueue_.size() > 0) { const Fragment& test = fragmentQueue_.front(); - printf("writing fragment, length %u\n", *length); +// printf("writing fragment, length %u\n", *length); *length = writeFragment(test, data, length); fragmentQueue_.pop(); if (fragmentQueue_.empty()) *lastPacket = true; - printf("lastPacket %d\n", *lastPacket); +// printf("lastPacket %d\n", *lastPacket); } return 0; @@ -35,15 +35,15 @@ void RtpFragmenter::calculatePackets() { unsigned int remaining = totalLenth_; unsigned int currentPos = 0; while (remaining > 0) { - printf("Packetizing, remaining %u\n", remaining); +// printf("Packetizing, remaining %u\n", remaining); Fragment newFragment; newFragment.first = false; newFragment.position = currentPos; if (currentPos == 0) newFragment.first = true; newFragment.size = remaining > MAX_SIZE - 1 ? MAX_SIZE - 1 : remaining; - printf("New fragment size %u, position %u\n", newFragment.size, - newFragment.position); +// printf("New fragment size %u, position %u\n", newFragment.size, +// newFragment.position); currentPos += newFragment.size; remaining -= newFragment.size; fragmentQueue_.push(newFragment); @@ -55,7 +55,7 @@ unsigned int RtpFragmenter::writeFragment(const Fragment& fragment, if (VP8) { buffer[0] = 0x0; if (fragment.first) - buffer[0] |= 0x01; // S bit 1 // era 10 + buffer[0] |= 0x10; // S bit 1 // era 01 memcpy(&buffer[1], &totalData_[fragment.position], fragment.size); return (fragment.size + 1); }else{ From a9ccace4f68215e1e859974956b0ab24d9999a5f Mon Sep 17 00:00:00 2001 From: Pedro Rodriguez Date: Wed, 26 Sep 2012 17:29:53 +0200 Subject: [PATCH 19/29] Code cleanup --- src/erizo/OneToManyProcessor.cpp | 40 +- src/erizo/OneToManyProcessor.h | 2 +- src/erizo/SdpInfo.cpp | 9 +- src/erizo/WebRtcConnection.cpp | 2 +- src/erizo/media/MediaProcessor.cpp | 1612 +++++++++++------------ src/erizo/media/MediaProcessor.h | 52 +- src/erizo/media/utils/RtpFragmenter.cpp | 67 - src/erizo/media/utils/RtpFragmenter.h | 30 - 8 files changed, 805 insertions(+), 1009 deletions(-) delete mode 100644 src/erizo/media/utils/RtpFragmenter.cpp delete mode 100644 src/erizo/media/utils/RtpFragmenter.h diff --git a/src/erizo/OneToManyProcessor.cpp b/src/erizo/OneToManyProcessor.cpp index 1a888c85ba..9992f2f075 100644 --- a/src/erizo/OneToManyProcessor.cpp +++ b/src/erizo/OneToManyProcessor.cpp @@ -5,6 +5,7 @@ #include "OneToManyProcessor.h" #include "WebRtcConnection.h" #include "RTPSink.h" +#include "media/utils/RtpHeader.h" namespace erizo { OneToManyProcessor::OneToManyProcessor() : @@ -24,6 +25,12 @@ OneToManyProcessor::OneToManyProcessor() : m.hasVideo = true; m.videoCodec.width = 640; m.videoCodec.height = 480; + m.hasAudio = false; + if (m.hasAudio) { + m.audioCodec.sampleRate = 8000; + m.audioCodec.bitRate = 64000; + + } ip->init(m, this); MediaInfo om; @@ -31,9 +38,16 @@ OneToManyProcessor::OneToManyProcessor() : om.videoCodec.bitRate = 2000000; om.videoCodec.width = 640; om.videoCodec.height = 480; - om.videoCodec.frameRate = 30; + om.videoCodec.frameRate = 20; om.hasVideo = true; // om.url = "file://tmp/test.mp4"; + + om.hasAudio = false; + if (om.hasAudio) { + om.audioCodec.sampleRate = 8000; + om.audioCodec.bitRate = 64000; + } + op = new OutputProcessor(); op->init(om, this); @@ -45,7 +59,7 @@ OneToManyProcessor::~OneToManyProcessor() { delete sendVideoBuffer_; if (sendAudioBuffer_) delete sendAudioBuffer_; - if(sink_){ + if (sink_) { delete sink_; } } @@ -68,12 +82,17 @@ int OneToManyProcessor::receiveAudioData(char* buf, int len) { int OneToManyProcessor::receiveVideoData(char* buf, int len) { memset(sendVideoBuffer_, 0, len); memcpy(sendVideoBuffer_, buf, len); -// ip->receiveVideoData(buf, len); - rtpHeader* head = (rtpHeader*) buf; - if (head->payloadtype!=100) - return 0; - ip->receiveVideoData(sendVideoBuffer_, len); + RTPHeader* theHead = reinterpret_cast(buf); + printf("Probando nuevo header\n\n"); + printf("extension %d pt %u\n", theHead->getExtension(), + theHead->getPayloadType()); + + if (theHead->getPayloadType() == 100) { + ip->receiveVideoData(sendVideoBuffer_, len); + } else { + this->receiveRtpData((unsigned char*) buf, len); + } // if (subscribers.empty() || len <= 0) // return 0; @@ -94,9 +113,9 @@ int OneToManyProcessor::receiveVideoData(char* buf, int len) { return 0; } -void OneToManyProcessor::receiveRawData(unsigned char* buf, int len) { - printf("Received %d\n", len); - op->receiveRawData(buf, len); +void OneToManyProcessor::receiveRawData(RawDataPacket& pkt) { + printf("Received %d\n", pkt.length); + op->receiveRawData(pkt); } void OneToManyProcessor::receiveRtpData(unsigned char*rtpdata, int len) { @@ -110,7 +129,6 @@ void OneToManyProcessor::receiveRtpData(unsigned char*rtpdata, int len) { // } std::map::iterator it; for (it = subscribers.begin(); it != subscribers.end(); it++) { -// memset(sendVideoBuffer_, 0, len); memcpy(sendVideoBuffer_, rtpdata, len); (*it).second->receiveVideoData(sendVideoBuffer_, len); } diff --git a/src/erizo/OneToManyProcessor.h b/src/erizo/OneToManyProcessor.h index 4b3d208e9f..a86238e13b 100644 --- a/src/erizo/OneToManyProcessor.h +++ b/src/erizo/OneToManyProcessor.h @@ -45,7 +45,7 @@ class OneToManyProcessor : public MediaReceiver, public RawDataReceiver, public void removeSubscriber(int peerId); int receiveAudioData(char* buf, int len); int receiveVideoData(char* buf, int len); - void receiveRawData (unsigned char* buf, int len); + void receiveRawData(RawDataPacket& packet); void receiveRtpData(unsigned char*rtpdata, int len); // MediaProcessor *mp; diff --git a/src/erizo/SdpInfo.cpp b/src/erizo/SdpInfo.cpp index b8442dfd89..13a56d1eb0 100644 --- a/src/erizo/SdpInfo.cpp +++ b/src/erizo/SdpInfo.cpp @@ -102,9 +102,10 @@ std::string SdpInfo::getSdp() { } sdp - << "a=rtpmap:103 ISAC/16000\na=rtpmap:104 ISAC/32000\na=rtpmap:0 PCMU/8000\n" - "a=rtpmap:8 PCMA/8000\na=rtpmap:106 CN/32000\na=rtpmap:105 CN/16000\n" - "a=rtpmap:13 CN/8000\na=rtpmap:126 telephone-event/8000\n"; +// << "a=rtpmap:103 ISAC/16000\na=rtpmap:104 ISAC/32000\na=rtpmap:0 PCMU/8000\n" +// "a=rtpmap:8 PCMA/8000\na=rtpmap:106 CN/32000\na=rtpmap:105 CN/16000\n" +// "a=rtpmap:13 CN/8000\na=rtpmap:126 telephone-event/8000\n"; + << "a=rtpmap:0 PCMU/8000\n"; sdp << "a=ssrc:" << audioSsrc << " cname:o/i14u9pJrxRKAsu\na=ssrc:" << audioSsrc << " mslabel:048f838f-2dd1-4a98-ab9e-8eb5f00abab8\na=ssrc:" @@ -134,7 +135,7 @@ std::string SdpInfo::getSdp() { } if (cand.mediaType == VIDEO_TYPE) { if (!printedVideo) { - sdp << "m=video " << cand.hostPort << " RTP/SAVPF 100 101 102\n"//" RTP/SAVPF 100 101 102\n" + sdp << "m=video " << cand.hostPort << " RTP/SAVPF 100 101 102\n" << "c=IN IP4 " << cand.hostAddress << endl << "a=rtcp:" << candidateVector_[0].hostPort << " IN IP4 " << cand.hostAddress diff --git a/src/erizo/WebRtcConnection.cpp b/src/erizo/WebRtcConnection.cpp index 30ec4e0037..dceb7f32f4 100644 --- a/src/erizo/WebRtcConnection.cpp +++ b/src/erizo/WebRtcConnection.cpp @@ -390,7 +390,7 @@ void WebRtcConnection::updateState(IceState newState, if (connStateListener_ != NULL) connStateListener_->connectionStateChanged(globalIceState_); // if (newState == FAILED) -//// this->close(); +// this->close(); } } diff --git a/src/erizo/media/MediaProcessor.cpp b/src/erizo/media/MediaProcessor.cpp index fa49b564c0..48781326c3 100644 --- a/src/erizo/media/MediaProcessor.cpp +++ b/src/erizo/media/MediaProcessor.cpp @@ -1,873 +1,757 @@ #include #include "MediaProcessor.h" -#include "../RTPSink.h" -#include "utils/RtpFragmenter.h" - -//UDPSocket *sock=NULL; -//UDPSocket *out=NULL; +#include "utils/RtpVP8Fragmenter.h" +#include "utils/RtpHeader.h" namespace erizo { -InputProcessor::InputProcessor() { - - audioDecoder = 0; - videoDecoder = 0; - - audioUnpackager = 0; - videoUnpackager = 0; - gotUnpackagedFrame_ = false; - upackagedSize_ = 0; - - decodedBuffer_ = NULL; - - avcodec_register_all(); - av_register_all(); -} - -InputProcessor::~InputProcessor() { - if (audioDecoder == 1) { - avcodec_close(aDecoderContext); - av_free(aDecoderContext); - } - - if (videoDecoder == 1) { - avcodec_close(vDecoderContext); - av_free(vDecoderContext); - av_free(dPicture); - } - if (decodedBuffer_ != NULL) { - free(decodedBuffer_); - } -} - -int InputProcessor::init(const MediaInfo& info, RawDataReceiver* receiver) { - this->mediaInfo = info; - this->rawReceiver_ = receiver; - printf("INIT\n"); - if (mediaInfo.hasVideo) { - printf("INIT\n"); - - mediaInfo.videoCodec.codec = CODEC_ID_VP8; - decodedBuffer_ = (unsigned char*) malloc( - info.videoCodec.width * info.videoCodec.height * 3 / 2); - unpackagedBuffer_ = (unsigned char*) malloc(UNPACKAGED_BUFFER_SIZE); - memset(decodedBuffer_, 0, - info.videoCodec.width * info.videoCodec.height * 3 / 2); - this->initVideoDecoder(); - this->initVideoUnpackager(); - } - - return 0; -} - -int InputProcessor::receiveAudioData(char* buf, int len) { - return 3; -} -int InputProcessor::receiveVideoData(char* buf, int len) { - if (videoUnpackager && videoDecoder) { - printf("elo\n"); - int ret = unpackageVideo(reinterpret_cast(buf), len, - unpackagedBuffer_, &gotUnpackagedFrame_); - if (ret < 0) - return 0; - upackagedSize_ += ret; - unpackagedBuffer_ += ret; - if (gotUnpackagedFrame_) { - unpackagedBuffer_ -= upackagedSize_; - printf("Tengo un frame desempaquetado!! Size = %d\n", - upackagedSize_); - int c; - int gotDecodedFrame = 0; - - c = this->decodeVideo(unpackagedBuffer_, upackagedSize_, - decodedBuffer_, - mediaInfo.videoCodec.width * mediaInfo.videoCodec.height * 3 - / 2, &gotDecodedFrame); - - upackagedSize_ = 0; - gotUnpackagedFrame_ = 0; - printf("Bytes dec = %d\n", c); - if (gotDecodedFrame && c > 0) { - printf("Tengo un frame decodificado!!\n"); - gotDecodedFrame = 0; - rawReceiver_->receiveRawData(decodedBuffer_, c); - } - } - return 3; - } - return 7; -} - -bool InputProcessor::initAudioDecoder() { - - aDecoder = avcodec_find_decoder(mediaInfo.audioCodec.codec); - if (!aDecoder) { - printf("Decoder de audio no encontrado"); - return false; - } - - aDecoderContext = avcodec_alloc_context3(aDecoder); - if (!aDecoderContext) { - printf("Error de memoria en decoder de audio"); - return false; - } - - aDecoderContext->sample_fmt = AV_SAMPLE_FMT_S16; - aDecoderContext->bit_rate = mediaInfo.audioCodec.bitRate; - aDecoderContext->sample_rate = mediaInfo.audioCodec.sampleRate; - aDecoderContext->channels = 1; - - if (avcodec_open2(aDecoderContext, aDecoder, NULL) < 0) { - printf("Error al abrir el decoder de audio"); - return false; - } - - audioDecoder = 1; - return true; - -} - -bool InputProcessor::initVideoDecoder() { - - videoCodecInfo& videoCodec = mediaInfo.videoCodec; - vDecoder = avcodec_find_decoder(videoCodec.codec); - if (!vDecoder) { - printf("Decoder de vídeo no encontrado"); - return false; - } - - vDecoderContext = avcodec_alloc_context3(vDecoder); - if (!vDecoderContext) { - printf("Error de memoria en decoder de vídeo"); - return false; - } - - vDecoderContext->width = videoCodec.width; - vDecoderContext->height = videoCodec.height; - - if (avcodec_open2(vDecoderContext, vDecoder, NULL) < 0) { - printf("Error al abrir el decoder de vídeo"); - return false; - } - - dPicture = avcodec_alloc_frame(); - if (!dPicture) { - printf("Error de memoria en frame del decoder de vídeo"); - return false; - } - - videoDecoder = 1; - return true; -} - -bool InputProcessor::initAudioUnpackager() { - - if (mediaInfo.proccessorType != RTP_ONLY) { - aInputFormatContext = avformat_alloc_context(); - if (!aInputFormatContext) { - printf("Memory Error al inicializar audioUnpackager"); - return false; - } - - aInputFormat = av_find_input_format("rtp"); - if (aInputFormat == NULL) { - printf("Could not guess format al inicializar audioUnpackager"); - return false; - } - - aInputFormatContext->iformat = aInputFormat; - - audioUnpackager = 1; - } - return true; -} - -bool InputProcessor::initVideoUnpackager() { - if (mediaInfo.proccessorType == RTP_ONLY) { - printf("Unpackaging from RTP\n"); - } else { - - } - videoUnpackager = 1; - return true; - -} - -int InputProcessor::decodeAudio(unsigned char* inBuff, int inBuffLen, - unsigned char* outBuff) { - - if (audioDecoder == 0) { - printf("No se han inicializado los parámetros del audioDecoder\n"); - return -1; - } - - AVPacket avpkt; - int outSize; - int decSize = 0; - int len = -1; - uint8_t *decBuff = (uint8_t*) malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE); - - av_init_packet(&avpkt); - avpkt.data = (unsigned char*) inBuff; - avpkt.size = inBuffLen; - - while (avpkt.size > 0) { - - outSize = AVCODEC_MAX_AUDIO_FRAME_SIZE; - - //Puede fallar. Cogido de libavcodec/utils.c del paso de avcodec_decode_audio3 a avcodec_decode_audio4 - //avcodec_decode_audio3(aDecoderContext, (short*)decBuff, &outSize, &avpkt); - - AVFrame frame; - int got_frame = 0; - - aDecoderContext->get_buffer = avcodec_default_get_buffer; - aDecoderContext->release_buffer = avcodec_default_release_buffer; - - len = avcodec_decode_audio4(aDecoderContext, &frame, &got_frame, - &avpkt); - - if (len >= 0 && got_frame) { - int plane_size; - //int planar = av_sample_fmt_is_planar(aDecoderContext->sample_fmt); - int data_size = av_samples_get_buffer_size(&plane_size, - aDecoderContext->channels, frame.nb_samples, - aDecoderContext->sample_fmt, 1); - if (outSize < data_size) { - printf( - "output buffer size is too small for the current frame\n"); - return AVERROR(EINVAL); - } - - memcpy(decBuff, frame.extended_data[0], plane_size); - - /* Si hay más de un canal - if (planar && aDecoderContext->channels > 1) { - uint8_t *out = ((uint8_t *)decBuff) + plane_size; - for (int ch = 1; ch < aDecoderContext->channels; ch++) { - memcpy(out, frame.extended_data[ch], plane_size); - out += plane_size; - } - } - */ - - outSize = data_size; - } else { - outSize = 0; - } - - if (len < 0) { - printf("Error al decodificar audio\n"); - free(decBuff); - return -1; - } - - avpkt.size -= len; - avpkt.data += len; - - if (outSize <= 0) { - continue; - } + InputProcessor::InputProcessor() { + + audioDecoder = 0; + videoDecoder = 0; + + audioUnpackager = 0; + videoUnpackager = 0; + gotUnpackagedFrame_ = false; + upackagedSize_ = 0; + decodedBuffer_ = NULL; + + avcodec_register_all(); + av_register_all(); + } + + InputProcessor::~InputProcessor() { + if (audioDecoder == 1) { + avcodec_close(aDecoderContext); + av_free(aDecoderContext); + } + + if (videoDecoder == 1) { + avcodec_close(vDecoderContext); + av_free(vDecoderContext); + av_free(dPicture); + } + if (decodedBuffer_ != NULL) { + free(decodedBuffer_); + } + } + + int InputProcessor::init(const MediaInfo& info, RawDataReceiver* receiver) { + this->mediaInfo = info; + this->rawReceiver_ = receiver; + if (mediaInfo.hasVideo) { + mediaInfo.videoCodec.codec = CODEC_ID_VP8; + decodedBuffer_ = (unsigned char*) malloc( + info.videoCodec.width * info.videoCodec.height * 3 / 2); + unpackagedBuffer_ = (unsigned char*) malloc(UNPACKAGED_BUFFER_SIZE); + this->initVideoDecoder(); + this->initVideoUnpackager(); + } + if (mediaInfo.hasAudio) { + printf("Init AUDIO processor\n"); + mediaInfo.audioCodec.codec =CODEC_ID_PCM_MULAW; + decodedAudioBuffer_ = (unsigned char*) malloc(UNPACKAGED_BUFFER_SIZE); + unpackagedAudioBuffer_ = (unsigned char*) malloc( + UNPACKAGED_BUFFER_SIZE); + this->initAudioDecoder(); + this->initAudioUnpackager(); + } + return 0; + } + + int InputProcessor::receiveAudioData(char* buf, int len) { + if (audioDecoder && audioUnpackager) { + printf("Decoding audio\n"); + int unp = unpackageAudio((unsigned char*) buf, len, + unpackagedAudioBuffer_); + int a = decodeAudio(unpackagedAudioBuffer_, unp, decodedAudioBuffer_); + printf("DECODED AUDIO a %d\n", a); + RawDataPacket p; + p.data = decodedAudioBuffer_; + p.type = AUDIO; + p.length = a; + rawReceiver_->receiveRawData(p); + } + } + int InputProcessor::receiveVideoData(char* buf, int len) { + if (videoUnpackager && videoDecoder) { + int ret = unpackageVideo(reinterpret_cast(buf), len, + unpackagedBuffer_, &gotUnpackagedFrame_); + if (ret < 0) + return 0; + upackagedSize_ += ret; + unpackagedBuffer_ += ret; + if (gotUnpackagedFrame_) { + unpackagedBuffer_ -= upackagedSize_; + printf("Tengo un frame desempaquetado!! Size = %d\n", + upackagedSize_); + int c; + int gotDecodedFrame = 0; + + c = this->decodeVideo(unpackagedBuffer_, upackagedSize_, + decodedBuffer_, + mediaInfo.videoCodec.width * mediaInfo.videoCodec.height * 3 + / 2, &gotDecodedFrame); + + upackagedSize_ = 0; + gotUnpackagedFrame_ = 0; + printf("Bytes dec = %d\n", c); + if (gotDecodedFrame && c > 0) { + printf("Tengo un frame decodificado!!\n"); + gotDecodedFrame = 0; + RawDataPacket p; + p.data = decodedBuffer_; + p.length = c; + p.type = VIDEO; + rawReceiver_->receiveRawData(p); + } + } + return 1; + } + return 1; + } + + bool InputProcessor::initAudioDecoder() { + + aDecoder = avcodec_find_decoder(mediaInfo.audioCodec.codec); + if (!aDecoder) { + printf("Decoder de audio no encontrado"); + return false; + } + + aDecoderContext = avcodec_alloc_context3(aDecoder); + if (!aDecoderContext) { + printf("Error de memoria en decoder de audio"); + return false; + } + + aDecoderContext->sample_fmt = AV_SAMPLE_FMT_S16; + aDecoderContext->bit_rate = mediaInfo.audioCodec.bitRate; + aDecoderContext->sample_rate = mediaInfo.audioCodec.sampleRate; + aDecoderContext->channels = 1; + + if (avcodec_open2(aDecoderContext, aDecoder, NULL) < 0) { + printf("Error al abrir el decoder de audio\n"); + exit(0); + return false; + } + printf("EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE %d\n", aDecoderContext->frame_size); + audioDecoder = 1; + return true; + + } + + bool InputProcessor::initVideoDecoder() { + + videoCodecInfo& videoCodec = mediaInfo.videoCodec; + vDecoder = avcodec_find_decoder(videoCodec.codec); + if (!vDecoder) { + printf("Decoder de vídeo no encontrado"); + return false; + } + + vDecoderContext = avcodec_alloc_context3(vDecoder); + if (!vDecoderContext) { + printf("Error de memoria en decoder de vídeo"); + return false; + } + + vDecoderContext->width = videoCodec.width; + vDecoderContext->height = videoCodec.height; + + if (avcodec_open2(vDecoderContext, vDecoder, NULL) < 0) { + printf("Error al abrir el decoder de vídeo"); + return false; + } + + dPicture = avcodec_alloc_frame(); + if (!dPicture) { + printf("Error de memoria en frame del decoder de vídeo"); + return false; + } + + videoDecoder = 1; + return true; + } + + bool InputProcessor::initAudioUnpackager() { + audioUnpackager = 1; + return true; + } + + bool InputProcessor::initVideoUnpackager() { + videoUnpackager = 1; + return true; + + } + + int InputProcessor::decodeAudio(unsigned char* inBuff, int inBuffLen, + unsigned char* outBuff) { + + if (audioDecoder == 0) { + printf("No se han inicializado los parámetros del audioDecoder\n"); + return -1; + } + + AVPacket avpkt; + int outSize; + int decSize = 0; + int len = -1; + uint8_t *decBuff = (uint8_t*) malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE); + + av_init_packet(&avpkt); + avpkt.data = (unsigned char*) inBuff; + avpkt.size = inBuffLen; + + while (avpkt.size > 0) { + + outSize = AVCODEC_MAX_AUDIO_FRAME_SIZE; + + //Puede fallar. Cogido de libavcodec/utils.c del paso de avcodec_decode_audio3 a avcodec_decode_audio4 + //avcodec_decode_audio3(aDecoderContext, (short*)decBuff, &outSize, &avpkt); + + AVFrame frame; + int got_frame = 0; + + aDecoderContext->get_buffer = avcodec_default_get_buffer; + aDecoderContext->release_buffer = avcodec_default_release_buffer; + + len = avcodec_decode_audio4(aDecoderContext, &frame, &got_frame, + &avpkt); + if (len >= 0 && got_frame) { + int plane_size; + //int planar = av_sample_fmt_is_planar(aDecoderContext->sample_fmt); + int data_size = av_samples_get_buffer_size(&plane_size, + aDecoderContext->channels, frame.nb_samples, + aDecoderContext->sample_fmt, 1); + if (outSize < data_size) { + printf( + "output buffer size is too small for the current frame\n"); + return AVERROR(EINVAL); + } + + memcpy(decBuff, frame.extended_data[0], plane_size); + + /* Si hay más de un canal + if (planar && aDecoderContext->channels > 1) { + uint8_t *out = ((uint8_t *)decBuff) + plane_size; + for (int ch = 1; ch < aDecoderContext->channels; ch++) { + memcpy(out, frame.extended_data[ch], plane_size); + out += plane_size; + } + } + */ + outSize = data_size; + } else { + outSize = 0; + } + + if (len < 0) { + printf("Error al decodificar audio\n"); + free(decBuff); + return -1; + } + + avpkt.size -= len; + avpkt.data += len; + + if (outSize <= 0) { + continue; + } + + memcpy(outBuff, decBuff, outSize); + outBuff += outSize; + decSize += outSize; + } + + free(decBuff); + + if (outSize <= 0) { + printf("Error de decodificación de audio debido a tamaño incorrecto"); + return -1; + } + + return decSize; + + } + + int InputProcessor::decodeVideo(unsigned char* inBuff, int inBuffLen, + unsigned char* outBuff, int outBuffLen, int* gotFrame) { + + if (videoDecoder == 0) { + printf("No se han inicializado los parámetros del videoDecoder"); + return -1; + } + + *gotFrame = 0; + + AVPacket avpkt; + av_init_packet(&avpkt); + + avpkt.data = inBuff; + avpkt.size = inBuffLen; + + int got_picture; + int len; + + while (avpkt.size > 0) { + + len = avcodec_decode_video2(vDecoderContext, dPicture, &got_picture, + &avpkt); + + if (len < 0) { + printf("Error al decodificar frame de vídeo\n"); + return -1; + } + + if (got_picture) { + *gotFrame = 1; + goto decoding; + } + avpkt.size -= len; + avpkt.data += len; + } + + if (!got_picture) { + printf("Aún no tengo frame"); + return -1; + } + +decoding: + + // int outSize = vDecoderContext->height * vDecoderContext->width; + int outSize = mediaInfo.videoCodec.height * mediaInfo.videoCodec.width; + + if (outBuffLen < (outSize * 3 / 2)) { + printf("No se ha rellenado el buffer??? outBuffLen = %d\n", outBuffLen); + return outSize * 3 / 2; + } + + unsigned char *lum = outBuff; + unsigned char *cromU = outBuff + outSize; + unsigned char *cromV = outBuff + outSize + outSize / 4; + + unsigned char *src = NULL; + int src_linesize, dst_linesize; + + src_linesize = dPicture->linesize[0]; + dst_linesize = vDecoderContext->width; + src = dPicture->data[0]; - memcpy(outBuff, decBuff, outSize); - outBuff += outSize; - decSize += outSize; - } - - free(decBuff); - - if (outSize <= 0) { - printf("Error de decodificación de audio debido a tamaño incorrecto"); - return -1; - } + for (int i = vDecoderContext->height; i > 0; i--) { + memcpy(lum, src, dst_linesize); + lum += dst_linesize; + src += src_linesize; + } - return decSize; - -} - -int InputProcessor::decodeVideo(unsigned char* inBuff, int inBuffLen, - unsigned char* outBuff, int outBuffLen, int* gotFrame) { - - if (videoDecoder == 0) { - printf("No se han inicializado los parámetros del videoDecoder"); - return -1; - } - - *gotFrame = 0; - - AVPacket avpkt; - av_init_packet(&avpkt); - - avpkt.data = inBuff; - avpkt.size = inBuffLen; - - int got_picture; - int len; - - while (avpkt.size > 0) { - - len = avcodec_decode_video2(vDecoderContext, dPicture, &got_picture, - &avpkt); - - if (len < 0) { - printf("Error al decodificar frame de vídeo\n"); - return -1; - } - - if (got_picture) { - *gotFrame = 1; - goto decoding; - } - avpkt.size -= len; - avpkt.data += len; - } - - if (!got_picture) { - printf("Aún no tengo frame"); - return -1; - } - - decoding: - -// int outSize = vDecoderContext->height * vDecoderContext->width; - int outSize = mediaInfo.videoCodec.height * mediaInfo.videoCodec.width; - - if (outBuffLen < (outSize * 3 / 2)) { - printf("No se ha rellenado el buffer??? outBuffLen = %d\n", outBuffLen); - return outSize * 3 / 2; - } - - unsigned char *lum = outBuff; - unsigned char *cromU = outBuff + outSize; - unsigned char *cromV = outBuff + outSize + outSize / 4; - - unsigned char *src = NULL; - int src_linesize, dst_linesize; - - src_linesize = dPicture->linesize[0]; - dst_linesize = vDecoderContext->width; - src = dPicture->data[0]; - - for (int i = vDecoderContext->height; i > 0; i--) { - memcpy(lum, src, dst_linesize); - lum += dst_linesize; - src += src_linesize; - } - - src_linesize = dPicture->linesize[1]; - dst_linesize = vDecoderContext->width / 2; - src = dPicture->data[1]; - - for (int i = vDecoderContext->height / 2; i > 0; i--) { - memcpy(cromU, src, dst_linesize); - cromU += dst_linesize; - src += src_linesize; - } - - src_linesize = dPicture->linesize[2]; - dst_linesize = vDecoderContext->width / 2; - src = dPicture->data[2]; - - for (int i = vDecoderContext->height / 2; i > 0; i--) { - memcpy(cromV, src, dst_linesize); - cromV += dst_linesize; - src += src_linesize; - } - av_free_packet(&avpkt); - - return outSize * 3 / 2; -} - -int InputProcessor::unpackageAudio(unsigned char* inBuff, int inBuffLen, - unsigned char* outBuff) { - - /* - if (audioUnpackager == 0) { - printf("No se ha inicializado el codec de input audio RTP"); - return -1; - } - AVIOContext *c = avio_alloc_context((unsigned char*)inBuff, inBuffLen, 0, NULL, NULL, NULL, NULL); - aInputFormatContext->pb = c; - //aInputFormatContext->flags = AVFMT_NOFILE; - aInputFormatContext->flags = AVFMT_FLAG_CUSTOM_IO; - - if (avformat_find_stream_info(aInputFormatContext, NULL) < 0) { - return -1; - } - - AVPacket pkt; - av_init_packet(&pkt); - - //aInputFormatContext->iformat->read_packet(aInputFormatContext, &pkt); - av_read_frame(aInputFormatContext, &pkt); - - outBuff = (char*)pkt.data; - int se = pkt.size; - - av_free_packet(&pkt); - av_free(c); - - return se; - */ - int l = inBuffLen - RTP_HEADER_LEN; - inBuff += RTP_HEADER_LEN; - memcpy(outBuff, inBuff, l); - - return l; -} - -int InputProcessor::unpackageVideo(unsigned char* inBuff, int inBuffLen, - unsigned char* outBuff, int *gotFrame) { - - if (videoUnpackager == 0) { - printf("Unpackager not correctly initialized"); - return -1; - } - - int inBuffOffset = 0; - *gotFrame = 0; - if (mediaInfo.proccessorType == RTP_ONLY) { - rtpHeader* head = (rtpHeader*) inBuff; - - int sec = ntohs(head->seqnum); - int ssrc = ntohl(head->ssrc); - unsigned long time = ntohl(head->timestamp); - printf("PT %d, ssrc %u, extension %d\n", head->payloadtype, ssrc, - head->extension); - if (ssrc != 55543 /*&& head->payloadtype!=101*/) { - return -1; - } - if (head->payloadtype != 100) { - printf("EEEEEEEEEEEEEEOOOOOOOOOOOOOOOOOOOOOOOO %d\n\n\n", - head->payloadtype); - return -1; - } - int extoffset = 0; - if (head->extension) { - extoffset++; - extoffset += ntohs(head->extLength); - extoffset = extoffset * 4; - unsigned int extId = ntohs(head->extId); -// printf("There is extension length: %u , id: %u\n", extoffset, -// extId); - } - int l = inBuffLen - RTP_HEADER_LEN; - l -= extoffset; - inBuffOffset += RTP_HEADER_LEN; - inBuffOffset += extoffset; - vp8RtpHeader* vphead = (vp8RtpHeader*) &inBuff[inBuffOffset]; -// printf("MIO X: %u , N:%u PartID %u\n", vphead->X, vphead->N, -// vphead->partId); - - erizo::RTPPayloadVP8* parsed = pars.parseVP8( - (unsigned char*) &inBuff[inBuffOffset], l); -// printf("l : %d, parsedDatalength %u\n", l, parsed->dataLength); -// l--; -// inBuff++; -// memcpy(outBuff, inBuff, parsed->dataLength); - memcpy(outBuff, parsed->data, parsed->dataLength); - if (head->marker) { -// printf("Marker\n"); - *gotFrame = 1; - } - -// return l; - return parsed->dataLength; - } else { - - if (avformat_find_stream_info(vInputFormatContext, NULL) < 0) { - return -1; - } - - AVPacket pkt; - av_init_packet(&pkt); - - //aInputFormatContext->iformat->read_packet(aInputFormatContext, &pkt); - - int p = av_read_frame(vInputFormatContext, &pkt); - printf("Leido frame %d\n", p); - - outBuff = pkt.data; - - int se = pkt.size; - - av_free_packet(&pkt); - - return se; - - } - -} - -OutputProcessor::OutputProcessor() { - - audioCoder = 0; - videoCoder = 0; - - audioPackager = 0; - videoPackager = 0; - timestamp_ = 0; - - encodedBuffer_ = NULL; - packagedBuffer_ = NULL; - - avcodec_register_all(); - av_register_all(); -} - -OutputProcessor::~OutputProcessor() { - - if (audioCoder == 1) { - avcodec_close(aCoderContext); - av_free(aCoderContext); - } - - if (videoCoder == 1) { - avcodec_close(vCoderContext); - av_free(vCoderContext); - av_free(cPicture); - } - if (encodedBuffer_) { - free(encodedBuffer_); - } - if (packagedBuffer_) { - free(packagedBuffer_); - } - if (rtpBuffer_) { - free(rtpBuffer_); - } -} - -int OutputProcessor::init(const MediaInfo& info, RTPDataReceiver* rtpReceiver) { - this->mediaInfo = info; - this->rtpReceiver_ = rtpReceiver; - - encodedBuffer_ = (unsigned char*) malloc(UNPACKAGED_BUFFER_SIZE); - packagedBuffer_ = (unsigned char*) malloc(PACKAGED_BUFFER_SIZE); - rtpBuffer_ = (unsigned char*) malloc(PACKAGED_BUFFER_SIZE); - - this->mediaInfo.videoCodec.codec = CODEC_ID_VP8; - if (!this->initVideoCoder()) { - printf("Fallo aqui\n"); - exit(0); - } - this->initVideoPackager(); - return 0; -} - -void OutputProcessor::receiveRawData(unsigned char* data, int len) { - AVPacket pkt; - av_init_packet(&pkt); - pkt.data = encodedBuffer_; - pkt.size = UNPACKAGED_BUFFER_SIZE; - - int a = this->encodeVideo(data, len, &pkt); - if (a > 0) - int b = this->packageVideo(&pkt, packagedBuffer_); - av_free_packet(&pkt); -} - -bool OutputProcessor::initAudioCoder() { - - aCoder = avcodec_find_encoder(mediaInfo.audioCodec.codec); - if (!aCoder) { - printf("Encoder de audio no encontrado"); - return false; - } - - aCoderContext = avcodec_alloc_context3(aCoder); - if (!aCoderContext) { - printf("Error de memoria en coder de audio"); - return false; - } - - aCoderContext->sample_fmt = AV_SAMPLE_FMT_S16; - aCoderContext->bit_rate = mediaInfo.audioCodec.bitRate; - aCoderContext->sample_rate = mediaInfo.audioCodec.sampleRate; - aCoderContext->channels = 1; - - if (avcodec_open2(aCoderContext, aCoder, NULL) < 0) { - printf("Error al abrir el coder de audio"); - return false; - } - - audioCoder = 1; - return true; -} - -bool OutputProcessor::initVideoCoder() { - - vCoder = avcodec_find_encoder(mediaInfo.videoCodec.codec); - if (!vCoder) { - printf("Encoder de vídeo no encontrado"); - return false; - } - - vCoderContext = avcodec_alloc_context3(vCoder); - if (!vCoderContext) { - printf("Error de memoria en coder de vídeo"); - return false; - } - - vCoderContext->bit_rate = mediaInfo.videoCodec.bitRate; - vCoderContext->rc_min_rate = mediaInfo.videoCodec.bitRate; // - vCoderContext->rc_max_rate = mediaInfo.videoCodec.bitRate; // VPX_CBR - vCoderContext->qmin = 8; - vCoderContext->qmax = 56; // rc_quantifiers -// vCoderContext->frame_skip_threshold = 30; - vCoderContext->rc_buffer_aggressivity = 1; - vCoderContext->rc_buffer_size = vCoderContext->bit_rate; - vCoderContext->rc_initial_buffer_occupancy = vCoderContext->bit_rate / 2; - vCoderContext->width = mediaInfo.videoCodec.width; - vCoderContext->height = mediaInfo.videoCodec.height; - vCoderContext->pix_fmt = PIX_FMT_YUV420P; - vCoderContext->time_base = (AVRational) {1, 90000}; - vCoderContext->sample_aspect_ratio = - (AVRational) {mediaInfo.videoCodec.width,mediaInfo.videoCodec.height}; - - if (avcodec_open2(vCoderContext, vCoder, NULL) < 0) { - printf("Error al abrir el decoder de vídeo"); - return false; - } - - cPicture = avcodec_alloc_frame(); - if (!cPicture) { - printf("Error de memoria en frame del coder de vídeo"); - return false; - } - - videoCoder = 1; - printf("videoCoder configured successfully %d x %d\n", vCoderContext->width, - vCoderContext->height); - return true; -} - -bool OutputProcessor::initAudioPackager() { - - aOutputFormatContext = avformat_alloc_context(); - if (!aOutputFormatContext) { - printf("Memory Error al inicializar audioPackager"); - return false; - } - - aOutputFormat = av_guess_format("rtp", NULL, NULL); - if (aOutputFormat == NULL) { - printf("Could not guess format al inicializar audioPackager"); - return false; - } - - aOutputFormatContext->oformat = aOutputFormat; - aOutputFormat->audio_codec = mediaInfo.audioCodec.codec; - - audioPackager = 1; - return true; -} - -bool OutputProcessor::initVideoPackager() { - if (mediaInfo.proccessorType == RTP_ONLY) { - printf("RTP ONLY OutputProcessor\n"); - seqnum_ = 0; - } else { - printf("FILE ONLY OutputProcessor: %s\n", mediaInfo.url.c_str()); - vOutputFormatContext = avformat_alloc_context(); - if (!vOutputFormatContext) { - printf("videoPackager: Error creating avformat context \n"); - return false; - } - - vOutputFormat = av_guess_format(NULL, mediaInfo.url.c_str(), NULL); - if (vOutputFormat == NULL) { - printf("videoPackager: Could not guess format"); - return false; - } - - vOutputFormatContext->oformat = vOutputFormat; - vOutputFormat->video_codec = mediaInfo.videoCodec.codec; - - } - videoPackager = 1; - return true; -} - -int OutputProcessor::packageAudio(unsigned char* inBuff, int inBuffLen, - unsigned char* outBuff) { - - if (audioPackager == 0) { - printf("No se ha inicializado el codec de output audio RTP"); - return -1; - } - - AVIOContext *c = avio_alloc_context((unsigned char*) outBuff, 2000, 1, NULL, - NULL, NULL, NULL); - -// aOutputFormatContext->pb = c; -// aOutputFormatContext->flags = AVFMT_NOFILE; - - AVPacket pkt; - av_init_packet(&pkt); - pkt.data = (unsigned char*) inBuff; - pkt.size = inBuffLen; - - int ret = av_write_frame(aOutputFormatContext, &pkt); - - av_free_packet(&pkt); - av_free(c); - - return ret; -} - -int OutputProcessor::packageVideo(AVPacket* pkt, unsigned char* outBuff) { - if (videoPackager == 0) { - printf("No se ha inicailizado el codec de output vídeo RTP"); - return -1; - } - - if (mediaInfo.proccessorType == RTP_ONLY) { - -// return l; - printf("To packetize %u\n", pkt->size); - if (pkt->size <= 0) - return -1; - RtpFragmenter frag(pkt->data, pkt->size); - bool lastFrame = false; - unsigned int outlen = 0; - timeval time; - gettimeofday(&time, NULL); - long millis = (time.tv_sec * 1000) + (time.tv_usec / 1000); - timestamp_ += 90000 / mediaInfo.videoCodec.frameRate; - - do { - outlen = 0; - frag.getPacket(outBuff, &outlen, &lastFrame); - unsigned int l = outlen + RTP_HEADER_LEN; -// memset(rtpBuffer_,0,PACKAGED_BUFFER_SIZE); - rtpHeader * head = (rtpHeader*) rtpBuffer_; - - head->version = 2; //v = 2 - head->extension = 0; - head->marker = lastFrame ? 1 : 0; - head->padding = 0; - head->cc = 0; - head->seqnum = htons(seqnum_++); - head->timestamp = htonl(millis * 90); //pkt->pts; -// head->timestamp = htonl(timestamp_); - head->ssrc = htonl(55543); - head->payloadtype = 100; - //rtpBuffer_ += RTP_HEADER_LEN; - printf("outlen to write %u, lastframe %d\n", outlen, lastFrame, - pkt->dts); - memcpy(&rtpBuffer_[RTP_HEADER_LEN], outBuff, outlen); -// sink_->sendData(rtpBuffer_, l); - rtpReceiver_->receiveRtpData(rtpBuffer_, l); - } while (!lastFrame); - - } else { -// AVIOContext *c = avio_alloc_context((unsigned char*) outBuff, l, 1, -// NULL, NULL, NULL, NULL); -// vOutputFormatContext->pb = c; -// vOutputFormatContext->flags = AVFMT_NOFILE; - - pkt->stream_index = 0; - int ret = av_write_frame(vOutputFormatContext, pkt); - - //av_free_packet(&pkt); -// av_free(c); - } - return 0; -} - -int OutputProcessor::encodeAudio(unsigned char* inBuff, int nSamples, - unsigned char* outBuff) { - - if (audioCoder == 0) { - printf("No se han inicializado los parámetros del audioCoder"); - return -1; - } - - //Puede fallar. Revisar samples. Cogido de libavcodec/utils.c del paso de avcodec_encode_audio a avcodec_encode_audio2 - //avcodec_encode_audio(aCoderContext, (unsigned char*)outBuff, nSamples*2, (short*)inBuff); - - AVPacket pkt; - AVFrame frame0; - AVFrame *frame; - int ret, samples_size, got_packet; - - av_init_packet(&pkt); - pkt.data = (unsigned char*) inBuff; - pkt.size = nSamples * 2; - - frame = &frame0; - avcodec_get_frame_defaults(frame); - - frame->nb_samples = nSamples; - - samples_size = av_samples_get_buffer_size(NULL, aCoderContext->channels, - frame->nb_samples, aCoderContext->sample_fmt, 1); - - if ((ret = avcodec_fill_audio_frame(frame, aCoderContext->channels, - aCoderContext->sample_fmt, (const uint8_t *) inBuff, samples_size, - 1))) - return ret; - - frame->pts = AV_NOPTS_VALUE; - //aCoderContext->internal->sample_count += frame->nb_samples; - - got_packet = 0; - - ret = avcodec_encode_audio2(aCoderContext, &pkt, frame, &got_packet); - - if (!ret && got_packet && aCoderContext->coded_frame) { - aCoderContext->coded_frame->pts = pkt.pts; - aCoderContext->coded_frame->key_frame = !!(pkt.flags & AV_PKT_FLAG_KEY); - } - //ff_packet_free_side_data(&pkt); - - if (frame && frame->extended_data != frame->data) - av_freep(&frame->extended_data); - - return ret; - -} - -int OutputProcessor::encodeVideo(unsigned char* inBuff, int inBuffLen, - AVPacket* pkt) { - if (videoCoder == 0) { - printf("No se han inicializado los parámetros del videoCoder"); - return -1; - } - int size = vCoderContext->width * vCoderContext->height; - printf("vCoderContext width %d\n", vCoderContext->width); - - cPicture->pts = AV_NOPTS_VALUE; - cPicture->data[0] = (unsigned char*) inBuff; - cPicture->data[1] = (unsigned char*) inBuff + size; - cPicture->data[2] = (unsigned char*) inBuff + size + size / 4; - cPicture->linesize[0] = vCoderContext->width; - cPicture->linesize[1] = vCoderContext->width / 2; - cPicture->linesize[2] = vCoderContext->width / 2; - - int ret = 0; - int got_packet = 0; - printf( - "Before encoding inBufflen %d, size %d, codecontext width %d pkt->size%d\n", - inBuffLen, size, vCoderContext->width, pkt->size); - ret = avcodec_encode_video2(vCoderContext, pkt, cPicture, &got_packet); - printf("Encoded video size %u, ret %d, got_packet %d, pts %lld, dts %lld\n", - pkt->size, ret, got_packet, pkt->pts, pkt->dts); - if (!ret && got_packet && vCoderContext->coded_frame) { - vCoderContext->coded_frame->pts = pkt->pts; - vCoderContext->coded_frame->key_frame = - !!(pkt->flags & AV_PKT_FLAG_KEY); - } - /* free any side data since we cannot return it */ -// if (pkt.side_data_elems > 0) { -// int i; -// for (i = 0; i < pkt.side_data_elems; i++) -// av_free(pkt.side_data[i].data); -// av_freep(&pkt.side_data); -// pkt.side_data_elems = 0; -// } - return ret ? ret : pkt->size; -} + src_linesize = dPicture->linesize[1]; + dst_linesize = vDecoderContext->width / 2; + src = dPicture->data[1]; + + for (int i = vDecoderContext->height / 2; i > 0; i--) { + memcpy(cromU, src, dst_linesize); + cromU += dst_linesize; + src += src_linesize; + } + + src_linesize = dPicture->linesize[2]; + dst_linesize = vDecoderContext->width / 2; + src = dPicture->data[2]; + + for (int i = vDecoderContext->height / 2; i > 0; i--) { + memcpy(cromV, src, dst_linesize); + cromV += dst_linesize; + src += src_linesize; + } + av_free_packet(&avpkt); + + return outSize * 3 / 2; + } + + int InputProcessor::unpackageAudio(unsigned char* inBuff, int inBuffLen, + unsigned char* outBuff) { + + int l = inBuffLen - RTPHeader::MIN_SIZE; + memcpy(outBuff, &inBuff[RTPHeader::MIN_SIZE], l); + + return l; + } + + int InputProcessor::unpackageVideo(unsigned char* inBuff, int inBuffLen, + unsigned char* outBuff, int *gotFrame) { + + if (videoUnpackager == 0) { + printf("Unpackager not correctly initialized"); + return -1; + } + + int inBuffOffset = 0; + *gotFrame = 0; + RTPHeader* head = reinterpret_cast(inBuff); + + + printf("PT %d, ssrc %u, extension %d\n", head->getPayloadType(), head->getSSRC(), + head->getExtension()); + if ( head->getSSRC() != 55543 /*&& head->payloadtype!=101*/) { + return -1; + } + if (head->getPayloadType() != 100) { + return -1; + } + + printf("RTP header length: %d", head->getHeaderLength()); //Should include extensions + int l = inBuffLen - head->getHeaderLength(); + inBuffOffset+=head->getHeaderLength(); + + erizo::RTPPayloadVP8* parsed = pars.parseVP8( + (unsigned char*) &inBuff[inBuffOffset], l); + memcpy(outBuff, parsed->data, parsed->dataLength); + if (head->getMarker()) { + printf("Marker\n"); + *gotFrame = 1; + } + return parsed->dataLength; + + } + + OutputProcessor::OutputProcessor() { + + audioCoder = 0; + videoCoder = 0; + + audioPackager = 0; + videoPackager = 0; + timestamp_ = 0; + + encodedBuffer_ = NULL; + packagedBuffer_ = NULL; + + avcodec_register_all(); + av_register_all(); + } + + OutputProcessor::~OutputProcessor() { + + if (audioCoder == 1) { + avcodec_close(aCoderContext); + av_free(aCoderContext); + } + + if (videoCoder == 1) { + avcodec_close(vCoderContext); + av_free(vCoderContext); + av_free(cPicture); + } + if (encodedBuffer_) { + free(encodedBuffer_); + } + if (packagedBuffer_) { + free(packagedBuffer_); + } + if (rtpBuffer_) { + free(rtpBuffer_); + } + } + + int OutputProcessor::init(const MediaInfo& info, RTPDataReceiver* rtpReceiver) { + this->mediaInfo = info; + this->rtpReceiver_ = rtpReceiver; + + encodedBuffer_ = (unsigned char*) malloc(UNPACKAGED_BUFFER_SIZE); + packagedBuffer_ = (unsigned char*) malloc(PACKAGED_BUFFER_SIZE); + rtpBuffer_ = (unsigned char*) malloc(PACKAGED_BUFFER_SIZE); + + if (mediaInfo.hasVideo) { + this->mediaInfo.videoCodec.codec = CODEC_ID_VP8; + if (!this->initVideoCoder()) { + printf("Fallo aqui\n"); + } + this->initVideoPackager(); + } + if (mediaInfo.hasAudio) { + printf("Init AUDIO processor\n"); + mediaInfo.audioCodec.codec = CODEC_ID_MP2;//CODEC_ID_PCM_MULAW; + mediaInfo.audioCodec.sampleRate= 44100; + mediaInfo.audioCodec.bitRate = 64000; + encodedAudioBuffer_ = (unsigned char*) malloc(UNPACKAGED_BUFFER_SIZE); + packagedAudioBuffer_ = (unsigned char*) malloc(UNPACKAGED_BUFFER_SIZE); + this->initAudioCoder(); + this->initAudioPackager(); + + } + + return 0; + } + + + void OutputProcessor::receiveRawData(RawDataPacket& packet) { + AVPacket pkt; + av_init_packet(&pkt); + pkt.data = encodedBuffer_; + pkt.size = UNPACKAGED_BUFFER_SIZE; + if (packet.type == VIDEO) { + int a = this->encodeVideo(packet.data, packet.length, &pkt); + if (a > 0) + int b = this->packageVideo(&pkt, packagedBuffer_); + } else { + int a = this->encodeAudio(packet.data, packet.length, &pkt); + if (a > 0) { + printf("GUAY a %d\n", a); + } + + } + av_free_packet(&pkt); + } + + bool OutputProcessor::initAudioCoder() { + + aCoder = avcodec_find_encoder(mediaInfo.audioCodec.codec); + if (!aCoder) { + printf("Encoder de audio no encontrado"); + exit(0); + return false; + } + + aCoderContext = avcodec_alloc_context3(aCoder); + if (!aCoderContext) { + printf("Error de memoria en coder de audio"); + exit(0); + return false; + } + + aCoderContext->sample_fmt = AV_SAMPLE_FMT_S16; + aCoderContext->bit_rate = mediaInfo.audioCodec.bitRate; + aCoderContext->sample_rate = mediaInfo.audioCodec.sampleRate; + aCoderContext->channels = 1; + + if (avcodec_open2(aCoderContext, aCoder, NULL) < 0) { + printf("Error al abrir el coder de audio"); + exit(0); + return false; + } + + audioCoder = 1; + return true; + } + + bool OutputProcessor::initVideoCoder() { + + vCoder = avcodec_find_encoder(mediaInfo.videoCodec.codec); + if (!vCoder) { + printf("Encoder de vídeo no encontrado"); + return false; + } + + vCoderContext = avcodec_alloc_context3(vCoder); + if (!vCoderContext) { + printf("Error de memoria en coder de vídeo"); + return false; + } + + vCoderContext->bit_rate = mediaInfo.videoCodec.bitRate; + vCoderContext->rc_min_rate = mediaInfo.videoCodec.bitRate; // + vCoderContext->rc_max_rate = mediaInfo.videoCodec.bitRate; // VPX_CBR + vCoderContext->qmin = 8; + vCoderContext->qmax = 56; // rc_quantifiers + // vCoderContext->frame_skip_threshold = 30; + vCoderContext->rc_buffer_aggressivity = 1; + vCoderContext->rc_buffer_size = vCoderContext->bit_rate; + vCoderContext->rc_initial_buffer_occupancy = vCoderContext->bit_rate / 2; + vCoderContext->width = mediaInfo.videoCodec.width; + vCoderContext->height = mediaInfo.videoCodec.height; + vCoderContext->pix_fmt = PIX_FMT_YUV420P; + vCoderContext->time_base = (AVRational) {1, 90000}; + vCoderContext->sample_aspect_ratio = + (AVRational) {mediaInfo.videoCodec.width,mediaInfo.videoCodec.height}; + + if (avcodec_open2(vCoderContext, vCoder, NULL) < 0) { + printf("Error al abrir el decoder de vídeo"); + return false; + } + + cPicture = avcodec_alloc_frame(); + if (!cPicture) { + printf("Error de memoria en frame del coder de vídeo"); + return false; + } + + videoCoder = 1; + printf("videoCoder configured successfully %d x %d\n", vCoderContext->width, + vCoderContext->height); + return true; + } + + bool OutputProcessor::initAudioPackager() { + audioPackager = 1; + return true; + } + + bool OutputProcessor::initVideoPackager() { + seqnum_ = 0; + videoPackager = 1; + return true; + } + + int OutputProcessor::packageAudio(unsigned char* inBuff, int inBuffLen, + unsigned char* outBuff) { + + if (audioPackager == 0) { + printf("No se ha inicializado el codec de output audio RTP"); + return -1; + } + + + timeval time; + gettimeofday(&time, NULL); + long millis = (time.tv_sec * 1000) + (time.tv_usec / 1000); + + RTPHeader head; + head.setSeqNumber(seqnum_++); + head.setTimestamp(millis*8); + head.setSSRC(55543); + head.setPayloadType(0); + + memcpy (rtpBuffer_, &head, head.getHeaderLength()); + memcpy(&rtpBuffer_[head.getHeaderLength()], inBuff, inBuffLen); + // sink_->sendData(rtpBuffer_, l); + // rtpReceiver_->receiveRtpData(rtpBuffer_, (inBuffLen + RTP_HEADER_LEN)); + } + + int OutputProcessor::packageVideo(AVPacket* pkt, unsigned char* outBuff) { + if (videoPackager == 0) { + printf("No se ha inicailizado el codec de output vídeo RTP"); + return -1; + } + + printf("To packetize %u\n", pkt->size); + if (pkt->size <= 0) + return -1; + RtpVP8Fragmenter frag(pkt->data, pkt->size, 1100); + bool lastFrame = false; + unsigned int outlen = 0; + timeval time; + gettimeofday(&time, NULL); + long millis = (time.tv_sec * 1000) + (time.tv_usec / 1000); + // timestamp_ += 90000 / mediaInfo.videoCodec.frameRate; + + do { + outlen = 0; + frag.getPacket(outBuff, &outlen, &lastFrame); + RTPHeader rtpHeader; + rtpHeader.setMarker(lastFrame?1:0); + rtpHeader.setSeqNumber(seqnum_++); + rtpHeader.setTimestamp(millis*90); + rtpHeader.setSSRC(55543); + rtpHeader.setPayloadType(100); + memcpy(rtpBuffer_, &rtpHeader, rtpHeader.getHeaderLength()); + memcpy(&rtpBuffer_[rtpHeader.getHeaderLength()],outBuff, outlen); + + int l = outlen + rtpHeader.getHeaderLength(); + // sink_->sendData(rtpBuffer_, l); + rtpReceiver_->receiveRtpData(rtpBuffer_, l); + } while (!lastFrame); + + return 0; + } + + int OutputProcessor::encodeAudio(unsigned char* inBuff, int nSamples, + AVPacket* pkt) { + + if (audioCoder == 0) { + printf("No se han inicializado los parámetros del audioCoder"); + return -1; + } + + AVFrame *frame; + /* frame containing input raw audio */ + frame = avcodec_alloc_frame(); + if (!frame) { + fprintf(stderr, "could not allocate audio frame\n"); + exit(1); + } + uint16_t* samples; + int ret, got_output, buffer_size; + float t, tincr; + + frame->nb_samples = aCoderContext->frame_size; + frame->format = aCoderContext->sample_fmt; + // frame->channel_layout = aCoderContext->channel_layout; + + /* the codec gives us the frame size, in samples, + * we calculate the size of the samples buffer in bytes */ + printf("channels %d, frame_size %d, sample_fmt %d\n", + aCoderContext->channels, aCoderContext->frame_size, + aCoderContext->sample_fmt); + buffer_size = av_samples_get_buffer_size(NULL, aCoderContext->channels, + aCoderContext->frame_size, aCoderContext->sample_fmt, 0); + samples = (uint16_t*) av_malloc(buffer_size); + if (!samples) { + fprintf(stderr, "could not allocate %d bytes for samples buffer\n", + buffer_size); + exit(1); + } + /* setup the data pointers in the AVFrame */ + ret = avcodec_fill_audio_frame(frame, aCoderContext->channels, + aCoderContext->sample_fmt, (const uint8_t*) samples, buffer_size, + 0); + if (ret < 0) { + fprintf(stderr, "could not setup audio frame\n"); + exit(1); + } + + ret = avcodec_encode_audio2(aCoderContext, pkt, frame, &got_output); + if (ret < 0) { + fprintf(stderr, "error encoding audio frame\n"); + exit(1); + } + if (got_output) { + //fwrite(pkt.data, 1, pkt.size, f); + printf("Got OUTPUT\n"); + } + + return ret; + + } + + int OutputProcessor::encodeVideo(unsigned char* inBuff, int inBuffLen, + AVPacket* pkt) { + if (videoCoder == 0) { + printf("No se han inicializado los parámetros del videoCoder"); + return -1; + } + int size = vCoderContext->width * vCoderContext->height; + printf("vCoderContext width %d\n", vCoderContext->width); + + cPicture->pts = AV_NOPTS_VALUE; + cPicture->data[0] = (unsigned char*) inBuff; + cPicture->data[1] = (unsigned char*) inBuff + size; + cPicture->data[2] = (unsigned char*) inBuff + size + size / 4; + cPicture->linesize[0] = vCoderContext->width; + cPicture->linesize[1] = vCoderContext->width / 2; + cPicture->linesize[2] = vCoderContext->width / 2; + + int ret = 0; + int got_packet = 0; + printf( + "Before encoding inBufflen %d, size %d, codecontext width %d pkt->size%d\n", + inBuffLen, size, vCoderContext->width, pkt->size); + ret = avcodec_encode_video2(vCoderContext, pkt, cPicture, &got_packet); + printf("Encoded video size %u, ret %d, got_packet %d, pts %lld, dts %lld\n", + pkt->size, ret, got_packet, pkt->pts, pkt->dts); + if (!ret && got_packet && vCoderContext->coded_frame) { + vCoderContext->coded_frame->pts = pkt->pts; + vCoderContext->coded_frame->key_frame = + !!(pkt->flags & AV_PKT_FLAG_KEY); + } + /* free any side data since we cannot return it */ + // if (pkt.side_data_elems > 0) { + // int i; + // for (i = 0; i < pkt.side_data_elems; i++) + // av_free(pkt.side_data[i].data); + // av_freep(&pkt.side_data); + // pkt.side_data_elems = 0; + // } + return ret ? ret : pkt->size; + } } /* namespace erizo */ diff --git a/src/erizo/media/MediaProcessor.h b/src/erizo/media/MediaProcessor.h index 3f59892a13..81e8677963 100644 --- a/src/erizo/media/MediaProcessor.h +++ b/src/erizo/media/MediaProcessor.h @@ -42,6 +42,16 @@ enum ProcessorType { RTP_ONLY, AVF }; +enum DataType { + VIDEO, AUDIO +}; + +struct RawDataPacket { + unsigned char* data; + int length; + DataType type; +}; + struct MediaInfo { std::string url; bool hasVideo; @@ -54,30 +64,6 @@ struct MediaInfo { }; -typedef struct { - uint32_t cc :4; - uint32_t extension :1; - uint32_t padding :1; - uint32_t version :2; - uint32_t payloadtype :7; - uint32_t marker :1; - uint32_t seqnum :16; - uint32_t timestamp; - uint32_t ssrc; - uint32_t extId :16; - uint32_t extLength :16; -} rtpHeader; - -typedef struct { - uint32_t partId :4; - uint32_t S :1; - uint32_t N :1; - uint32_t R :1; - uint32_t X :1; -} vp8RtpHeader; - -#define RTP_HEADER_LEN 12 - #define UNPACKAGED_BUFFER_SIZE 150000 #define PACKAGED_BUFFER_SIZE 2000 //class MediaProcessor{ @@ -90,7 +76,7 @@ typedef struct { class RawDataReceiver { public: - virtual void receiveRawData(unsigned char*data, int len) = 0; + virtual void receiveRawData(RawDataPacket& packet) = 0; virtual ~RawDataReceiver() { } ; @@ -132,6 +118,9 @@ class InputProcessor: MediaReceiver { unsigned char* decodedBuffer_; unsigned char* unpackagedBuffer_; + unsigned char* decodedAudioBuffer_; + unsigned char* unpackagedAudioBuffer_; + AVCodec* aDecoder; AVCodecContext* aDecoderContext; @@ -175,7 +164,7 @@ class OutputProcessor: public RawDataReceiver { virtual ~OutputProcessor(); int init(const MediaInfo& info, RTPDataReceiver* rtpReceiver); - void receiveRawData(unsigned char*data, int len); + void receiveRawData(RawDataPacket& packet); private: @@ -193,6 +182,10 @@ class OutputProcessor: public RawDataReceiver { unsigned char* packagedBuffer_; unsigned char* rtpBuffer_; + unsigned char* encodedAudioBuffer_; + unsigned char* packagedAudioBuffer_; + unsigned char* rtpAudioBuffer_; + MediaInfo mediaInfo; RTPDataReceiver* rtpReceiver_; @@ -222,16 +215,13 @@ class OutputProcessor: public RawDataReceiver { bool initVideoPackager(); int encodeAudio(unsigned char* inBuff, int nSamples, - unsigned char* outBuff); -// int encodeVideo(unsigned char* inBuff, int inBuffLen, -// unsigned char* outBuff, int outBuffLen); + AVPacket* pkt); int encodeVideo(unsigned char* inBuff, int inBuffLen, AVPacket* pkt); int packageAudio(unsigned char* inBuff, int inBuffLen, unsigned char* outBuff); -// int packageVideo(unsigned char* inBuff, int inBuffLen, -// unsigned char* outBuff); + int packageVideo(AVPacket* pkt, unsigned char* outBuff); }; } /* namespace erizo */ diff --git a/src/erizo/media/utils/RtpFragmenter.cpp b/src/erizo/media/utils/RtpFragmenter.cpp deleted file mode 100644 index cce99cd5a5..0000000000 --- a/src/erizo/media/utils/RtpFragmenter.cpp +++ /dev/null @@ -1,67 +0,0 @@ -#include -#include -#include "RtpFragmenter.h" - -#define MAX_SIZE 1100 //max fragment size including vp8 payload descriptor -#define VP8 1 -namespace erizo { - -RtpFragmenter::RtpFragmenter(unsigned char* data, unsigned int length) : - totalData_(data), totalLenth_(length) { - calculatePackets(); -// printf("Packets calculated successfully\n"); -} - -RtpFragmenter::~RtpFragmenter() { -} - -int RtpFragmenter::getPacket(unsigned char* data, unsigned int* length, - bool* lastPacket) { - if (fragmentQueue_.size() > 0) { - const Fragment& test = fragmentQueue_.front(); -// printf("writing fragment, length %u\n", *length); - - *length = writeFragment(test, data, length); - fragmentQueue_.pop(); - if (fragmentQueue_.empty()) - *lastPacket = true; - -// printf("lastPacket %d\n", *lastPacket); - - } - return 0; -} -void RtpFragmenter::calculatePackets() { - unsigned int remaining = totalLenth_; - unsigned int currentPos = 0; - while (remaining > 0) { -// printf("Packetizing, remaining %u\n", remaining); - Fragment newFragment; - newFragment.first = false; - newFragment.position = currentPos; - if (currentPos == 0) - newFragment.first = true; - newFragment.size = remaining > MAX_SIZE - 1 ? MAX_SIZE - 1 : remaining; -// printf("New fragment size %u, position %u\n", newFragment.size, -// newFragment.position); - currentPos += newFragment.size; - remaining -= newFragment.size; - fragmentQueue_.push(newFragment); - } -} -unsigned int RtpFragmenter::writeFragment(const Fragment& fragment, - unsigned char* buffer, unsigned int* length) { - - if (VP8) { - buffer[0] = 0x0; - if (fragment.first) - buffer[0] |= 0x10; // S bit 1 // era 01 - memcpy(&buffer[1], &totalData_[fragment.position], fragment.size); - return (fragment.size + 1); - }else{ - memcpy(&buffer[0], &totalData_[fragment.position], fragment.size); - return fragment.size; - } -} - -} /* namespace erizo */ diff --git a/src/erizo/media/utils/RtpFragmenter.h b/src/erizo/media/utils/RtpFragmenter.h deleted file mode 100644 index a0e9498be0..0000000000 --- a/src/erizo/media/utils/RtpFragmenter.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef RTPFRAGMENTER_H_ -#define RTPFRAGMENTER_H_ - -#include - -namespace erizo { - -class RtpFragmenter { -public: - RtpFragmenter(unsigned char* data, unsigned int length); - virtual ~RtpFragmenter(); - - int getPacket(unsigned char* data, unsigned int* length, bool* lastPacket); - -private: - struct Fragment { - unsigned int position; - unsigned int size; - bool first; - }; - void calculatePackets(); - unsigned int writeFragment(const Fragment& fragment, unsigned char* buffer, - unsigned int* length); - unsigned char* totalData_; - unsigned int totalLenth_; - std::queue fragmentQueue_; -}; - -} /* namespace erizo */ -#endif /* RTPFRAGMENTER_H_ */ From 0eedbdac108e315d58007ca29dc6dd909f349ed5 Mon Sep 17 00:00:00 2001 From: Pedro Rodriguez Date: Wed, 26 Sep 2012 17:30:23 +0200 Subject: [PATCH 20/29] Code Cleanup --- src/erizo/media/utils/RtpHeader.h | 187 +++++++++++++++++++++ src/erizo/media/utils/RtpVP8Fragmenter.cpp | 63 +++++++ src/erizo/media/utils/RtpVP8Fragmenter.h | 31 ++++ 3 files changed, 281 insertions(+) create mode 100644 src/erizo/media/utils/RtpHeader.h create mode 100644 src/erizo/media/utils/RtpVP8Fragmenter.cpp create mode 100644 src/erizo/media/utils/RtpVP8Fragmenter.h diff --git a/src/erizo/media/utils/RtpHeader.h b/src/erizo/media/utils/RtpHeader.h new file mode 100644 index 0000000000..63b36d53b2 --- /dev/null +++ b/src/erizo/media/utils/RtpHeader.h @@ -0,0 +1,187 @@ +/* + * RtpHeader.h + * + * Created on: Sep 20, 2012 + * Author: pedro + */ + +#ifndef RTPHEADER_H_ +#define RTPHEADER_H_ + +class RTPHeader { +public: + // constants + + /** + * KSize + * Longitud de la cabecera en bytes. + */ + static const int MIN_SIZE = 12; + +public: + // Constructor + inline RTPHeader() : + cc(0), extension(0), padding(0), version(2), payloadtype(0), marker( + 0), seqnum(0), timestamp(0), ssrc(0), extId(0), extLength(0) { + // No implementation required + } + +public: + // Member functions + + /** + * Get the marker bit from the RTP header. + * @return 1 if marker bit is set 0 if is not set. + */ + inline uint8_t getMarker() const { + return marker; + } + + /** + * Set the marker bit from the RTP header. + * @param aMarker 1 to set marker bit, 0 to unset it. + */ + inline void setMarker(uint8_t aMarker) { + marker = aMarker; + } + + /** + * Get the extension bit from the RTP header. + * @return 1 if extension bit is set 0 if is not set. + */ + inline uint8_t getExtension() const { + return extension; + } + + /** + * Set the extension bit from the RTP header + * @param ext 1 to set extension bit, 0 to unset i + */ + inline void setExtension(uint8_t ext) { + extension = ext; + } + + /** + * Get the payload type from the RTP header. + * @return A TInt8 holding the value. + */ + inline uint8_t getPayloadType() const { + return payloadtype; + } + + /** + * Set the payload type from the RTP header. + * @param aType the payload type. Valid range between 0x00 to 0x7F + */ + inline void setPayloadType(uint8_t aType) { + payloadtype = aType; + } + + /** + * Get the sequence number field from the RTP header. + * @return A TInt16 holding the value. + */ + inline uint16_t getSeqNumber() const { + return ntohs(seqnum); + } + + /** + * Set the seq number from the RTP header. + * @param aSeqNumber The seq number. Valid range between 0x0000 to 0xFFFF + */ + inline void setSeqNumber(uint16_t aSeqNumber) { + seqnum = htons(aSeqNumber); + } + + /** + * Get the Timestamp field from the RTP header. + * @return A TInt32 holding the value. + */ + inline uint32_t getTimestamp() const { + return ntohl(timestamp); + } + + /** + * Set the Timestamp from the RTP header. + * @param aTimestamp The Tmestamp. Valid range between 0x00000000 to 0xFFFFFFFF + */ + inline void setTimestamp(uint32_t aTimestamp) { + timestamp = htonl(aTimestamp); + } + + /** + * Get the SSRC field from the RTP header. + * @return A TInt32 holding the value. + */ + inline uint32_t getSSRC() const { + return ntohl(ssrc); + } + + /** + * Set the SSRC from the RTP header. + * @param aSSRC The SSRC. Valid range between 0x00000000 to 0xFFFFFFFF + */ + inline void setSSRC(uint32_t aSSRC) { + ssrc = htonl(aSSRC); + } + /** + * Get the sequence number field from the RTP header. + * @return A TInt16 holding the value. + */ + inline uint16_t getExtId() const { + return ntohs(extId); + } + + /** + * Set the seq number from the RTP header. + * @param extensionId The seq number. Valid range between 0x0000 to 0xFFFF + */ + inline void setExtId(uint16_t extensionId) { + extId = htons(extensionId); + } + + /** + * Get the sequence number field from the RTP header. + * @return A TInt16 holding the value. + */ + inline uint16_t getExtLength() const { + return ntohs(extLength); + } + + /** + * Set the seq number from the RTP header. + * @param aSeqNumber The seq number. Valid range between 0x0000 to 0xFFFF + */ + inline void setExtLength(uint16_t extensionLength) { + extId = htons(extensionLength); + } + + /** + * Get the RTP header length + * @return the length in 8 bit units + */ + inline int getHeaderLength() { + return MIN_SIZE + cc * 4 + extension * (4 + extLength * 4); + } + + + +private: + // Data + + uint32_t cc :4; + uint32_t extension :1; + uint32_t padding :1; + uint32_t version :2; + uint32_t payloadtype :7; + uint32_t marker :1; + uint32_t seqnum :16; + uint32_t timestamp; + uint32_t ssrc; + uint32_t csrc[3]; + uint32_t extId :16; + uint32_t extLength :16; + +}; + +#endif /* RTPHEADER_H_ */ diff --git a/src/erizo/media/utils/RtpVP8Fragmenter.cpp b/src/erizo/media/utils/RtpVP8Fragmenter.cpp new file mode 100644 index 0000000000..ce047fa951 --- /dev/null +++ b/src/erizo/media/utils/RtpVP8Fragmenter.cpp @@ -0,0 +1,63 @@ +#include +#include +#include "RtpVP8Fragmenter.h" + +#define MAX_SIZE 1100 //max fragment size including vp8 payload descriptor +#define VP8 1 +namespace erizo { + +RtpVP8Fragmenter::RtpVP8Fragmenter(unsigned char* data, unsigned int length, + unsigned int maxLength) : + totalData_(data), totalLenth_(length), maxlength_(maxLength) { + calculatePackets(); +} + +RtpVP8Fragmenter::~RtpVP8Fragmenter() { +} + +int RtpVP8Fragmenter::getPacket(unsigned char* data, unsigned int* length, + bool* lastPacket) { + if (fragmentQueue_.size() > 0) { + const Fragment& test = fragmentQueue_.front(); + + *length = writeFragment(test, data, length); + fragmentQueue_.pop(); + if (fragmentQueue_.empty()) + *lastPacket = true; + } + return 0; +} +void RtpVP8Fragmenter::calculatePackets() { + unsigned int remaining = totalLenth_; + unsigned int currentPos = 0; + while (remaining > 0) { +// printf("Packetizing, remaining %u\n", remaining); + Fragment newFragment; + newFragment.first = false; + newFragment.position = currentPos; + if (currentPos == 0) + newFragment.first = true; + newFragment.size = remaining > MAX_SIZE - 1 ? MAX_SIZE - 1 : remaining; +// printf("New fragment size %u, position %u\n", newFragment.size, +// newFragment.position); + currentPos += newFragment.size; + remaining -= newFragment.size; + fragmentQueue_.push(newFragment); + } +} +unsigned int RtpVP8Fragmenter::writeFragment(const Fragment& fragment, + unsigned char* buffer, unsigned int* length) { + + if (VP8) { + buffer[0] = 0x0; + if (fragment.first) + buffer[0] |= 0x10; // S bit 1 // era 01 + memcpy(&buffer[1], &totalData_[fragment.position], fragment.size); + return (fragment.size + 1); + } else { + memcpy(&buffer[0], &totalData_[fragment.position], fragment.size); + return fragment.size; + } +} + +} /* namespace erizo */ diff --git a/src/erizo/media/utils/RtpVP8Fragmenter.h b/src/erizo/media/utils/RtpVP8Fragmenter.h new file mode 100644 index 0000000000..620971d0fe --- /dev/null +++ b/src/erizo/media/utils/RtpVP8Fragmenter.h @@ -0,0 +1,31 @@ +#ifndef RTPFRAGMENTER_H_ +#define RTPFRAGMENTER_H_ + +#include + +namespace erizo { + +class RtpVP8Fragmenter { +public: + RtpVP8Fragmenter(unsigned char* data, unsigned int length, unsigned int maxLength); + virtual ~RtpVP8Fragmenter(); + + int getPacket(unsigned char* data, unsigned int* length, bool* lastPacket); + +private: + struct Fragment { + unsigned int position; + unsigned int size; + bool first; + }; + void calculatePackets(); + unsigned int writeFragment(const Fragment& fragment, unsigned char* buffer, + unsigned int* length); + unsigned char* totalData_; + unsigned int totalLenth_; + unsigned int maxlength_; + std::queue fragmentQueue_; +}; + +} /* namespace erizo */ +#endif /* RTPFRAGMENTER_H_ */ From fbe1c6feb5f18a065ae3985720310aa893c9edcc Mon Sep 17 00:00:00 2001 From: Pedro Rodriguez Date: Wed, 17 Oct 2012 18:40:35 +0200 Subject: [PATCH 21/29] Media reorganization --- src/erizo/NiceConnection.cpp | 598 ++++++++-------- src/erizo/OneToManyProcessor.cpp | 2 +- src/erizo/media/MediaProcessor.cpp | 24 +- src/erizo/media/MediaProcessor.h | 21 +- src/erizo/media/codecs/CodecFactory.cpp | 27 + src/erizo/media/codecs/CodecFactory.h | 45 ++ src/erizo/media/codecs/Codecs.h | 0 src/erizo/media/codecs/VideoCodec.cpp | 258 +++++++ src/erizo/media/codecs/VideoCodec.h | 46 ++ src/erizo/media/mixers/VideoMixer.cpp | 45 ++ src/erizo/media/mixers/VideoMixer.h | 75 ++ src/erizo/media/mixers/VideoUtils.cpp | 644 ++++++++++++++++++ src/erizo/media/mixers/VideoUtils.h | 70 ++ src/erizo/media/{utils => rtp}/RtpHeader.h | 0 src/erizo/media/{utils => rtp}/RtpParser.cpp | 0 src/erizo/media/{utils => rtp}/RtpParser.h | 0 .../media/{utils => rtp}/RtpVP8Fragmenter.cpp | 0 .../media/{utils => rtp}/RtpVP8Fragmenter.h | 0 18 files changed, 1527 insertions(+), 328 deletions(-) create mode 100644 src/erizo/media/codecs/CodecFactory.cpp create mode 100644 src/erizo/media/codecs/CodecFactory.h create mode 100644 src/erizo/media/codecs/Codecs.h create mode 100644 src/erizo/media/codecs/VideoCodec.cpp create mode 100644 src/erizo/media/codecs/VideoCodec.h create mode 100644 src/erizo/media/mixers/VideoMixer.cpp create mode 100644 src/erizo/media/mixers/VideoMixer.h create mode 100644 src/erizo/media/mixers/VideoUtils.cpp create mode 100644 src/erizo/media/mixers/VideoUtils.h rename src/erizo/media/{utils => rtp}/RtpHeader.h (100%) rename src/erizo/media/{utils => rtp}/RtpParser.cpp (100%) rename src/erizo/media/{utils => rtp}/RtpParser.h (100%) rename src/erizo/media/{utils => rtp}/RtpVP8Fragmenter.cpp (100%) rename src/erizo/media/{utils => rtp}/RtpVP8Fragmenter.h (100%) diff --git a/src/erizo/NiceConnection.cpp b/src/erizo/NiceConnection.cpp index 4de39c351c..1f9b1b0612 100644 --- a/src/erizo/NiceConnection.cpp +++ b/src/erizo/NiceConnection.cpp @@ -10,304 +10,304 @@ namespace erizo { -guint stream_id; -GSList* lcands; -int streamsGathered; -int rec, sen; -int length; -int components = 2; -uint32_t ssrc = 55543; - -void cb_nice_recv(NiceAgent* agent, guint stream_id, guint component_id, - guint len, gchar* buf, gpointer user_data) { - -// printf( "cb_nice_recv len %u id %u\n",len, stream_id ); - NiceConnection* nicecon = (NiceConnection*) user_data; - nicecon->getWebRtcConnection()->receiveNiceData((char*) buf, (int) len, - (NiceConnection*) user_data); -} - -void cb_candidate_gathering_done(NiceAgent *agent, guint stream_id, - gpointer user_data) { - - NiceConnection *conn = (NiceConnection*) user_data; - //printf("ConnState %u\n",conn->state); - // ... Wait until the signal candidate-gathering-done is fired ... - int currentCompId = 1; - lcands = nice_agent_get_local_candidates(agent, stream_id, currentCompId++); - NiceCandidate *cand; - GSList* iterator; - // printf("gathering done %u\n",stream_id); - //printf("Candidates---------------------------------------------------->\n"); - while (lcands != NULL) { - for (iterator = lcands; iterator; iterator = iterator->next) { - char address[40]; - cand = (NiceCandidate*) iterator->data; - nice_address_to_string(&cand->addr, address); - if (strstr(address, ":") != NULL) { - printf("Ignoring IPV6 candidate\n"); - continue; - - } -// printf("foundation %s\n", cand->foundation); -// printf("compid %u\n", cand->component_id); -// printf("stream_id %u\n", cand->stream_id); -// printf("priority %u\n", cand->priority); -// printf("username %s\n", cand->username); -// printf("password %s\n", cand->password); - CandidateInfo cand_info; - cand_info.componentId = cand->component_id; - cand_info.foundation = cand->foundation; - cand_info.priority = cand->priority; - cand_info.hostAddress = std::string(address); - cand_info.hostPort = nice_address_get_port(&cand->addr); - cand_info.mediaType = conn->mediaType; - - /* - * NICE_CANDIDATE_TYPE_HOST, - * NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE, - * NICE_CANDIDATE_TYPE_PEER_REFLEXIVE, - * NICE_CANDIDATE_TYPE_RELAYED, - */ - switch (cand->type) { - case NICE_CANDIDATE_TYPE_HOST: - cand_info.hostType = HOST; - break; - case NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE: - cand_info.hostType = SRLFX; - break; - case NICE_CANDIDATE_TYPE_PEER_REFLEXIVE: - cand_info.hostType = PRFLX; - break; - case NICE_CANDIDATE_TYPE_RELAYED: - printf("WARNING TURN NOT IMPLEMENTED YET\n"); - cand_info.hostType = RELAY; - break; - default: - break; - } - cand_info.netProtocol = "udp"; - cand_info.transProtocol = std::string(*conn->transportName); - //cand_info.username = std::string(cand->username); - if (cand->username) - cand_info.username = std::string(cand->username); - else - cand_info.username = std::string("(null)"); - - if (cand->password) - cand_info.password = std::string(cand->password); - else - cand_info.password = std::string("(null)"); - - conn->localCandidates->push_back(cand_info); - } - lcands = nice_agent_get_local_candidates(agent, stream_id, - currentCompId++); - } - printf("candidate_gathering done, size %u\n", - conn->localCandidates->size()); - conn->updateIceState(CANDIDATES_GATHERED); -} - -void cb_component_state_changed(NiceAgent *agent, guint stream_id, - guint component_id, guint state, gpointer user_data) { - printf("cb_component_state_changed %u\n", state); - if (state == NICE_COMPONENT_STATE_READY) { - NiceConnection *conn = (NiceConnection*) user_data; - conn->updateIceState(READY); - } else if (state == NICE_COMPONENT_STATE_FAILED) { - printf("Ice Component failed, stopping\n"); - NiceConnection *conn = (NiceConnection*) user_data; - conn->updateIceState(FAILED); - //conn->getWebRtcConnection()->close(); - } - -} - -void cb_new_selected_pair(NiceAgent *agent, guint stream_id, guint component_id, - gchar *lfoundation, gchar *rfoundation, gpointer user_data) { - printf( - "cb_new_selected_pair for stream %u, comp %u, lfound %s, rfound %s \n", - stream_id, component_id, lfoundation, rfoundation); - NiceConnection *conn = (NiceConnection*) user_data; - - printf( - "cb_new_selected_pair for stream %u, comp %u, lfound %s, rfound %s \n", - stream_id, component_id, lfoundation, rfoundation); -} - -NiceConnection::NiceConnection(MediaType med, - const std::string &transport_name) { - - agent_ = NULL; - loop_ = NULL; - conn_ = NULL; - mediaType = med; - localCandidates = new std::vector(); - transportName = new std::string(transport_name); -} - -NiceConnection::~NiceConnection() { - - if (iceState != FINISHED) - this->close(); - if (agent_) - g_object_unref(agent_); - if (localCandidates) - delete localCandidates; - if (transportName) - delete transportName; -} - -void NiceConnection::join() { - - m_Thread_.join(); -} - -void NiceConnection::start() { - - m_Thread_ = boost::thread(&NiceConnection::init, this); -} - -void NiceConnection::close() { - - if (agent_ != NULL) - nice_agent_remove_stream(agent_, 1); - if (loop_ != NULL) - g_main_loop_quit(loop_); - iceState = FINISHED; -} - -int NiceConnection::sendData(void *buf, int len) { - - int val = -1; - if (iceState == READY) { - val = nice_agent_send(agent_, 1, 1, len, (char*) buf); - } - return val; -} - -WebRtcConnection* NiceConnection::getWebRtcConnection() { - - return conn_; -} - -void NiceConnection::init() { - - streamsGathered = 0; - this->updateIceState(INITIAL); - - g_type_init(); - g_thread_init(NULL); - - loop_ = g_main_loop_new(NULL, FALSE); - // nice_debug_enable( TRUE ); - // Create a nice agent - agent_ = nice_agent_new(g_main_loop_get_context(loop_), - NICE_COMPATIBILITY_GOOGLE); - -// NiceAddress* naddr = nice_address_new(); -// nice_agent_add_local_address(agent_, naddr); - - GValue val = { 0 }, val2 = { 0 }; - -// g_value_init(&val, G_TYPE_STRING); -// g_value_set_string(&val, "173.194.70.126"); -// g_object_set_property(G_OBJECT( agent_ ), "stun-server", &val); -// -// g_value_init(&val2, G_TYPE_UINT); -// g_value_set_uint(&val2, 19302); -// g_object_set_property(G_OBJECT( agent_ ), "stun-server-port", &val2); - - // Connect the signals - g_signal_connect( G_OBJECT( agent_ ), "candidate-gathering-done", - G_CALLBACK( cb_candidate_gathering_done ), this); - g_signal_connect( G_OBJECT( agent_ ), "component-state-changed", - G_CALLBACK( cb_component_state_changed ), this); - g_signal_connect( G_OBJECT( agent_ ), "new-selected-pair", - G_CALLBACK( cb_new_selected_pair ), this); - - // Create a new stream and start gathering candidates - - int res = nice_agent_add_stream(agent_, 1); - // Set Port Range ----> If this doesn't work when linking the file libnice.sym has to be modified to include this call -// nice_agent_set_port_range(agent_, (guint)1, (guint)1, (guint)51000, (guint)52000); - - nice_agent_gather_candidates(agent_, 1); - nice_agent_attach_recv(agent_, 1, 1, g_main_loop_get_context(loop_), - cb_nice_recv, this); - - // Attach to the component to receive the data - g_main_loop_run(loop_); -} - -bool NiceConnection::setRemoteCandidates( - std::vector &candidates) { - - GSList* candList = NULL; - - for (unsigned int it = 0; it < candidates.size(); it++) { - NiceCandidateType nice_cand_type; - CandidateInfo cinfo = candidates[it]; - if (cinfo.mediaType != this->mediaType - || this->transportName->compare(cinfo.transProtocol)) - continue; - - switch (cinfo.hostType) { - case HOST: - nice_cand_type = NICE_CANDIDATE_TYPE_HOST; - break; - case SRLFX: - nice_cand_type = NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE; - break; - case PRFLX: - nice_cand_type = NICE_CANDIDATE_TYPE_PEER_REFLEXIVE; - break; - case RELAY: - nice_cand_type = NICE_CANDIDATE_TYPE_RELAYED; - break; - default: - nice_cand_type = NICE_CANDIDATE_TYPE_HOST; - break; - } - - NiceCandidate* thecandidate = nice_candidate_new(nice_cand_type); - NiceAddress* naddr = nice_address_new(); - nice_address_set_from_string(naddr, cinfo.hostAddress.c_str()); - nice_address_set_port(naddr, cinfo.hostPort); - thecandidate->addr = *naddr; - char* uname = (char*) malloc(cinfo.username.size()); - char* pass = (char*) malloc(cinfo.password.size()); - sprintf(thecandidate->foundation, "%s", cinfo.foundation.c_str()); - sprintf(uname, "%s", cinfo.username.c_str()); - sprintf(pass, "%s", cinfo.password.c_str()); - - thecandidate->username = uname; - thecandidate->password = pass; - thecandidate->stream_id = (guint) 1; - thecandidate->component_id = cinfo.componentId; - thecandidate->priority = cinfo.priority; - thecandidate->transport = NICE_CANDIDATE_TRANSPORT_UDP; - candList = g_slist_append(candList, thecandidate); - - } - - nice_agent_set_remote_candidates(agent_, (guint) 1, 1, candList); - - printf("Candidates SET\n"); - this->updateIceState(CANDIDATES_RECEIVED); - return true; -} - -void NiceConnection::setWebRtcConnection(WebRtcConnection* connection) { - - this->conn_ = connection; -} - -void NiceConnection::updateIceState(IceState state) { - this->iceState = state; - if (this->conn_ != NULL) - this->conn_->updateState(state, this); -} + guint stream_id; + GSList* lcands; + int streamsGathered; + int rec, sen; + int length; + int components = 2; + uint32_t ssrc = 55543; + + void cb_nice_recv(NiceAgent* agent, guint stream_id, guint component_id, + guint len, gchar* buf, gpointer user_data) { + + // printf( "cb_nice_recv len %u id %u\n",len, stream_id ); + NiceConnection* nicecon = (NiceConnection*) user_data; + nicecon->getWebRtcConnection()->receiveNiceData((char*) buf, (int) len, + (NiceConnection*) user_data); + } + + void cb_candidate_gathering_done(NiceAgent *agent, guint stream_id, + gpointer user_data) { + + NiceConnection *conn = (NiceConnection*) user_data; + //printf("ConnState %u\n",conn->state); + // ... Wait until the signal candidate-gathering-done is fired ... + int currentCompId = 1; + lcands = nice_agent_get_local_candidates(agent, stream_id, currentCompId++); + NiceCandidate *cand; + GSList* iterator; + // printf("gathering done %u\n",stream_id); + //printf("Candidates---------------------------------------------------->\n"); + while (lcands != NULL) { + for (iterator = lcands; iterator; iterator = iterator->next) { + char address[40]; + cand = (NiceCandidate*) iterator->data; + nice_address_to_string(&cand->addr, address); + if (strstr(address, ":") != NULL) { + printf("Ignoring IPV6 candidate\n"); + continue; + + } + // printf("foundation %s\n", cand->foundation); + // printf("compid %u\n", cand->component_id); + // printf("stream_id %u\n", cand->stream_id); + // printf("priority %u\n", cand->priority); + // printf("username %s\n", cand->username); + // printf("password %s\n", cand->password); + CandidateInfo cand_info; + cand_info.componentId = cand->component_id; + cand_info.foundation = cand->foundation; + cand_info.priority = cand->priority; + cand_info.hostAddress = std::string(address); + cand_info.hostPort = nice_address_get_port(&cand->addr); + cand_info.mediaType = conn->mediaType; + + /* + * NICE_CANDIDATE_TYPE_HOST, + * NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE, + * NICE_CANDIDATE_TYPE_PEER_REFLEXIVE, + * NICE_CANDIDATE_TYPE_RELAYED, + */ + switch (cand->type) { + case NICE_CANDIDATE_TYPE_HOST: + cand_info.hostType = HOST; + break; + case NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE: + cand_info.hostType = SRLFX; + break; + case NICE_CANDIDATE_TYPE_PEER_REFLEXIVE: + cand_info.hostType = PRFLX; + break; + case NICE_CANDIDATE_TYPE_RELAYED: + printf("WARNING TURN NOT IMPLEMENTED YET\n"); + cand_info.hostType = RELAY; + break; + default: + break; + } + cand_info.netProtocol = "udp"; + cand_info.transProtocol = std::string(*conn->transportName); + //cand_info.username = std::string(cand->username); + if (cand->username) + cand_info.username = std::string(cand->username); + else + cand_info.username = std::string("(null)"); + + if (cand->password) + cand_info.password = std::string(cand->password); + else + cand_info.password = std::string("(null)"); + + conn->localCandidates->push_back(cand_info); + } + lcands = nice_agent_get_local_candidates(agent, stream_id, + currentCompId++); + } + printf("candidate_gathering done, size %u\n", + conn->localCandidates->size()); + conn->updateIceState(CANDIDATES_GATHERED); + } + + void cb_component_state_changed(NiceAgent *agent, guint stream_id, + guint component_id, guint state, gpointer user_data) { + printf("cb_component_state_changed %u\n", state); + if (state == NICE_COMPONENT_STATE_READY) { + NiceConnection *conn = (NiceConnection*) user_data; + conn->updateIceState(READY); + } else if (state == NICE_COMPONENT_STATE_FAILED) { + printf("Ice Component failed, stopping\n"); + NiceConnection *conn = (NiceConnection*) user_data; + conn->updateIceState(FAILED); + //conn->getWebRtcConnection()->close(); + } + + } + + void cb_new_selected_pair(NiceAgent *agent, guint stream_id, guint component_id, + gchar *lfoundation, gchar *rfoundation, gpointer user_data) { + printf( + "cb_new_selected_pair for stream %u, comp %u, lfound %s, rfound %s \n", + stream_id, component_id, lfoundation, rfoundation); + NiceConnection *conn = (NiceConnection*) user_data; + + printf( + "cb_new_selected_pair for stream %u, comp %u, lfound %s, rfound %s \n", + stream_id, component_id, lfoundation, rfoundation); + } + + NiceConnection::NiceConnection(MediaType med, + const std::string &transport_name) { + + agent_ = NULL; + loop_ = NULL; + conn_ = NULL; + mediaType = med; + localCandidates = new std::vector(); + transportName = new std::string(transport_name); + } + + NiceConnection::~NiceConnection() { + + if (iceState != FINISHED) + this->close(); + if (agent_) + g_object_unref(agent_); + if (localCandidates) + delete localCandidates; + if (transportName) + delete transportName; + } + + void NiceConnection::join() { + + m_Thread_.join(); + } + + void NiceConnection::start() { + + m_Thread_ = boost::thread(&NiceConnection::init, this); + } + + void NiceConnection::close() { + + if (agent_ != NULL) + nice_agent_remove_stream(agent_, 1); + if (loop_ != NULL) + g_main_loop_quit(loop_); + iceState = FINISHED; + } + + int NiceConnection::sendData(void *buf, int len) { + + int val = -1; + if (iceState == READY) { + val = nice_agent_send(agent_, 1, 1, len, (char*) buf); + } + return val; + } + + WebRtcConnection* NiceConnection::getWebRtcConnection() { + + return conn_; + } + + void NiceConnection::init() { + + streamsGathered = 0; + this->updateIceState(INITIAL); + + g_type_init(); + g_thread_init(NULL); + + loop_ = g_main_loop_new(NULL, FALSE); + // nice_debug_enable( TRUE ); + // Create a nice agent + agent_ = nice_agent_new(g_main_loop_get_context(loop_), + NICE_COMPATIBILITY_GOOGLE); + + // NiceAddress* naddr = nice_address_new(); + // nice_agent_add_local_address(agent_, naddr); + + GValue val = { 0 }, val2 = { 0 }; + + // g_value_init(&val, G_TYPE_STRING); + // g_value_set_string(&val, "173.194.70.126"); + // g_object_set_property(G_OBJECT( agent_ ), "stun-server", &val); + // + // g_value_init(&val2, G_TYPE_UINT); + // g_value_set_uint(&val2, 19302); + // g_object_set_property(G_OBJECT( agent_ ), "stun-server-port", &val2); + + // Connect the signals + g_signal_connect( G_OBJECT( agent_ ), "candidate-gathering-done", + G_CALLBACK( cb_candidate_gathering_done ), this); + g_signal_connect( G_OBJECT( agent_ ), "component-state-changed", + G_CALLBACK( cb_component_state_changed ), this); + g_signal_connect( G_OBJECT( agent_ ), "new-selected-pair", + G_CALLBACK( cb_new_selected_pair ), this); + + // Create a new stream and start gathering candidates + + int res = nice_agent_add_stream(agent_, 1); + // Set Port Range ----> If this doesn't work when linking the file libnice.sym has to be modified to include this call + // nice_agent_set_port_range(agent_, (guint)1, (guint)1, (guint)51000, (guint)52000); + + nice_agent_gather_candidates(agent_, 1); + nice_agent_attach_recv(agent_, 1, 1, g_main_loop_get_context(loop_), + cb_nice_recv, this); + + // Attach to the component to receive the data + g_main_loop_run(loop_); + } + + bool NiceConnection::setRemoteCandidates( + std::vector &candidates) { + + GSList* candList = NULL; + + for (unsigned int it = 0; it < candidates.size(); it++) { + NiceCandidateType nice_cand_type; + CandidateInfo cinfo = candidates[it]; + if (cinfo.mediaType != this->mediaType + || this->transportName->compare(cinfo.transProtocol)) + continue; + + switch (cinfo.hostType) { + case HOST: + nice_cand_type = NICE_CANDIDATE_TYPE_HOST; + break; + case SRLFX: + nice_cand_type = NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE; + break; + case PRFLX: + nice_cand_type = NICE_CANDIDATE_TYPE_PEER_REFLEXIVE; + break; + case RELAY: + nice_cand_type = NICE_CANDIDATE_TYPE_RELAYED; + break; + default: + nice_cand_type = NICE_CANDIDATE_TYPE_HOST; + break; + } + + NiceCandidate* thecandidate = nice_candidate_new(nice_cand_type); + NiceAddress* naddr = nice_address_new(); + nice_address_set_from_string(naddr, cinfo.hostAddress.c_str()); + nice_address_set_port(naddr, cinfo.hostPort); + thecandidate->addr = *naddr; + char* uname = (char*) malloc(cinfo.username.size()); + char* pass = (char*) malloc(cinfo.password.size()); + sprintf(thecandidate->foundation, "%s", cinfo.foundation.c_str()); + sprintf(uname, "%s", cinfo.username.c_str()); + sprintf(pass, "%s", cinfo.password.c_str()); + + thecandidate->username = uname; + thecandidate->password = pass; + thecandidate->stream_id = (guint) 1; + thecandidate->component_id = cinfo.componentId; + thecandidate->priority = cinfo.priority; + thecandidate->transport = NICE_CANDIDATE_TRANSPORT_UDP; + candList = g_slist_append(candList, thecandidate); + + } + + nice_agent_set_remote_candidates(agent_, (guint) 1, 1, candList); + + printf("Candidates SET\n"); + this->updateIceState(CANDIDATES_RECEIVED); + return true; + } + + void NiceConnection::setWebRtcConnection(WebRtcConnection* connection) { + + this->conn_ = connection; + } + + void NiceConnection::updateIceState(IceState state) { + this->iceState = state; + if (this->conn_ != NULL) + this->conn_->updateState(state, this); + } } /* namespace erizo */ diff --git a/src/erizo/OneToManyProcessor.cpp b/src/erizo/OneToManyProcessor.cpp index 9992f2f075..d61fec57c5 100644 --- a/src/erizo/OneToManyProcessor.cpp +++ b/src/erizo/OneToManyProcessor.cpp @@ -5,7 +5,7 @@ #include "OneToManyProcessor.h" #include "WebRtcConnection.h" #include "RTPSink.h" -#include "media/utils/RtpHeader.h" +#include "media/rtp/RtpHeader.h" namespace erizo { OneToManyProcessor::OneToManyProcessor() : diff --git a/src/erizo/media/MediaProcessor.cpp b/src/erizo/media/MediaProcessor.cpp index 48781326c3..ada64cdf99 100644 --- a/src/erizo/media/MediaProcessor.cpp +++ b/src/erizo/media/MediaProcessor.cpp @@ -1,8 +1,8 @@ #include #include "MediaProcessor.h" -#include "utils/RtpVP8Fragmenter.h" -#include "utils/RtpHeader.h" +#include "rtp/RtpVP8Fragmenter.h" +#include "rtp/RtpHeader.h" namespace erizo { @@ -41,7 +41,7 @@ namespace erizo { this->mediaInfo = info; this->rawReceiver_ = receiver; if (mediaInfo.hasVideo) { - mediaInfo.videoCodec.codec = CODEC_ID_VP8; + mediaInfo.videoCodec.codec = VIDEO_CODEC_VP8; decodedBuffer_ = (unsigned char*) malloc( info.videoCodec.width * info.videoCodec.height * 3 / 2); unpackagedBuffer_ = (unsigned char*) malloc(UNPACKAGED_BUFFER_SIZE); @@ -50,7 +50,7 @@ namespace erizo { } if (mediaInfo.hasAudio) { printf("Init AUDIO processor\n"); - mediaInfo.audioCodec.codec =CODEC_ID_PCM_MULAW; + mediaInfo.audioCodec.codec = AUDIO_CODEC_PCM_MULAW_8; decodedAudioBuffer_ = (unsigned char*) malloc(UNPACKAGED_BUFFER_SIZE); unpackagedAudioBuffer_ = (unsigned char*) malloc( UNPACKAGED_BUFFER_SIZE); @@ -114,7 +114,7 @@ namespace erizo { bool InputProcessor::initAudioDecoder() { - aDecoder = avcodec_find_decoder(mediaInfo.audioCodec.codec); + aDecoder = avcodec_find_decoder(static_cast(mediaInfo.audioCodec.codec)); if (!aDecoder) { printf("Decoder de audio no encontrado"); return false; @@ -144,8 +144,8 @@ namespace erizo { bool InputProcessor::initVideoDecoder() { - videoCodecInfo& videoCodec = mediaInfo.videoCodec; - vDecoder = avcodec_find_decoder(videoCodec.codec); + VideoCodecInfo& videoCodec = mediaInfo.videoCodec; + vDecoder = avcodec_find_decoder(static_cast(videoCodec.codec)); if (!vDecoder) { printf("Decoder de vídeo no encontrado"); return false; @@ -463,21 +463,23 @@ namespace erizo { rtpBuffer_ = (unsigned char*) malloc(PACKAGED_BUFFER_SIZE); if (mediaInfo.hasVideo) { - this->mediaInfo.videoCodec.codec = CODEC_ID_VP8; + this->mediaInfo.videoCodec.codec = VIDEO_CODEC_VP8; if (!this->initVideoCoder()) { printf("Fallo aqui\n"); } this->initVideoPackager(); } if (mediaInfo.hasAudio) { + printf("Init AUDIO processor\n"); - mediaInfo.audioCodec.codec = CODEC_ID_MP2;//CODEC_ID_PCM_MULAW; + mediaInfo.audioCodec.codec = AUDIO_CODEC_PCM_MULAW_8; mediaInfo.audioCodec.sampleRate= 44100; mediaInfo.audioCodec.bitRate = 64000; encodedAudioBuffer_ = (unsigned char*) malloc(UNPACKAGED_BUFFER_SIZE); packagedAudioBuffer_ = (unsigned char*) malloc(UNPACKAGED_BUFFER_SIZE); this->initAudioCoder(); this->initAudioPackager(); + } @@ -506,7 +508,7 @@ namespace erizo { bool OutputProcessor::initAudioCoder() { - aCoder = avcodec_find_encoder(mediaInfo.audioCodec.codec); + aCoder = avcodec_find_encoder(static_cast(mediaInfo.audioCodec.codec)); if (!aCoder) { printf("Encoder de audio no encontrado"); exit(0); @@ -537,7 +539,7 @@ namespace erizo { bool OutputProcessor::initVideoCoder() { - vCoder = avcodec_find_encoder(mediaInfo.videoCodec.codec); + vCoder = avcodec_find_encoder(static_cast(mediaInfo.videoCodec.codec)); if (!vCoder) { printf("Encoder de vídeo no encontrado"); return false; diff --git a/src/erizo/media/MediaProcessor.h b/src/erizo/media/MediaProcessor.h index 81e8677963..2b25c01890 100644 --- a/src/erizo/media/MediaProcessor.h +++ b/src/erizo/media/MediaProcessor.h @@ -6,8 +6,9 @@ #include #include -#include "utils/RtpParser.h" +#include "rtp/RtpParser.h" #include "../MediaDefinitions.h" +#include "codecs/CodecFactory.h" extern "C" { #include @@ -17,20 +18,6 @@ extern "C" { namespace erizo { -struct audioCodecInfo { - enum CodecID codec; - int bitRate; - int sampleRate; -}; - -struct videoCodecInfo { - enum CodecID codec; - int width; - int height; - int bitRate; - int frameRate; - int maxInter; -}; struct RTPInfo { enum CodecID codec; @@ -59,8 +46,8 @@ struct MediaInfo { ProcessorType proccessorType; RTPInfo rtpVideoInfo; RTPInfo rtpAudioInfo; - videoCodecInfo videoCodec; - audioCodecInfo audioCodec; + VideoCodecInfo videoCodec; + AudioCodecInfo audioCodec; }; diff --git a/src/erizo/media/codecs/CodecFactory.cpp b/src/erizo/media/codecs/CodecFactory.cpp new file mode 100644 index 0000000000..d0b3ed56cf --- /dev/null +++ b/src/erizo/media/codecs/CodecFactory.cpp @@ -0,0 +1,27 @@ +/* + *CodecFactory.cpp + */ +#include "CodecFactory.h" +#include "VideoCodec.h" + +#include +extern "C" { +#include +} + +namespace erizo { + + CodecFactory* CodecFactory::getInstance(){ + if (theInstance==0){ + theInstance = new CodecFactory(); + avcodec_register_all(); + } + return theInstance; + } + CodecFactory::CodecFactory(){ + + } + +} + + diff --git a/src/erizo/media/codecs/CodecFactory.h b/src/erizo/media/codecs/CodecFactory.h new file mode 100644 index 0000000000..c37931ba21 --- /dev/null +++ b/src/erizo/media/codecs/CodecFactory.h @@ -0,0 +1,45 @@ +/* + * CodecFactory.h + */ +#ifndef CODECFACTORY_H_ +#define CODECFACTORY_H_ + +#include + +namespace erizo{ + + enum VideoCodecID{ + VIDEO_CODEC_VP8, + VIDEO_CODEC_H264 + }; + + enum AudioCodecID{ + AUDIO_CODEC_PCM_MULAW_8 + }; + + struct VideoCodecInfo { + VideoCodecID codec; + int payloadType; + int width; + int height; + int bitRate; + int frameRate; + }; + + struct AudioCodecInfo { + AudioCodecID codec; + int bitRate; + int sampleRate; + }; + + class CodecFactory{ + public: + static CodecFactory* getInstance(); + protected: + CodecFactory(); + private: + static CodecFactory* theInstance; + }; + +} +#endif /* CODECFACTORY_H_ */ diff --git a/src/erizo/media/codecs/Codecs.h b/src/erizo/media/codecs/Codecs.h new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/erizo/media/codecs/VideoCodec.cpp b/src/erizo/media/codecs/VideoCodec.cpp new file mode 100644 index 0000000000..4c39100d2b --- /dev/null +++ b/src/erizo/media/codecs/VideoCodec.cpp @@ -0,0 +1,258 @@ +/** + * VP8Codec.pp + */ + +#include "VideoCodec.h" +#include "CodecFactory.h" + +#include +#include +extern "C" { +#include +} + +namespace erizo { + inline CodecID + VideoCodecID2ffmpegDecoderID(VideoCodecID codec) + { + switch (codec) + { + case VIDEO_CODEC_H264: return CODEC_ID_H264; + case VIDEO_CODEC_VP8: return CODEC_ID_VP8; + default: printf("Unknown codec\n"); return CODEC_ID_VP8; + } + } + + VideoEncoder::VideoEncoder(){ + } + + int VideoEncoder::initEncoder(const VideoCodecInfo& info){ + vCoder = avcodec_find_encoder(static_cast(info.codec)); + if (!vCoder) { + printf("Encoder de vídeo no encontrado"); + return -1; + } + + vCoderContext = avcodec_alloc_context3(vCoder); + if (!vCoderContext) { + printf("Error de memoria en coder de vídeo"); + return -2; + } + + vCoderContext->bit_rate = info.bitRate; + vCoderContext->rc_min_rate = info.bitRate; // + vCoderContext->rc_max_rate = info.bitRate; // VPX_CBR + vCoderContext->qmin = 8; + vCoderContext->qmax = 56; // rc_quantifiers + // vCoderContext->frame_skip_threshold = 30; + vCoderContext->rc_buffer_aggressivity = 1; + vCoderContext->rc_buffer_size = vCoderContext->bit_rate; + vCoderContext->rc_initial_buffer_occupancy = vCoderContext->bit_rate / 2; + vCoderContext->width = info.width; + vCoderContext->height = info.height; + vCoderContext->pix_fmt = PIX_FMT_YUV420P; + vCoderContext->time_base = (AVRational) {1, 90000}; + vCoderContext->sample_aspect_ratio = + (AVRational) {info.width,info.height}; + + if (avcodec_open2(vCoderContext, vCoder, NULL) < 0) { + printf("Error al abrir el decoder de vídeo"); + return -3; + } + + cPicture = avcodec_alloc_frame(); + if (!cPicture) { + printf("Error de memoria en frame del coder de vídeo"); + return -4; + } + + printf("videoCoder configured successfully %d x %d\n", vCoderContext->width, + vCoderContext->height); + return 0; + } + + int VideoEncoder::encodeVideo (uint8_t* inBuffer, int inLength, uint8_t* outBuffer, int outLength, bool& hasFrame){ + + int size = vCoderContext->width * vCoderContext->height; + printf("vCoderContext width %d\n", vCoderContext->width); + + cPicture->pts = AV_NOPTS_VALUE; + cPicture->data[0] = (unsigned char*) inBuffer; + cPicture->data[1] = (unsigned char*) inBuffer + size; + cPicture->data[2] = (unsigned char*) inBuffer + size + size / 4; + cPicture->linesize[0] = vCoderContext->width; + cPicture->linesize[1] = vCoderContext->width / 2; + cPicture->linesize[2] = vCoderContext->width / 2; + + AVPacket pkt; + av_init_packet(&pkt); + pkt.data = inBuffer; + pkt.size = inLength; + + int ret = 0; + int got_packet = 0; + printf( + "Before encoding inBufflen %d, size %d, codecontext width %d pkt->size%d\n", + inLength, size, vCoderContext->width, pkt.size); + ret = avcodec_encode_video2(vCoderContext, &pkt, cPicture, &got_packet); + printf("Encoded video size %u, ret %d, got_packet %d, pts %lld, dts %lld\n", + pkt.size, ret, got_packet, pkt.pts, pkt.dts); + if (!ret && got_packet && vCoderContext->coded_frame) { + vCoderContext->coded_frame->pts = pkt.pts; + vCoderContext->coded_frame->key_frame = + !!(pkt.flags & AV_PKT_FLAG_KEY); + } + /* free any side data since we cannot return it */ + // if (pkt.side_data_elems > 0) { + // int i; + // for (i = 0; i < pkt.side_data_elems; i++) + // av_free(pkt.side_data[i].data); + // av_freep(&pkt.side_data); + // pkt.side_data_elems = 0; + // } + return ret ? ret : pkt.size; + + return ret; + } + + int VideoEncoder::closeEncoder() { + return 0; + } + + + VideoDecoder::VideoDecoder(){ + vDecoder = 0; + vDecoderContext = 0; + } + + int VideoDecoder::initDecoder (const VideoCodecInfo& info){ + vDecoder = avcodec_find_decoder(CODEC_ID_VP8); + if (!vDecoder) { + printf("Error getting video decoder\n"); + return -1; + } + + vDecoderContext = avcodec_alloc_context3(vDecoder); + if (!vDecoderContext) { + printf("Error getting allocating decoder context"); + return -1; + } + + vDecoderContext->width = info.width; + vDecoderContext->height = info.height; + + if (avcodec_open2(vDecoderContext, vDecoder, NULL) < 0) { + printf("Error opening video decoder\n"); + return -1; + } + + dPicture = avcodec_alloc_frame(); + if (!dPicture) { + printf("Error allocating video frame\n"); + return -1; + } + + return 0; + } + int VideoDecoder::decodeVideo(uint8_t* inBuff, int inBuffLen, + uint8_t* outBuff, int outBuffLen, bool* gotFrame){ + if (vDecoder == 0 || vDecoderContext == 0){ + printf("Init Codec First\n"); + return -1; + } + + *gotFrame = false; + + AVPacket avpkt; + av_init_packet(&avpkt); + + avpkt.data = inBuff; + avpkt.size = inBuffLen; + + int got_picture; + int len; + + while (avpkt.size > 0) { + + len = avcodec_decode_video2(vDecoderContext, dPicture, &got_picture, + &avpkt); + + if (len < 0) { + printf("Error al decodificar frame de vídeo\n"); + return -1; + } + + if (got_picture) { + *gotFrame = 1; + goto decoding; + } + avpkt.size -= len; + avpkt.data += len; + } + + if (!got_picture) { + printf("Aún no tengo frame"); + return -1; + } + +decoding: + + int outSize = vDecoderContext->height * vDecoderContext->width; + + if (outBuffLen < (outSize * 3 / 2)) { + printf("No se ha rellenado el buffer??? outBuffLen = %d\n", outBuffLen); + return outSize * 3 / 2; + } + + unsigned char *lum = outBuff; + unsigned char *cromU = outBuff + outSize; + unsigned char *cromV = outBuff + outSize + outSize / 4; + + unsigned char *src = NULL; + int src_linesize, dst_linesize; + + src_linesize = dPicture->linesize[0]; + dst_linesize = vDecoderContext->width; + src = dPicture->data[0]; + + for (int i = vDecoderContext->height; i > 0; i--) { + memcpy(lum, src, dst_linesize); + lum += dst_linesize; + src += src_linesize; + } + + src_linesize = dPicture->linesize[1]; + dst_linesize = vDecoderContext->width / 2; + src = dPicture->data[1]; + + for (int i = vDecoderContext->height / 2; i > 0; i--) { + memcpy(cromU, src, dst_linesize); + cromU += dst_linesize; + src += src_linesize; + } + + src_linesize = dPicture->linesize[2]; + dst_linesize = vDecoderContext->width / 2; + src = dPicture->data[2]; + + for (int i = vDecoderContext->height / 2; i > 0; i--) { + memcpy(cromV, src, dst_linesize); + cromV += dst_linesize; + src += src_linesize; + } + av_free_packet(&avpkt); + + return outSize * 3 / 2; + } + + int VideoDecoder::closeDecoder(){ + if (dPicture!=0) + av_free(dPicture); + if (vDecoderContext!=0){ + avcodec_close(vDecoderContext); + av_free(vDecoderContext); + } + return 0; + } + +} diff --git a/src/erizo/media/codecs/VideoCodec.h b/src/erizo/media/codecs/VideoCodec.h new file mode 100644 index 0000000000..ea5816a82a --- /dev/null +++ b/src/erizo/media/codecs/VideoCodec.h @@ -0,0 +1,46 @@ +/** + * VideoCodec.h + */ + +#ifndef VIDEOCODEC_H_ +#define VIDEOCODEC_H_ + +#include "CodecFactory.h" +//Forward Declarations + +struct AVCodec; +struct AVCodecContext; +struct AVFrame; + +namespace erizo { + + class VideoEncoder { + public: + VideoEncoder(); + int initEncoder (const VideoCodecInfo& info); + int encodeVideo (uint8_t* inBuffer, int length, + uint8_t* outBuffer, int outLength, bool& hasFrame); + int closeEncoder (); + + private: + AVCodec* vCoder; + AVCodecContext* vCoderContext; + AVFrame* cPicture; + }; + + class VideoDecoder { + public: + VideoDecoder(); + int initDecoder (const VideoCodecInfo& info); + int decodeVideo(uint8_t* inBuff, int inBuffLen, + uint8_t* outBuff, int outBuffLen, bool* gotFrame); + int closeDecoder(); + + private: + AVCodec* vDecoder; + AVCodecContext* vDecoderContext; + AVFrame* dPicture; + }; + +} +#endif /* VIDEOCODEC_H_ */ diff --git a/src/erizo/media/mixers/VideoMixer.cpp b/src/erizo/media/mixers/VideoMixer.cpp new file mode 100644 index 0000000000..7ba52529f7 --- /dev/null +++ b/src/erizo/media/mixers/VideoMixer.cpp @@ -0,0 +1,45 @@ +/* + * VideoMixer.cpp + */ + +#include "VideoMixer.h" +#include "../../WebRtcConnection.h" + +namespace erizo { + VideoMixer::VideoMixer() : + MediaReceiver() { + + + } + + VideoMixer::~VideoMixer() { + } + + int VideoMixer::receiveAudioData(char* buf, int len) { + + } + + int VideoMixer::receiveVideoData(char* buf, int len) { + } + + void VideoMixer::receiveRawData(RawDataPacket& pkt) { + } + + void VideoMixer::receiveRtpData(unsigned char*rtpdata, int len) { + } + + void VideoMixer::setPublisher(WebRtcConnection* webRtcConn) { + } + + void VideoMixer::addSubscriber(WebRtcConnection* webRtcConn, + int peerId) { + } + + void VideoMixer::removeSubscriber(int peerId) { + } + + void VideoMixer::closeAll() { + } + +}/* namespace erizo */ + diff --git a/src/erizo/media/mixers/VideoMixer.h b/src/erizo/media/mixers/VideoMixer.h new file mode 100644 index 0000000000..83f772e3e9 --- /dev/null +++ b/src/erizo/media/mixers/VideoMixer.h @@ -0,0 +1,75 @@ + +/* + * VideoMixer.h + */ + +#ifndef VIDEOMIXER_H_ +#define VIDEOMIXER_H_ + +#include +#include + +#include "../../MediaDefinitions.h" +#include "../MediaProcessor.h" + + +namespace erizo{ +class WebRtcConnection; +class RTPSink; + +/** + * Represents a One to Many connection. + * Receives media from one publisher and retransmits it to every subscriber. + */ +class VideoMixer : public MediaReceiver, public RawDataReceiver, public RTPDataReceiver { +public: + WebRtcConnection *publisher; + std::map subscribers; + + VideoMixer(); + virtual ~VideoMixer(); + /** + * Sets the Publisher + * @param webRtcConn The WebRtcConnection of the Publisher + */ + void setPublisher(WebRtcConnection* webRtcConn); + /** + * Sets the subscriber + * @param webRtcConn The WebRtcConnection of the subscriber + * @param peerId An unique Id for the subscriber + */ + void addSubscriber(WebRtcConnection* webRtcConn, int peerId); + /** + * Eliminates the subscriber given its peer id + * @param peerId the peerId + */ + void removeSubscriber(int peerId); + int receiveAudioData(char* buf, int len); + int receiveVideoData(char* buf, int len); + void receiveRawData(RawDataPacket& packet); + void receiveRtpData(unsigned char*rtpdata, int len); + +// MediaProcessor *mp; + InputProcessor* ip; + OutputProcessor* op; + /** + * Closes all the subscribers and the publisher, the object is useless after this + */ + void closeAll(); + +private: + char* sendVideoBuffer_; + char* sendAudioBuffer_; + char* unpackagedBuffer_; + char* decodedBuffer_; + char* codedBuffer_; + RTPSink* sink_; + std::vector head; + int gotFrame_,gotDecodedFrame_, size_; + void sendHead(WebRtcConnection* conn); + RtpParser pars; + unsigned int sentPackets_; +}; + +} /* namespace erizo */ +#endif /* VIDEOMIXER_H_ */ diff --git a/src/erizo/media/mixers/VideoUtils.cpp b/src/erizo/media/mixers/VideoUtils.cpp new file mode 100644 index 0000000000..3c6f4ec5dd --- /dev/null +++ b/src/erizo/media/mixers/VideoUtils.cpp @@ -0,0 +1,644 @@ +#include +#include + +#include "VideoUtils.h" + +// +// MIN macro +// +#define MIN(a,b) (a(format)) + { + case I420P_FORMAT: + if (outBuffLen < outW*outH*3/2) + { + printf("vRescale:: needed %d, outBuffLen = %d\n", + outW*outH*3/2, + outBuffLen + ); + return -1; + } + + //rescale luminance + vRescaleP(inBuff, + inW*inH, + outBuff, + outW*outH, + inW, + inH, + outW, + outH, + 1 // Bytes Per Pixel + ); + + //rescale chroma U + vRescaleP(inBuff+inW*inH, + inW*inH*4, + outBuff+outW*outH, + outW*outH*4, + inW/2, + inH/2, + outW/2, + outH/2, + 1 // Bytes Per Pixel + ); + + //rescale chroma V + vRescaleP(inBuff+inW*inH*5/4, + inW*inH*4, + outBuff+outW*outH*5/4, + outW*outH*4, + inW/2, + inH/2, + outW/2, + outH/2, + 1 // Bytes Per Pixel + ); + + return outW*outH*3/2; + + case RGB24_FORMAT: + case BGR24_FORMAT: + if (outBuffLen < outW*outH*3) + { + printf("vRescale:: needed %d, outBuffLen = %d\n", + outW*outH*3, + outBuffLen + ); + return -1; + } + + //rescale rgb plane + vRescaleP(inBuff, + inW*inH, + outBuff, + outW*outH, + inW, + inH, + outW, + outH, + 3 // Bytes Per Pixel + ); + + return outW*outH*3; + + default: + fprintf(stderr, "vRescale: not implemented for %d\n", format); + abort(); + } + return -1; +} + +inline void +vPutImageP(unsigned char *inBuff, + unsigned int inBuffLen, + unsigned char *outBuff, + unsigned int W, + unsigned int H, + unsigned int X, + unsigned int Y, + unsigned int totalW, + unsigned int totalH, + unsigned int BPP, + unsigned char *mask, + bool invert + ) +{ + unsigned lineSize1 = W*BPP; + unsigned lineSize2 = totalW*BPP; + unsigned initRectPos1 = 0; + unsigned initRectPos2 = lineSize2*Y + X*BPP; + unsigned position1 = 0; + unsigned position2 = 0; + + if (mask) + { + for (unsigned i = 0; i < H; i++) + { + position1 = initRectPos1 + lineSize1*i; //save image1 position + position2 = initRectPos2 + lineSize2*i; //save image2 position + for (unsigned j = 0; j < lineSize1; j++) + { + if (((bool)mask[position2+j])^invert) + { + outBuff[position2+j] = inBuff[position1+j]; //copy pixel + } + } + } + } + else + { + for (unsigned i = 0; i < H; i++) + { + position1 = initRectPos1 + lineSize1*i; //save image1 position + position2 = initRectPos2 + lineSize2*i; //save image2 position + memcpy(&outBuff[position2],&inBuff[position1],lineSize1); //copy line + } + } +} + +int +VideoUtils::vPutImage(unsigned char *inBuff, + unsigned int inBuffLen, + unsigned char *outBuff, + unsigned int outBuffLen, + unsigned int inW, + unsigned int inH, + unsigned int outW, + unsigned int outH, + unsigned int posX, + unsigned int posY, + unsigned int totalW, + unsigned int totalH, + uint32_t format, + unsigned char *mask, + bool invert + ) +{ + if ((outW > totalW) || (outH > totalH)) + { + printf("vPutImage : output resolution greater" + " than total image resolution!\n" + ); + return -1; + } + + if (posX + outW>totalW) outW = totalW-posX; + if (posY + outH>totalH) outH = totalH-posY; + + double factor = 0; + int BPP = 0; + switch (format) + { + case I420P_FORMAT: + factor = 1.5; + BPP = 1; + break; + case RGB24_FORMAT: + case BGR24_FORMAT: + factor = 3; + BPP = 3; + break; + default: + printf("vPutImage : unknown format %d\n", format); + abort(); + } + + if (outBuffLen < outW*outH*BPP*factor) + { + printf("vPutImage :: needed %f, outBuffLen = %d\n", + totalW*totalH*BPP*factor, + outBuffLen + ); + return -1; + } + + unsigned char * image = inBuff; + + int len = inBuffLen; + if ((inW != outW) || + (inH != outH)) + { + len = int(outW*outH*factor); + image = new unsigned char[len]; + int ret = vRescale (inBuff, + inBuffLen, + image, + len, + inW, + inH, + outW, + outH, + format + ); + + if (ret<=0) + { + printf("vPutImage : vRescale failed\n"); + delete [] image; + return -1; + } + } + + switch (format) + { + case I420P_FORMAT: + + //put luminance plane + vPutImageP(image, + outW*outH*BPP, + outBuff, + outW, + outH, + posX, + posY, + totalW, + totalH, + BPP, + mask, + invert + ); + + //put chroma U plane + vPutImageP(image+outW*outH*BPP, + outW*outH*BPP/4, + outBuff+totalW*totalH*BPP, + outW/2, + outH/2, + posX/2, + posY/2, + totalW/2, + totalH/2, + BPP, + mask?mask+totalW*totalH*BPP:NULL, + invert + ); + + //put chroma V plane + vPutImageP(image+outW*outH*BPP*5/4, + outW*outH*BPP/4, + outBuff+totalW*totalH*BPP*5/4, + outW/2, + outH/2, + posX/2, + posY/2, + totalW/2, + totalH/2, + BPP, + mask?mask+totalW*totalH*BPP*5/4:NULL, + invert + ); + break; + + case RGB24_FORMAT: + case BGR24_FORMAT: + + //put bgr plane + vPutImageP(image, + outW*outH*BPP, + outBuff, + outW, + outH, + posX, + posY, + totalW, + totalH, + BPP, + mask, + invert + ); + break; + + default: + printf("vPutImage : unknown format\n"); + abort(); + } + + if (image != inBuff) + { + delete[] image; + } + + return int(totalW*totalH*BPP*factor); +} + +inline void +vSetMaskRectP(unsigned char *mask, + unsigned int W, + unsigned int H, + unsigned int posX, + unsigned int posY, + unsigned int totalW, + unsigned int totalH, + bool val, + int BPP + ) +{ + unsigned lineSize1 = W*BPP; + unsigned lineSize2 = totalW*BPP; + unsigned initRectPos1 = 0; + unsigned initRectPos2 = lineSize2*posY + posX*BPP; + unsigned position1 = 0; + unsigned position2 = 0; + for(unsigned i = 0; i < H; i++) + { + position1 = initRectPos1 + lineSize1*i; //save image1 position + position2 = initRectPos2 + lineSize2*i; //save image2 position + for (unsigned j = 0; j < lineSize1; j+=BPP) + { + for (int k = 0;k + +class VideoUtils{ + + enum ImgFormat{ + I420P_FORMAT, + RGB24_FORMAT, + BGR24_FORMAT + }; + + static int + vRescale(unsigned char *inBuff, + unsigned int inBuffLen, + unsigned char *outBuff, + unsigned int outBuffLen, + unsigned int inW, + unsigned int inH, + unsigned int outW, + unsigned int outH, + uint32_t format + ); + + static int + vPutImage(unsigned char *inBuff, + unsigned int inBuffLen, + unsigned char *outBuff, + unsigned int outBuffLen, + unsigned int inW, + unsigned int inH, + unsigned int outW, + unsigned int outH, + unsigned int posX, + unsigned int posY, + unsigned int totalW, + unsigned int totalH, + uint32_t format, + unsigned char *mask = NULL, + bool invertMask = false + ); + + static void + vSetMaskRect(unsigned char *mask, + unsigned int W, + unsigned int H, + unsigned int posX, + unsigned int posY, + unsigned int totalW, + unsigned int totalH, + bool val, + uint32_t format + ); + + static int + vSetMask(unsigned char *outBuff, + unsigned outBuffLen, + unsigned char *mask, + unsigned W, + unsigned H, + unsigned totalW, + unsigned totalH, + bool val, + uint32_t format + ); +}; + +#endif //_VIDEOUTILS_H_ + diff --git a/src/erizo/media/utils/RtpHeader.h b/src/erizo/media/rtp/RtpHeader.h similarity index 100% rename from src/erizo/media/utils/RtpHeader.h rename to src/erizo/media/rtp/RtpHeader.h diff --git a/src/erizo/media/utils/RtpParser.cpp b/src/erizo/media/rtp/RtpParser.cpp similarity index 100% rename from src/erizo/media/utils/RtpParser.cpp rename to src/erizo/media/rtp/RtpParser.cpp diff --git a/src/erizo/media/utils/RtpParser.h b/src/erizo/media/rtp/RtpParser.h similarity index 100% rename from src/erizo/media/utils/RtpParser.h rename to src/erizo/media/rtp/RtpParser.h diff --git a/src/erizo/media/utils/RtpVP8Fragmenter.cpp b/src/erizo/media/rtp/RtpVP8Fragmenter.cpp similarity index 100% rename from src/erizo/media/utils/RtpVP8Fragmenter.cpp rename to src/erizo/media/rtp/RtpVP8Fragmenter.cpp diff --git a/src/erizo/media/utils/RtpVP8Fragmenter.h b/src/erizo/media/rtp/RtpVP8Fragmenter.h similarity index 100% rename from src/erizo/media/utils/RtpVP8Fragmenter.h rename to src/erizo/media/rtp/RtpVP8Fragmenter.h From 0c777842971135357a3d33c2c682fd6686214a85 Mon Sep 17 00:00:00 2001 From: Pedro Rodriguez Date: Wed, 17 Oct 2012 18:45:36 +0200 Subject: [PATCH 22/29] updated readme for media branch --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 56d00438d0..a5bdbe9c19 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Erizo, a C/C++ Multipoint Control Unit (MCU) Library for WebRTC - +*Warning: This is the 'media' branch, it is highly unstable* Erizo is a project that aims to implement a library able to communicate with WebRTC (http://www.webrtc.org) browser clients in order to provide advanced communication services. Currently it is tested on Ubuntu 11.10 and above but it should be able to be compiled on other distributions. Updated code documentation can be found at http://ging.github.com/erizo From 02fe97963f38ea0cfbf61014bb6b0ada39b9508b Mon Sep 17 00:00:00 2001 From: Pedro Rodriguez Date: Wed, 17 Oct 2012 19:46:51 +0300 Subject: [PATCH 23/29] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index a5bdbe9c19..a3af07ede8 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ # Erizo, a C/C++ Multipoint Control Unit (MCU) Library for WebRTC *Warning: This is the 'media' branch, it is highly unstable* + Erizo is a project that aims to implement a library able to communicate with WebRTC (http://www.webrtc.org) browser clients in order to provide advanced communication services. Currently it is tested on Ubuntu 11.10 and above but it should be able to be compiled on other distributions. Updated code documentation can be found at http://ging.github.com/erizo From 5c63343176bec3744fb4a9b4327aa60828dc24bc Mon Sep 17 00:00:00 2001 From: Pedro Rodriguez Date: Wed, 17 Oct 2012 19:45:32 +0200 Subject: [PATCH 24/29] Added license --- src/erizo/media/rtp/RtpParser.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/erizo/media/rtp/RtpParser.cpp b/src/erizo/media/rtp/RtpParser.cpp index 45313f0a88..1e6dc967d4 100644 --- a/src/erizo/media/rtp/RtpParser.cpp +++ b/src/erizo/media/rtp/RtpParser.cpp @@ -1,3 +1,17 @@ +/* + * This file contains third party code: copyright below + */ + +/* + * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + #include #include #include From e07f85d0fd5e2ea91935c00be5ec6cb150c5b80a Mon Sep 17 00:00:00 2001 From: Pedro Rodriguez Date: Wed, 17 Oct 2012 19:50:27 +0200 Subject: [PATCH 25/29] Started cleanup of codecs to new codecs/VideoCodec --- src/erizo/media/MediaProcessor.cpp | 191 +---------------------------- 1 file changed, 3 insertions(+), 188 deletions(-) diff --git a/src/erizo/media/MediaProcessor.cpp b/src/erizo/media/MediaProcessor.cpp index ada64cdf99..afc9c6ba3f 100644 --- a/src/erizo/media/MediaProcessor.cpp +++ b/src/erizo/media/MediaProcessor.cpp @@ -144,33 +144,6 @@ namespace erizo { bool InputProcessor::initVideoDecoder() { - VideoCodecInfo& videoCodec = mediaInfo.videoCodec; - vDecoder = avcodec_find_decoder(static_cast(videoCodec.codec)); - if (!vDecoder) { - printf("Decoder de vídeo no encontrado"); - return false; - } - - vDecoderContext = avcodec_alloc_context3(vDecoder); - if (!vDecoderContext) { - printf("Error de memoria en decoder de vídeo"); - return false; - } - - vDecoderContext->width = videoCodec.width; - vDecoderContext->height = videoCodec.height; - - if (avcodec_open2(vDecoderContext, vDecoder, NULL) < 0) { - printf("Error al abrir el decoder de vídeo"); - return false; - } - - dPicture = avcodec_alloc_frame(); - if (!dPicture) { - printf("Error de memoria en frame del decoder de vídeo"); - return false; - } - videoDecoder = 1; return true; } @@ -278,95 +251,8 @@ namespace erizo { int InputProcessor::decodeVideo(unsigned char* inBuff, int inBuffLen, unsigned char* outBuff, int outBuffLen, int* gotFrame) { - - if (videoDecoder == 0) { - printf("No se han inicializado los parámetros del videoDecoder"); - return -1; - } - - *gotFrame = 0; - - AVPacket avpkt; - av_init_packet(&avpkt); - - avpkt.data = inBuff; - avpkt.size = inBuffLen; - - int got_picture; - int len; - - while (avpkt.size > 0) { - - len = avcodec_decode_video2(vDecoderContext, dPicture, &got_picture, - &avpkt); - - if (len < 0) { - printf("Error al decodificar frame de vídeo\n"); - return -1; - } - - if (got_picture) { - *gotFrame = 1; - goto decoding; - } - avpkt.size -= len; - avpkt.data += len; - } - - if (!got_picture) { - printf("Aún no tengo frame"); - return -1; - } - -decoding: - - // int outSize = vDecoderContext->height * vDecoderContext->width; - int outSize = mediaInfo.videoCodec.height * mediaInfo.videoCodec.width; - - if (outBuffLen < (outSize * 3 / 2)) { - printf("No se ha rellenado el buffer??? outBuffLen = %d\n", outBuffLen); - return outSize * 3 / 2; - } - - unsigned char *lum = outBuff; - unsigned char *cromU = outBuff + outSize; - unsigned char *cromV = outBuff + outSize + outSize / 4; - - unsigned char *src = NULL; - int src_linesize, dst_linesize; - - src_linesize = dPicture->linesize[0]; - dst_linesize = vDecoderContext->width; - src = dPicture->data[0]; - - for (int i = vDecoderContext->height; i > 0; i--) { - memcpy(lum, src, dst_linesize); - lum += dst_linesize; - src += src_linesize; - } - - src_linesize = dPicture->linesize[1]; - dst_linesize = vDecoderContext->width / 2; - src = dPicture->data[1]; - - for (int i = vDecoderContext->height / 2; i > 0; i--) { - memcpy(cromU, src, dst_linesize); - cromU += dst_linesize; - src += src_linesize; - } - - src_linesize = dPicture->linesize[2]; - dst_linesize = vDecoderContext->width / 2; - src = dPicture->data[2]; - - for (int i = vDecoderContext->height / 2; i > 0; i--) { - memcpy(cromV, src, dst_linesize); - cromV += dst_linesize; - src += src_linesize; - } - av_free_packet(&avpkt); - - return outSize * 3 / 2; + return 1; + } int InputProcessor::unpackageAudio(unsigned char* inBuff, int inBuffLen, @@ -539,45 +425,6 @@ namespace erizo { bool OutputProcessor::initVideoCoder() { - vCoder = avcodec_find_encoder(static_cast(mediaInfo.videoCodec.codec)); - if (!vCoder) { - printf("Encoder de vídeo no encontrado"); - return false; - } - - vCoderContext = avcodec_alloc_context3(vCoder); - if (!vCoderContext) { - printf("Error de memoria en coder de vídeo"); - return false; - } - - vCoderContext->bit_rate = mediaInfo.videoCodec.bitRate; - vCoderContext->rc_min_rate = mediaInfo.videoCodec.bitRate; // - vCoderContext->rc_max_rate = mediaInfo.videoCodec.bitRate; // VPX_CBR - vCoderContext->qmin = 8; - vCoderContext->qmax = 56; // rc_quantifiers - // vCoderContext->frame_skip_threshold = 30; - vCoderContext->rc_buffer_aggressivity = 1; - vCoderContext->rc_buffer_size = vCoderContext->bit_rate; - vCoderContext->rc_initial_buffer_occupancy = vCoderContext->bit_rate / 2; - vCoderContext->width = mediaInfo.videoCodec.width; - vCoderContext->height = mediaInfo.videoCodec.height; - vCoderContext->pix_fmt = PIX_FMT_YUV420P; - vCoderContext->time_base = (AVRational) {1, 90000}; - vCoderContext->sample_aspect_ratio = - (AVRational) {mediaInfo.videoCodec.width,mediaInfo.videoCodec.height}; - - if (avcodec_open2(vCoderContext, vCoder, NULL) < 0) { - printf("Error al abrir el decoder de vídeo"); - return false; - } - - cPicture = avcodec_alloc_frame(); - if (!cPicture) { - printf("Error de memoria en frame del coder de vídeo"); - return false; - } - videoCoder = 1; printf("videoCoder configured successfully %d x %d\n", vCoderContext->width, vCoderContext->height); @@ -722,38 +569,6 @@ namespace erizo { printf("No se han inicializado los parámetros del videoCoder"); return -1; } - int size = vCoderContext->width * vCoderContext->height; - printf("vCoderContext width %d\n", vCoderContext->width); - - cPicture->pts = AV_NOPTS_VALUE; - cPicture->data[0] = (unsigned char*) inBuff; - cPicture->data[1] = (unsigned char*) inBuff + size; - cPicture->data[2] = (unsigned char*) inBuff + size + size / 4; - cPicture->linesize[0] = vCoderContext->width; - cPicture->linesize[1] = vCoderContext->width / 2; - cPicture->linesize[2] = vCoderContext->width / 2; - - int ret = 0; - int got_packet = 0; - printf( - "Before encoding inBufflen %d, size %d, codecontext width %d pkt->size%d\n", - inBuffLen, size, vCoderContext->width, pkt->size); - ret = avcodec_encode_video2(vCoderContext, pkt, cPicture, &got_packet); - printf("Encoded video size %u, ret %d, got_packet %d, pts %lld, dts %lld\n", - pkt->size, ret, got_packet, pkt->pts, pkt->dts); - if (!ret && got_packet && vCoderContext->coded_frame) { - vCoderContext->coded_frame->pts = pkt->pts; - vCoderContext->coded_frame->key_frame = - !!(pkt->flags & AV_PKT_FLAG_KEY); - } - /* free any side data since we cannot return it */ - // if (pkt.side_data_elems > 0) { - // int i; - // for (i = 0; i < pkt.side_data_elems; i++) - // av_free(pkt.side_data[i].data); - // av_freep(&pkt.side_data); - // pkt.side_data_elems = 0; - // } - return ret ? ret : pkt->size; + return 1; } } /* namespace erizo */ From 64745a944db947ee1385f1dedbb1e928ffaae391 Mon Sep 17 00:00:00 2001 From: Pedro Rodriguez Date: Fri, 19 Oct 2012 15:44:36 +0200 Subject: [PATCH 26/29] Started work on video Mixer --- src/erizo/media/mixers/VideoMixer.cpp | 38 ++++++++++++++++++++++----- src/erizo/media/mixers/VideoMixer.h | 12 ++++----- 2 files changed, 37 insertions(+), 13 deletions(-) diff --git a/src/erizo/media/mixers/VideoMixer.cpp b/src/erizo/media/mixers/VideoMixer.cpp index 7ba52529f7..7b973d45c0 100644 --- a/src/erizo/media/mixers/VideoMixer.cpp +++ b/src/erizo/media/mixers/VideoMixer.cpp @@ -3,12 +3,39 @@ */ #include "VideoMixer.h" +#include "VideoUtils.h" +#include "../../RTPSink.h" #include "../../WebRtcConnection.h" namespace erizo { VideoMixer::VideoMixer() : MediaReceiver() { + sendVideoBuffer_ = (char*) malloc(2000); + sendAudioBuffer_ = (char*) malloc(2000); + + subscriber = NULL; + sentPackets_ = 0; + ip = new InputProcessor(); + sink_ = new RTPSink("127.0.0.1", "50000"); + MediaInfo m; + m.proccessorType = RTP_ONLY; + // m.videoCodec.bitRate = 2000000; + // printf("m.videoCodec.bitrate %d\n\n", m.videoCodec.bitRate); + m.hasVideo = true; + m.videoCodec.width = 640; + m.videoCodec.height = 480; + ip->init(m, this); + + MediaInfo om; + om.proccessorType = RTP_ONLY; + om.videoCodec.bitRate = 2000000; + om.videoCodec.width = 640; + om.videoCodec.height = 480; + om.videoCodec.frameRate = 20; + om.hasVideo = true; + op = new OutputProcessor(); + op->init(om, this); } @@ -20,22 +47,19 @@ namespace erizo { } int VideoMixer::receiveVideoData(char* buf, int len) { - } - void VideoMixer::receiveRawData(RawDataPacket& pkt) { } - void VideoMixer::receiveRtpData(unsigned char*rtpdata, int len) { + void VideoMixer::receiveRawData(RawDataPacket& pkt) { } - void VideoMixer::setPublisher(WebRtcConnection* webRtcConn) { + void VideoMixer::addPublisher(WebRtcConnection* webRtcConn, int peerSSRC){ } - void VideoMixer::addSubscriber(WebRtcConnection* webRtcConn, - int peerId) { + void VideoMixer::setSubscriber(WebRtcConnection* webRtcConn){ } - void VideoMixer::removeSubscriber(int peerId) { + void VideoMixer::removePublisher(int peerSSRC) { } void VideoMixer::closeAll() { diff --git a/src/erizo/media/mixers/VideoMixer.h b/src/erizo/media/mixers/VideoMixer.h index 83f772e3e9..769de7f374 100644 --- a/src/erizo/media/mixers/VideoMixer.h +++ b/src/erizo/media/mixers/VideoMixer.h @@ -23,8 +23,8 @@ class RTPSink; */ class VideoMixer : public MediaReceiver, public RawDataReceiver, public RTPDataReceiver { public: - WebRtcConnection *publisher; - std::map subscribers; + WebRtcConnection *subscriber; + std::map publishers; VideoMixer(); virtual ~VideoMixer(); @@ -32,22 +32,22 @@ class VideoMixer : public MediaReceiver, public RawDataReceiver, public RTPDataR * Sets the Publisher * @param webRtcConn The WebRtcConnection of the Publisher */ - void setPublisher(WebRtcConnection* webRtcConn); + void addPublisher(WebRtcConnection* webRtcConn, int peerSSRC); /** * Sets the subscriber * @param webRtcConn The WebRtcConnection of the subscriber * @param peerId An unique Id for the subscriber */ - void addSubscriber(WebRtcConnection* webRtcConn, int peerId); + void setSubscriber(WebRtcConnection* webRtcConn); /** * Eliminates the subscriber given its peer id * @param peerId the peerId */ - void removeSubscriber(int peerId); + void removePublisher(int peerSSRC); int receiveAudioData(char* buf, int len); int receiveVideoData(char* buf, int len); void receiveRawData(RawDataPacket& packet); - void receiveRtpData(unsigned char*rtpdata, int len); + void receiveRtpData(); // MediaProcessor *mp; InputProcessor* ip; From c6b0130090f46a1d4d697d458c5304406a6d1b70 Mon Sep 17 00:00:00 2001 From: Pedro Rodriguez Date: Wed, 24 Oct 2012 18:59:48 +0200 Subject: [PATCH 27/29] Removed CodecFactory --- src/erizo/media/MediaProcessor.h | 2 +- src/erizo/media/codecs/CodecFactory.cpp | 27 --------------- src/erizo/media/codecs/CodecFactory.h | 45 ------------------------- src/erizo/media/codecs/Codecs.h | 32 ++++++++++++++++++ src/erizo/media/codecs/VideoCodec.cpp | 2 +- src/erizo/media/codecs/VideoCodec.h | 2 +- 6 files changed, 35 insertions(+), 75 deletions(-) delete mode 100644 src/erizo/media/codecs/CodecFactory.cpp delete mode 100644 src/erizo/media/codecs/CodecFactory.h diff --git a/src/erizo/media/MediaProcessor.h b/src/erizo/media/MediaProcessor.h index 2b25c01890..0ed768e941 100644 --- a/src/erizo/media/MediaProcessor.h +++ b/src/erizo/media/MediaProcessor.h @@ -8,7 +8,7 @@ #include "rtp/RtpParser.h" #include "../MediaDefinitions.h" -#include "codecs/CodecFactory.h" +#include "codecs/Codecs.h" extern "C" { #include diff --git a/src/erizo/media/codecs/CodecFactory.cpp b/src/erizo/media/codecs/CodecFactory.cpp deleted file mode 100644 index d0b3ed56cf..0000000000 --- a/src/erizo/media/codecs/CodecFactory.cpp +++ /dev/null @@ -1,27 +0,0 @@ -/* - *CodecFactory.cpp - */ -#include "CodecFactory.h" -#include "VideoCodec.h" - -#include -extern "C" { -#include -} - -namespace erizo { - - CodecFactory* CodecFactory::getInstance(){ - if (theInstance==0){ - theInstance = new CodecFactory(); - avcodec_register_all(); - } - return theInstance; - } - CodecFactory::CodecFactory(){ - - } - -} - - diff --git a/src/erizo/media/codecs/CodecFactory.h b/src/erizo/media/codecs/CodecFactory.h deleted file mode 100644 index c37931ba21..0000000000 --- a/src/erizo/media/codecs/CodecFactory.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * CodecFactory.h - */ -#ifndef CODECFACTORY_H_ -#define CODECFACTORY_H_ - -#include - -namespace erizo{ - - enum VideoCodecID{ - VIDEO_CODEC_VP8, - VIDEO_CODEC_H264 - }; - - enum AudioCodecID{ - AUDIO_CODEC_PCM_MULAW_8 - }; - - struct VideoCodecInfo { - VideoCodecID codec; - int payloadType; - int width; - int height; - int bitRate; - int frameRate; - }; - - struct AudioCodecInfo { - AudioCodecID codec; - int bitRate; - int sampleRate; - }; - - class CodecFactory{ - public: - static CodecFactory* getInstance(); - protected: - CodecFactory(); - private: - static CodecFactory* theInstance; - }; - -} -#endif /* CODECFACTORY_H_ */ diff --git a/src/erizo/media/codecs/Codecs.h b/src/erizo/media/codecs/Codecs.h index e69de29bb2..9bbb3333e9 100644 --- a/src/erizo/media/codecs/Codecs.h +++ b/src/erizo/media/codecs/Codecs.h @@ -0,0 +1,32 @@ + +#ifndef CODECS_H_ +#define CODECS_H_ + +#include +namespace erizo{ + + enum VideoCodecID{ + VIDEO_CODEC_VP8, + VIDEO_CODEC_H264 + }; + + enum AudioCodecID{ + AUDIO_CODEC_PCM_MULAW_8 + }; + + struct VideoCodecInfo { + VideoCodecID codec; + int payloadType; + int width; + int height; + int bitRate; + int frameRate; + }; + + struct AudioCodecInfo { + AudioCodecID codec; + int bitRate; + int sampleRate; + }; +} +#endif /* CODECS_H_ */ diff --git a/src/erizo/media/codecs/VideoCodec.cpp b/src/erizo/media/codecs/VideoCodec.cpp index 4c39100d2b..d10dc1b96f 100644 --- a/src/erizo/media/codecs/VideoCodec.cpp +++ b/src/erizo/media/codecs/VideoCodec.cpp @@ -3,7 +3,7 @@ */ #include "VideoCodec.h" -#include "CodecFactory.h" +#include "Codecs.h" #include #include diff --git a/src/erizo/media/codecs/VideoCodec.h b/src/erizo/media/codecs/VideoCodec.h index ea5816a82a..0593b9e42e 100644 --- a/src/erizo/media/codecs/VideoCodec.h +++ b/src/erizo/media/codecs/VideoCodec.h @@ -5,7 +5,7 @@ #ifndef VIDEOCODEC_H_ #define VIDEOCODEC_H_ -#include "CodecFactory.h" +#include "Codecs.h" //Forward Declarations struct AVCodec; From 84666d5a25d335ba665cf059883b2d6b67da932e Mon Sep 17 00:00:00 2001 From: Pedro Rodriguez Date: Fri, 26 Oct 2012 16:33:24 +0200 Subject: [PATCH 28/29] Finished moving codecs out of MediaProcessor to VideoCodec --- src/erizo/OneToManyProcessor.cpp | 8 +-- src/erizo/media/MediaProcessor.cpp | 86 ++++++++------------------- src/erizo/media/MediaProcessor.h | 18 ++---- src/erizo/media/codecs/VideoCodec.cpp | 44 ++++++-------- src/erizo/media/codecs/VideoCodec.h | 8 +-- src/erizo/media/mixers/VideoUtils.cpp | 3 + src/erizo/media/mixers/VideoUtils.h | 4 ++ 7 files changed, 64 insertions(+), 107 deletions(-) diff --git a/src/erizo/OneToManyProcessor.cpp b/src/erizo/OneToManyProcessor.cpp index d61fec57c5..8e1c3b4cb1 100644 --- a/src/erizo/OneToManyProcessor.cpp +++ b/src/erizo/OneToManyProcessor.cpp @@ -31,6 +31,7 @@ OneToManyProcessor::OneToManyProcessor() : m.audioCodec.bitRate = 64000; } + printf("init ip\n"); ip->init(m, this); MediaInfo om; @@ -84,9 +85,8 @@ int OneToManyProcessor::receiveVideoData(char* buf, int len) { memcpy(sendVideoBuffer_, buf, len); RTPHeader* theHead = reinterpret_cast(buf); - printf("Probando nuevo header\n\n"); - printf("extension %d pt %u\n", theHead->getExtension(), - theHead->getPayloadType()); +// printf("extension %d pt %u\n", theHead->getExtension(), +// theHead->getPayloadType()); if (theHead->getPayloadType() == 100) { ip->receiveVideoData(sendVideoBuffer_, len); @@ -114,7 +114,7 @@ int OneToManyProcessor::receiveVideoData(char* buf, int len) { } void OneToManyProcessor::receiveRawData(RawDataPacket& pkt) { - printf("Received %d\n", pkt.length); +// printf("Received %d\n", pkt.length); op->receiveRawData(pkt); } diff --git a/src/erizo/media/MediaProcessor.cpp b/src/erizo/media/MediaProcessor.cpp index afc9c6ba3f..b07e2ad4e7 100644 --- a/src/erizo/media/MediaProcessor.cpp +++ b/src/erizo/media/MediaProcessor.cpp @@ -3,6 +3,7 @@ #include "MediaProcessor.h" #include "rtp/RtpVP8Fragmenter.h" #include "rtp/RtpHeader.h" +#include "codecs/VideoCodec.h" namespace erizo { @@ -17,7 +18,6 @@ namespace erizo { upackagedSize_ = 0; decodedBuffer_ = NULL; - avcodec_register_all(); av_register_all(); } @@ -28,9 +28,7 @@ namespace erizo { } if (videoDecoder == 1) { - avcodec_close(vDecoderContext); - av_free(vDecoderContext); - av_free(dPicture); + vDecoder.closeDecoder(); } if (decodedBuffer_ != NULL) { free(decodedBuffer_); @@ -45,8 +43,9 @@ namespace erizo { decodedBuffer_ = (unsigned char*) malloc( info.videoCodec.width * info.videoCodec.height * 3 / 2); unpackagedBuffer_ = (unsigned char*) malloc(UNPACKAGED_BUFFER_SIZE); - this->initVideoDecoder(); - this->initVideoUnpackager(); + if(!vDecoder.initDecoder(mediaInfo.videoCodec)); + videoDecoder = 1; + if(!this->initVideoUnpackager()); } if (mediaInfo.hasAudio) { printf("Init AUDIO processor\n"); @@ -89,11 +88,11 @@ namespace erizo { int c; int gotDecodedFrame = 0; - c = this->decodeVideo(unpackagedBuffer_, upackagedSize_, + c = vDecoder.decodeVideo(unpackagedBuffer_, upackagedSize_, decodedBuffer_, mediaInfo.videoCodec.width * mediaInfo.videoCodec.height * 3 / 2, &gotDecodedFrame); - + upackagedSize_ = 0; gotUnpackagedFrame_ = 0; printf("Bytes dec = %d\n", c); @@ -142,12 +141,6 @@ namespace erizo { } - bool InputProcessor::initVideoDecoder() { - - videoDecoder = 1; - return true; - } - bool InputProcessor::initAudioUnpackager() { audioUnpackager = 1; return true; @@ -249,12 +242,6 @@ namespace erizo { } - int InputProcessor::decodeVideo(unsigned char* inBuff, int inBuffLen, - unsigned char* outBuff, int outBuffLen, int* gotFrame) { - return 1; - - } - int InputProcessor::unpackageAudio(unsigned char* inBuff, int inBuffLen, unsigned char* outBuff) { @@ -277,8 +264,8 @@ namespace erizo { RTPHeader* head = reinterpret_cast(inBuff); - printf("PT %d, ssrc %u, extension %d\n", head->getPayloadType(), head->getSSRC(), - head->getExtension()); +// printf("PT %d, ssrc %u, extension %d\n", head->getPayloadType(), head->getSSRC(), +// head->getExtension()); if ( head->getSSRC() != 55543 /*&& head->payloadtype!=101*/) { return -1; } @@ -286,7 +273,7 @@ namespace erizo { return -1; } - printf("RTP header length: %d", head->getHeaderLength()); //Should include extensions +// printf("RTP header length: %d", head->getHeaderLength()); //Should include extensions int l = inBuffLen - head->getHeaderLength(); inBuffOffset+=head->getHeaderLength(); @@ -325,9 +312,7 @@ namespace erizo { } if (videoCoder == 1) { - avcodec_close(vCoderContext); - av_free(vCoderContext); - av_free(cPicture); + vCoder.closeEncoder(); } if (encodedBuffer_) { free(encodedBuffer_); @@ -350,8 +335,8 @@ namespace erizo { if (mediaInfo.hasVideo) { this->mediaInfo.videoCodec.codec = VIDEO_CODEC_VP8; - if (!this->initVideoCoder()) { - printf("Fallo aqui\n"); + if (vCoder.initEncoder(mediaInfo.videoCodec)) { + printf("Error initing encoder\n"); } this->initVideoPackager(); } @@ -365,7 +350,6 @@ namespace erizo { packagedAudioBuffer_ = (unsigned char*) malloc(UNPACKAGED_BUFFER_SIZE); this->initAudioCoder(); this->initAudioPackager(); - } @@ -374,22 +358,20 @@ namespace erizo { void OutputProcessor::receiveRawData(RawDataPacket& packet) { - AVPacket pkt; - av_init_packet(&pkt); - pkt.data = encodedBuffer_; - pkt.size = UNPACKAGED_BUFFER_SIZE; + int hasFrame = 0; if (packet.type == VIDEO) { - int a = this->encodeVideo(packet.data, packet.length, &pkt); + printf("Encoding video: size %d\n", packet.length); + int a = vCoder.encodeVideo(packet.data, packet.length, encodedBuffer_,UNPACKAGED_BUFFER_SIZE,hasFrame); if (a > 0) - int b = this->packageVideo(&pkt, packagedBuffer_); + int b = this->packageVideo(encodedBuffer_, a, packagedBuffer_); } else { - int a = this->encodeAudio(packet.data, packet.length, &pkt); - if (a > 0) { - printf("GUAY a %d\n", a); - } +// int a = this->encodeAudio(packet.data, packet.length, &pkt); +// if (a > 0) { +// printf("GUAY a %d\n", a); +// } } - av_free_packet(&pkt); +// av_free_packet(&pkt); } bool OutputProcessor::initAudioCoder() { @@ -423,14 +405,6 @@ namespace erizo { return true; } - bool OutputProcessor::initVideoCoder() { - - videoCoder = 1; - printf("videoCoder configured successfully %d x %d\n", vCoderContext->width, - vCoderContext->height); - return true; - } - bool OutputProcessor::initAudioPackager() { audioPackager = 1; return true; @@ -467,16 +441,16 @@ namespace erizo { // rtpReceiver_->receiveRtpData(rtpBuffer_, (inBuffLen + RTP_HEADER_LEN)); } - int OutputProcessor::packageVideo(AVPacket* pkt, unsigned char* outBuff) { + int OutputProcessor::packageVideo(unsigned char* inBuff, int buffSize, unsigned char* outBuff) { if (videoPackager == 0) { printf("No se ha inicailizado el codec de output vídeo RTP"); return -1; } - printf("To packetize %u\n", pkt->size); - if (pkt->size <= 0) + printf("To packetize %u\n", buffSize); + if (buffSize <= 0) return -1; - RtpVP8Fragmenter frag(pkt->data, pkt->size, 1100); + RtpVP8Fragmenter frag(inBuff, buffSize, 1100); bool lastFrame = false; unsigned int outlen = 0; timeval time; @@ -563,12 +537,4 @@ namespace erizo { } - int OutputProcessor::encodeVideo(unsigned char* inBuff, int inBuffLen, - AVPacket* pkt) { - if (videoCoder == 0) { - printf("No se han inicializado los parámetros del videoCoder"); - return -1; - } - return 1; - } } /* namespace erizo */ diff --git a/src/erizo/media/MediaProcessor.h b/src/erizo/media/MediaProcessor.h index 0ed768e941..d3523ead1d 100644 --- a/src/erizo/media/MediaProcessor.h +++ b/src/erizo/media/MediaProcessor.h @@ -9,6 +9,7 @@ #include "rtp/RtpParser.h" #include "../MediaDefinitions.h" #include "codecs/Codecs.h" +#include "codecs/VideoCodec.h" extern "C" { #include @@ -111,12 +112,10 @@ class InputProcessor: MediaReceiver { AVCodec* aDecoder; AVCodecContext* aDecoderContext; - AVCodec* vDecoder; - AVCodecContext* vDecoderContext; - AVFrame* dPicture; AVFormatContext* aInputFormatContext; AVInputFormat* aInputFormat; + VideoDecoder vDecoder; RTPInfo* vRTPInfo; @@ -128,15 +127,12 @@ class InputProcessor: MediaReceiver { erizo::RtpParser pars; bool initAudioDecoder(); - bool initVideoDecoder(); bool initAudioUnpackager(); bool initVideoUnpackager(); int decodeAudio(unsigned char* inBuff, int inBuffLen, unsigned char* outBuff); - int decodeVideo(unsigned char* inBuff, int inBuffLen, - unsigned char* outBuff, int outBuffLen, int* gotFrame); int unpackageAudio(unsigned char* inBuff, int inBuffLen, unsigned char* outBuff); @@ -180,9 +176,8 @@ class OutputProcessor: public RawDataReceiver { AVCodec* aCoder; AVCodecContext* aCoderContext; - AVCodec* vCoder; - AVCodecContext* vCoderContext; - AVFrame* cPicture; + VideoEncoder vCoder; + AVFormatContext* aOutputFormatContext; AVOutputFormat* aOutputFormat; @@ -196,7 +191,6 @@ class OutputProcessor: public RawDataReceiver { RtpParser pars; bool initAudioCoder(); - bool initVideoCoder(); bool initAudioPackager(); bool initVideoPackager(); @@ -204,12 +198,10 @@ class OutputProcessor: public RawDataReceiver { int encodeAudio(unsigned char* inBuff, int nSamples, AVPacket* pkt); - int encodeVideo(unsigned char* inBuff, int inBuffLen, AVPacket* pkt); - int packageAudio(unsigned char* inBuff, int inBuffLen, unsigned char* outBuff); - int packageVideo(AVPacket* pkt, unsigned char* outBuff); + int packageVideo(unsigned char* inBuff, int buffSize, unsigned char* outBuff); }; } /* namespace erizo */ diff --git a/src/erizo/media/codecs/VideoCodec.cpp b/src/erizo/media/codecs/VideoCodec.cpp index d10dc1b96f..ddbaef9f21 100644 --- a/src/erizo/media/codecs/VideoCodec.cpp +++ b/src/erizo/media/codecs/VideoCodec.cpp @@ -24,18 +24,19 @@ namespace erizo { } VideoEncoder::VideoEncoder(){ + avcodec_register_all(); } int VideoEncoder::initEncoder(const VideoCodecInfo& info){ - vCoder = avcodec_find_encoder(static_cast(info.codec)); + vCoder = avcodec_find_encoder(VideoCodecID2ffmpegDecoderID(info.codec)); if (!vCoder) { - printf("Encoder de vídeo no encontrado"); + printf("Video codec not found for encoder"); return -1; } vCoderContext = avcodec_alloc_context3(vCoder); if (!vCoderContext) { - printf("Error de memoria en coder de vídeo"); + printf("Error allocating vCoderContext"); return -2; } @@ -56,13 +57,13 @@ namespace erizo { (AVRational) {info.width,info.height}; if (avcodec_open2(vCoderContext, vCoder, NULL) < 0) { - printf("Error al abrir el decoder de vídeo"); + printf("Error opening video decoder"); return -3; } cPicture = avcodec_alloc_frame(); if (!cPicture) { - printf("Error de memoria en frame del coder de vídeo"); + printf("Error allocating video frame"); return -4; } @@ -71,23 +72,23 @@ namespace erizo { return 0; } - int VideoEncoder::encodeVideo (uint8_t* inBuffer, int inLength, uint8_t* outBuffer, int outLength, bool& hasFrame){ + int VideoEncoder::encodeVideo (unsigned char* inBuffer, int inLength, unsigned char* outBuffer, int outLength, int& hasFrame){ int size = vCoderContext->width * vCoderContext->height; printf("vCoderContext width %d\n", vCoderContext->width); cPicture->pts = AV_NOPTS_VALUE; - cPicture->data[0] = (unsigned char*) inBuffer; - cPicture->data[1] = (unsigned char*) inBuffer + size; - cPicture->data[2] = (unsigned char*) inBuffer + size + size / 4; + cPicture->data[0] = inBuffer; + cPicture->data[1] = inBuffer + size; + cPicture->data[2] = inBuffer + size + size / 4; cPicture->linesize[0] = vCoderContext->width; cPicture->linesize[1] = vCoderContext->width / 2; cPicture->linesize[2] = vCoderContext->width / 2; AVPacket pkt; av_init_packet(&pkt); - pkt.data = inBuffer; - pkt.size = inLength; + pkt.data = outBuffer; + pkt.size = outLength; int ret = 0; int got_packet = 0; @@ -102,17 +103,7 @@ namespace erizo { vCoderContext->coded_frame->key_frame = !!(pkt.flags & AV_PKT_FLAG_KEY); } - /* free any side data since we cannot return it */ - // if (pkt.side_data_elems > 0) { - // int i; - // for (i = 0; i < pkt.side_data_elems; i++) - // av_free(pkt.side_data[i].data); - // av_freep(&pkt.side_data); - // pkt.side_data_elems = 0; - // } return ret ? ret : pkt.size; - - return ret; } int VideoEncoder::closeEncoder() { @@ -121,11 +112,13 @@ namespace erizo { VideoDecoder::VideoDecoder(){ + avcodec_register_all(); vDecoder = 0; vDecoderContext = 0; } int VideoDecoder::initDecoder (const VideoCodecInfo& info){ + printf("Init Decoder\n"); vDecoder = avcodec_find_decoder(CODEC_ID_VP8); if (!vDecoder) { printf("Error getting video decoder\n"); @@ -154,8 +147,9 @@ namespace erizo { return 0; } - int VideoDecoder::decodeVideo(uint8_t* inBuff, int inBuffLen, - uint8_t* outBuff, int outBuffLen, bool* gotFrame){ + int VideoDecoder::decodeVideo(unsigned char* inBuff, int inBuffLen, + unsigned char* outBuff, int outBuffLen, int* gotFrame){ + printf("decode video\n"); if (vDecoder == 0 || vDecoderContext == 0){ printf("Init Codec First\n"); return -1; @@ -178,7 +172,7 @@ namespace erizo { &avpkt); if (len < 0) { - printf("Error al decodificar frame de vídeo\n"); + printf("Error decoding video frame\n"); return -1; } @@ -191,7 +185,6 @@ namespace erizo { } if (!got_picture) { - printf("Aún no tengo frame"); return -1; } @@ -200,7 +193,6 @@ namespace erizo { int outSize = vDecoderContext->height * vDecoderContext->width; if (outBuffLen < (outSize * 3 / 2)) { - printf("No se ha rellenado el buffer??? outBuffLen = %d\n", outBuffLen); return outSize * 3 / 2; } diff --git a/src/erizo/media/codecs/VideoCodec.h b/src/erizo/media/codecs/VideoCodec.h index 0593b9e42e..8d4067d704 100644 --- a/src/erizo/media/codecs/VideoCodec.h +++ b/src/erizo/media/codecs/VideoCodec.h @@ -18,8 +18,8 @@ namespace erizo { public: VideoEncoder(); int initEncoder (const VideoCodecInfo& info); - int encodeVideo (uint8_t* inBuffer, int length, - uint8_t* outBuffer, int outLength, bool& hasFrame); + int encodeVideo (unsigned char* inBuffer, int length, + unsigned char* outBuffer, int outLength, int& hasFrame); int closeEncoder (); private: @@ -32,8 +32,8 @@ namespace erizo { public: VideoDecoder(); int initDecoder (const VideoCodecInfo& info); - int decodeVideo(uint8_t* inBuff, int inBuffLen, - uint8_t* outBuff, int outBuffLen, bool* gotFrame); + int decodeVideo(unsigned char* inBuff, int inBuffLen, + unsigned char* outBuff, int outBuffLen, int* gotFrame); int closeDecoder(); private: diff --git a/src/erizo/media/mixers/VideoUtils.cpp b/src/erizo/media/mixers/VideoUtils.cpp index 3c6f4ec5dd..365946bca7 100644 --- a/src/erizo/media/mixers/VideoUtils.cpp +++ b/src/erizo/media/mixers/VideoUtils.cpp @@ -1,3 +1,6 @@ +/** + * VideoUtils.cpp + */ #include #include diff --git a/src/erizo/media/mixers/VideoUtils.h b/src/erizo/media/mixers/VideoUtils.h index e8fc1e121b..5256d1ef88 100644 --- a/src/erizo/media/mixers/VideoUtils.h +++ b/src/erizo/media/mixers/VideoUtils.h @@ -1,3 +1,7 @@ +/** + * VideoUtils.h + */ + #ifndef VIDEOUTILS_H__ #define VIDEOUTILS_H_ From 2351a982c14139753cb5b5150588238d3fce623f Mon Sep 17 00:00:00 2001 From: Pedro Rodriguez Date: Fri, 26 Oct 2012 18:04:59 +0200 Subject: [PATCH 29/29] Recovered OneToMany processor and moved transcodification to OneToManyTranscoder --- src/erizo/OneToManyProcessor.cpp | 97 ++------------ src/erizo/OneToManyProcessor.h | 21 +-- src/erizo/media/MediaProcessor.h | 2 +- src/erizo/media/OneToManyTranscoder.cpp | 163 ++++++++++++++++++++++++ src/erizo/media/OneToManyTranscoder.h | 74 +++++++++++ src/erizo/media/mixers/VideoMixer.cpp | 11 ++ src/erizo/media/mixers/VideoMixer.h | 2 +- 7 files changed, 262 insertions(+), 108 deletions(-) create mode 100644 src/erizo/media/OneToManyTranscoder.cpp create mode 100644 src/erizo/media/OneToManyTranscoder.h diff --git a/src/erizo/OneToManyProcessor.cpp b/src/erizo/OneToManyProcessor.cpp index 8e1c3b4cb1..a1a7187c0d 100644 --- a/src/erizo/OneToManyProcessor.cpp +++ b/src/erizo/OneToManyProcessor.cpp @@ -4,8 +4,6 @@ #include "OneToManyProcessor.h" #include "WebRtcConnection.h" -#include "RTPSink.h" -#include "media/rtp/RtpHeader.h" namespace erizo { OneToManyProcessor::OneToManyProcessor() : @@ -13,44 +11,8 @@ OneToManyProcessor::OneToManyProcessor() : sendVideoBuffer_ = (char*) malloc(2000); sendAudioBuffer_ = (char*) malloc(2000); - publisher = NULL; sentPackets_ = 0; - ip = new InputProcessor(); - sink_ = new RTPSink("127.0.0.1", "50000"); - MediaInfo m; - m.proccessorType = RTP_ONLY; -// m.videoCodec.bitRate = 2000000; -// printf("m.videoCodec.bitrate %d\n\n", m.videoCodec.bitRate); - m.hasVideo = true; - m.videoCodec.width = 640; - m.videoCodec.height = 480; - m.hasAudio = false; - if (m.hasAudio) { - m.audioCodec.sampleRate = 8000; - m.audioCodec.bitRate = 64000; - - } - printf("init ip\n"); - ip->init(m, this); - - MediaInfo om; - om.proccessorType = RTP_ONLY; - om.videoCodec.bitRate = 2000000; - om.videoCodec.width = 640; - om.videoCodec.height = 480; - om.videoCodec.frameRate = 20; - om.hasVideo = true; -// om.url = "file://tmp/test.mp4"; - - om.hasAudio = false; - if (om.hasAudio) { - om.audioCodec.sampleRate = 8000; - om.audioCodec.bitRate = 64000; - } - - op = new OutputProcessor(); - op->init(om, this); } @@ -60,9 +22,6 @@ OneToManyProcessor::~OneToManyProcessor() { delete sendVideoBuffer_; if (sendAudioBuffer_) delete sendAudioBuffer_; - if (sink_) { - delete sink_; - } } int OneToManyProcessor::receiveAudioData(char* buf, int len) { @@ -81,70 +40,34 @@ int OneToManyProcessor::receiveAudioData(char* buf, int len) { } int OneToManyProcessor::receiveVideoData(char* buf, int len) { - memset(sendVideoBuffer_, 0, len); - memcpy(sendVideoBuffer_, buf, len); - - RTPHeader* theHead = reinterpret_cast(buf); -// printf("extension %d pt %u\n", theHead->getExtension(), -// theHead->getPayloadType()); - - if (theHead->getPayloadType() == 100) { - ip->receiveVideoData(sendVideoBuffer_, len); - } else { - this->receiveRtpData((unsigned char*) buf, len); - } - -// if (subscribers.empty() || len <= 0) -// return 0; -// if (sentPackets_ % 500 == 0) { -// publisher->sendFirPacket(); -// } -// std::map::iterator it; -// for (it = subscribers.begin(); it != subscribers.end(); it++) { -// memset(sendVideoBuffer_, 0, len); -// memcpy(sendVideoBuffer_, buf, len); -// (*it).second->receiveVideoData(sendVideoBuffer_, len); -// } -// memset(sendVideoBuffer_, 0, len); -// memcpy(sendVideoBuffer_, buf, len); -// sink_->sendData((unsigned char*)sendVideoBuffer_,len); - - sentPackets_++; - return 0; -} - -void OneToManyProcessor::receiveRawData(RawDataPacket& pkt) { -// printf("Received %d\n", pkt.length); - op->receiveRawData(pkt); -} - -void OneToManyProcessor::receiveRtpData(unsigned char*rtpdata, int len) { - printf("Received rtp data %d\n", len); - memcpy(sendVideoBuffer_, rtpdata, len); - if (subscribers.empty() || len <= 0) - return; -// if (sentPackets_ % 500 == 0) { -// publisher->sendFirPacket(); -// } + return 0; + if (sentPackets_ % 500 == 0) { + publisher->sendFirPacket(); + } std::map::iterator it; for (it = subscribers.begin(); it != subscribers.end(); it++) { - memcpy(sendVideoBuffer_, rtpdata, len); + memset(sendVideoBuffer_, 0, len); + memcpy(sendVideoBuffer_, buf, len); (*it).second->receiveVideoData(sendVideoBuffer_, len); } sentPackets_++; + return 0; } void OneToManyProcessor::setPublisher(WebRtcConnection* webRtcConn) { + this->publisher = webRtcConn; } void OneToManyProcessor::addSubscriber(WebRtcConnection* webRtcConn, int peerId) { + this->subscribers[peerId] = webRtcConn; } void OneToManyProcessor::removeSubscriber(int peerId) { + if (this->subscribers.find(peerId) != subscribers.end()) { this->subscribers[peerId]->close(); this->subscribers.erase(peerId); diff --git a/src/erizo/OneToManyProcessor.h b/src/erizo/OneToManyProcessor.h index a86238e13b..5f150addd3 100644 --- a/src/erizo/OneToManyProcessor.h +++ b/src/erizo/OneToManyProcessor.h @@ -6,21 +6,18 @@ #define ONETOMANYPROCESSOR_H_ #include -#include #include "MediaDefinitions.h" -#include "media/MediaProcessor.h" - namespace erizo{ + class WebRtcConnection; -class RTPSink; /** * Represents a One to Many connection. * Receives media from one publisher and retransmits it to every subscriber. */ -class OneToManyProcessor : public MediaReceiver, public RawDataReceiver, public RTPDataReceiver { +class OneToManyProcessor : public MediaReceiver { public: WebRtcConnection *publisher; std::map subscribers; @@ -45,12 +42,6 @@ class OneToManyProcessor : public MediaReceiver, public RawDataReceiver, public void removeSubscriber(int peerId); int receiveAudioData(char* buf, int len); int receiveVideoData(char* buf, int len); - void receiveRawData(RawDataPacket& packet); - void receiveRtpData(unsigned char*rtpdata, int len); - -// MediaProcessor *mp; - InputProcessor* ip; - OutputProcessor* op; /** * Closes all the subscribers and the publisher, the object is useless after this */ @@ -59,14 +50,6 @@ class OneToManyProcessor : public MediaReceiver, public RawDataReceiver, public private: char* sendVideoBuffer_; char* sendAudioBuffer_; - char* unpackagedBuffer_; - char* decodedBuffer_; - char* codedBuffer_; - RTPSink* sink_; - std::vector head; - int gotFrame_,gotDecodedFrame_, size_; - void sendHead(WebRtcConnection* conn); - RtpParser pars; unsigned int sentPackets_; }; diff --git a/src/erizo/media/MediaProcessor.h b/src/erizo/media/MediaProcessor.h index d3523ead1d..9d423cfc80 100644 --- a/src/erizo/media/MediaProcessor.h +++ b/src/erizo/media/MediaProcessor.h @@ -72,7 +72,7 @@ class RawDataReceiver { class RTPDataReceiver { public: - virtual void receiveRtpData(unsigned char*rtpdata, int len) = 0; + virtual void receiveRtpData(unsigned char* rtpdata, int len) = 0; virtual ~RTPDataReceiver() { } ; diff --git a/src/erizo/media/OneToManyTranscoder.cpp b/src/erizo/media/OneToManyTranscoder.cpp new file mode 100644 index 0000000000..2fd21f0b7e --- /dev/null +++ b/src/erizo/media/OneToManyTranscoder.cpp @@ -0,0 +1,163 @@ +/* + * OneToManyTranscoder.cpp + */ + +#include "OneToManyTranscoder.h" +#include "../WebRtcConnection.h" +#include "../RTPSink.h" +#include "rtp/RtpHeader.h" + +namespace erizo { +OneToManyTranscoder::OneToManyTranscoder() : + MediaReceiver() { + + sendVideoBuffer_ = (char*) malloc(2000); + sendAudioBuffer_ = (char*) malloc(2000); + + publisher = NULL; + sentPackets_ = 0; + ip = new InputProcessor(); + sink_ = new RTPSink("127.0.0.1", "50000"); + MediaInfo m; + m.proccessorType = RTP_ONLY; +// m.videoCodec.bitRate = 2000000; +// printf("m.videoCodec.bitrate %d\n\n", m.videoCodec.bitRate); + m.hasVideo = true; + m.videoCodec.width = 640; + m.videoCodec.height = 480; + m.hasAudio = false; + if (m.hasAudio) { + m.audioCodec.sampleRate = 8000; + m.audioCodec.bitRate = 64000; + + } + printf("init ip\n"); + ip->init(m, this); + + MediaInfo om; + om.proccessorType = RTP_ONLY; + om.videoCodec.bitRate = 2000000; + om.videoCodec.width = 640; + om.videoCodec.height = 480; + om.videoCodec.frameRate = 20; + om.hasVideo = true; +// om.url = "file://tmp/test.mp4"; + + om.hasAudio = false; + if (om.hasAudio) { + om.audioCodec.sampleRate = 8000; + om.audioCodec.bitRate = 64000; + } + + op = new OutputProcessor(); + op->init(om, this); + +} + +OneToManyTranscoder::~OneToManyTranscoder() { + this->closeAll(); + if (sendVideoBuffer_) + delete sendVideoBuffer_; + if (sendAudioBuffer_) + delete sendAudioBuffer_; + if (sink_) { + delete sink_; + } +} + +int OneToManyTranscoder::receiveAudioData(char* buf, int len) { + + if (subscribers.empty() || len <= 0) + return 0; + + std::map::iterator it; + for (it = subscribers.begin(); it != subscribers.end(); it++) { + memset(sendAudioBuffer_, 0, len); + memcpy(sendAudioBuffer_, buf, len); + (*it).second->receiveAudioData(sendAudioBuffer_, len); + } + + return 0; +} + +int OneToManyTranscoder::receiveVideoData(char* buf, int len) { + memset(sendVideoBuffer_, 0, len); + memcpy(sendVideoBuffer_, buf, len); + + RTPHeader* theHead = reinterpret_cast(buf); +// printf("extension %d pt %u\n", theHead->getExtension(), +// theHead->getPayloadType()); + + if (theHead->getPayloadType() == 100) { + ip->receiveVideoData(sendVideoBuffer_, len); + } else { + this->receiveRtpData((unsigned char*) buf, len); + } + +// if (subscribers.empty() || len <= 0) +// return 0; +// if (sentPackets_ % 500 == 0) { +// publisher->sendFirPacket(); +// } +// std::map::iterator it; +// for (it = subscribers.begin(); it != subscribers.end(); it++) { +// memset(sendVideoBuffer_, 0, len); +// memcpy(sendVideoBuffer_, buf, len); +// (*it).second->receiveVideoData(sendVideoBuffer_, len); +// } +// memset(sendVideoBuffer_, 0, len); +// memcpy(sendVideoBuffer_, buf, len); +// sink_->sendData((unsigned char*)sendVideoBuffer_,len); + + sentPackets_++; + return 0; +} + +void OneToManyTranscoder::receiveRawData(RawDataPacket& pkt) { +// printf("Received %d\n", pkt.length); + op->receiveRawData(pkt); +} + +void OneToManyTranscoder::receiveRtpData(unsigned char*rtpdata, int len) { + printf("Received rtp data %d\n", len); + memcpy(sendVideoBuffer_, rtpdata, len); + + if (subscribers.empty() || len <= 0) + return; +// if (sentPackets_ % 500 == 0) { +// publisher->sendFirPacket(); +// } + std::map::iterator it; + for (it = subscribers.begin(); it != subscribers.end(); it++) { + memcpy(sendVideoBuffer_, rtpdata, len); + (*it).second->receiveVideoData(sendVideoBuffer_, len); + } + sentPackets_++; +} + +void OneToManyTranscoder::setPublisher(WebRtcConnection* webRtcConn) { + this->publisher = webRtcConn; +} + +void OneToManyTranscoder::addSubscriber(WebRtcConnection* webRtcConn, + int peerId) { + this->subscribers[peerId] = webRtcConn; +} + +void OneToManyTranscoder::removeSubscriber(int peerId) { + if (this->subscribers.find(peerId) != subscribers.end()) { + this->subscribers[peerId]->close(); + this->subscribers.erase(peerId); + } +} + +void OneToManyTranscoder::closeAll() { + std::map::iterator it; + for (it = subscribers.begin(); it != subscribers.end(); it++) { + (*it).second->close(); + } + this->publisher->close(); +} + +}/* namespace erizo */ + diff --git a/src/erizo/media/OneToManyTranscoder.h b/src/erizo/media/OneToManyTranscoder.h new file mode 100644 index 0000000000..28a09d2e16 --- /dev/null +++ b/src/erizo/media/OneToManyTranscoder.h @@ -0,0 +1,74 @@ +/* + * OneToManyTranscoder.h + */ + +#ifndef ONETOMANYTRANSCODER_H_ +#define ONETOMANYTRANSCODER_H_ + +#include +#include + +#include "../MediaDefinitions.h" +#include "MediaProcessor.h" + + +namespace erizo{ +class WebRtcConnection; +class RTPSink; + +/** + * Represents a One to Many connection. + * Receives media from one publisher and retransmits it to every subscriber. + */ +class OneToManyTranscoder : public MediaReceiver, public RawDataReceiver, public RTPDataReceiver { +public: + WebRtcConnection *publisher; + std::map subscribers; + + OneToManyTranscoder(); + virtual ~OneToManyTranscoder(); + /** + * Sets the Publisher + * @param webRtcConn The WebRtcConnection of the Publisher + */ + void setPublisher(WebRtcConnection* webRtcConn); + /** + * Sets the subscriber + * @param webRtcConn The WebRtcConnection of the subscriber + * @param peerId An unique Id for the subscriber + */ + void addSubscriber(WebRtcConnection* webRtcConn, int peerId); + /** + * Eliminates the subscriber given its peer id + * @param peerId the peerId + */ + void removeSubscriber(int peerId); + int receiveAudioData(char* buf, int len); + int receiveVideoData(char* buf, int len); + void receiveRawData(RawDataPacket& packet); + void receiveRtpData(unsigned char*rtpdata, int len); + +// MediaProcessor *mp; + InputProcessor* ip; + OutputProcessor* op; + /** + * Closes all the subscribers and the publisher, the object is useless after this + */ + void closeAll(); + +private: + char* sendVideoBuffer_; + char* sendAudioBuffer_; + char* unpackagedBuffer_; + char* decodedBuffer_; + char* codedBuffer_; + RTPSink* sink_; + std::vector head; + int gotFrame_,gotDecodedFrame_, size_; + void sendHead(WebRtcConnection* conn); + RtpParser pars; + unsigned int sentPackets_; +}; + +} /* namespace erizo */ +#endif /* ONETOMANYTRANSCODER_H_ */ diff --git a/src/erizo/media/mixers/VideoMixer.cpp b/src/erizo/media/mixers/VideoMixer.cpp index 7b973d45c0..815438b2ef 100644 --- a/src/erizo/media/mixers/VideoMixer.cpp +++ b/src/erizo/media/mixers/VideoMixer.cpp @@ -40,6 +40,14 @@ namespace erizo { } VideoMixer::~VideoMixer() { + + if (sendVideoBuffer_) + delete sendVideoBuffer_; + if (sendAudioBuffer_) + delete sendAudioBuffer_; + if (sink_) { + delete sink_; + } } int VideoMixer::receiveAudioData(char* buf, int len) { @@ -53,6 +61,9 @@ namespace erizo { void VideoMixer::receiveRawData(RawDataPacket& pkt) { } + void VideoMixer::receiveRtpData(unsigned char* rtpdata, int len){ + } + void VideoMixer::addPublisher(WebRtcConnection* webRtcConn, int peerSSRC){ } diff --git a/src/erizo/media/mixers/VideoMixer.h b/src/erizo/media/mixers/VideoMixer.h index 769de7f374..b098b08412 100644 --- a/src/erizo/media/mixers/VideoMixer.h +++ b/src/erizo/media/mixers/VideoMixer.h @@ -47,7 +47,7 @@ class VideoMixer : public MediaReceiver, public RawDataReceiver, public RTPDataR int receiveAudioData(char* buf, int len); int receiveVideoData(char* buf, int len); void receiveRawData(RawDataPacket& packet); - void receiveRtpData(); + void receiveRtpData(unsigned char* rtpdata, int len); // MediaProcessor *mp; InputProcessor* ip;