void VideoFFmpegWriter::finish() { if( _error == IGNORE_FINISH ) return; av_write_trailer( _avformatOptions ); avcodec_close( _stream->codec ); if( !( _avformatOptions->oformat->flags & AVFMT_NOFILE ) ) url_fclose( _avformatOptions->pb ); freeFormat(); }
int VideoFFmpegWriter::execute( boost::uint8_t* in_buffer, int in_width, int in_height, PixelFormat in_pixelFormat ) { _error = IGNORE_FINISH; AVOutputFormat* fmt = 0; fmt = guess_format( _format.c_str(), NULL, NULL ); if( !fmt ) { fmt = guess_format( NULL, filename().c_str(), NULL ); if( !fmt ) { std::cerr << "ffmpegWriter: could not deduce output format from file extension." << std::endl; return false; } } if( !_avformatOptions ) _avformatOptions = avformat_alloc_context(); _avformatOptions->oformat = fmt; snprintf( _avformatOptions->filename, sizeof( _avformatOptions->filename ), "%s", filename().c_str() ); if( !_stream ) { _stream = av_new_stream( _avformatOptions, 0 ); if( !_stream ) { std::cout << "ffmpegWriter: out of memory." << std::endl; return false; } CodecID codecId = fmt->video_codec; AVCodec* userCodec = avcodec_find_encoder_by_name( _codec.c_str() ); if( userCodec ) codecId = userCodec->id; _stream->codec->codec_id = codecId; _stream->codec->codec_type = CODEC_TYPE_VIDEO; _stream->codec->bit_rate = _bitRate; _stream->codec->bit_rate_tolerance = _bitRateTolerance; _stream->codec->width = width(); _stream->codec->height = height(); _stream->codec->time_base = av_d2q( 1.0 / _fps, 100 ); _stream->codec->gop_size = _gopSize; if( _bFrames ) { _stream->codec->max_b_frames = _bFrames; _stream->codec->b_frame_strategy = 0; _stream->codec->b_quant_factor = 2.0; } _stream->codec->mb_decision = _mbDecision; _stream->codec->pix_fmt = _out_pixelFormat; if( !strcmp( _avformatOptions->oformat->name, "mp4" ) || !strcmp( _avformatOptions->oformat->name, "mov" ) || !strcmp( _avformatOptions->oformat->name, "3gp" ) || !strcmp( _avformatOptions->oformat->name, "flv" ) ) _stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER; if( av_set_parameters( _avformatOptions, NULL ) < 0 ) { std::cout << "ffmpegWriter: unable to set parameters." << std::endl; freeFormat(); return false; } dump_format( _avformatOptions, 0, filename().c_str(), 1 ); AVCodec* videoCodec = avcodec_find_encoder( codecId ); if( !videoCodec ) { std::cout << "ffmpegWriter: unable to find codec." << std::endl; freeFormat(); return false; } if( avcodec_open( _stream->codec, videoCodec ) < 0 ) { std::cout << "ffmpegWriter: unable to open codec." << std::endl; freeFormat(); return false; } if( !( fmt->flags & AVFMT_NOFILE ) ) { if( url_fopen( &_avformatOptions->pb, filename().c_str(), URL_WRONLY ) < 0 ) { std::cout << "ffmpegWriter: unable to open file." << std::endl; return false; } } av_write_header( _avformatOptions ); } _error = CLEANUP; AVFrame* in_frame = avcodec_alloc_frame(); avcodec_get_frame_defaults( in_frame ); avpicture_fill( (AVPicture*)in_frame, in_buffer, in_pixelFormat, in_width, in_height ); AVFrame* out_frame = avcodec_alloc_frame(); avcodec_get_frame_defaults( out_frame ); int out_picSize = avpicture_get_size( _out_pixelFormat, width(), height() ); boost::uint8_t* out_buffer = (boost::uint8_t*) av_malloc( out_picSize ); avpicture_fill( (AVPicture*) out_frame, out_buffer, _out_pixelFormat, width(), height() ); _sws_context = sws_getCachedContext( _sws_context, in_width, in_height, in_pixelFormat, width(), height(), _out_pixelFormat, SWS_BICUBIC, NULL, NULL, NULL ); std::cout << "ffmpegWriter: input format: " << pixelFormat_toString( in_pixelFormat ) << std::endl; std::cout << "ffmpegWriter: output format: " << pixelFormat_toString( _out_pixelFormat ) << std::endl; if( !_sws_context ) { std::cout << "ffmpeg-conversion failed (" << in_pixelFormat << "->" << _out_pixelFormat << ")." << std::endl; return false; } int error = sws_scale( _sws_context, in_frame->data, in_frame->linesize, 0, height(), out_frame->data, out_frame->linesize ); if( error < 0 ) { std::cout << "ffmpeg-conversion failed (" << in_pixelFormat << "->" << _out_pixelFormat << ")." << std::endl; return false; } int ret = 0; if( ( _avformatOptions->oformat->flags & AVFMT_RAWPICTURE ) != 0 ) { AVPacket pkt; av_init_packet( &pkt ); pkt.flags |= PKT_FLAG_KEY; pkt.stream_index = _stream->index; pkt.data = (boost::uint8_t*) out_frame; pkt.size = sizeof( AVPicture ); ret = av_interleaved_write_frame( _avformatOptions, &pkt ); } else { boost::uint8_t* out_buffer = (boost::uint8_t*) av_malloc( out_picSize ); ret = avcodec_encode_video( _stream->codec, out_buffer, out_picSize, out_frame ); if( ret > 0 ) { AVPacket pkt; av_init_packet( &pkt ); if( _stream->codec->coded_frame && _stream->codec->coded_frame->pts != static_cast<boost::int64_t>( AV_NOPTS_VALUE ) ) // static_cast<unsigned long> ( pkt.pts = av_rescale_q( _stream->codec->coded_frame->pts, _stream->codec->time_base, _stream->time_base ); if( _stream->codec->coded_frame && _stream->codec->coded_frame->key_frame ) pkt.flags |= PKT_FLAG_KEY; pkt.stream_index = _stream->index; pkt.data = out_buffer; pkt.size = ret; ret = av_interleaved_write_frame( _avformatOptions, &pkt ); } av_free( out_buffer ); } av_free( out_buffer ); av_free( out_frame ); av_free( in_frame ); // in_buffer not free (function parameter) if( ret ) { std::cout << "ffmpegWriter: error writing frame to file." << std::endl; return false; } _error = SUCCESS; return true; }
int VideoFFmpegWriter::execute( boost::uint8_t* in_buffer, int in_width, int in_height, PixelFormat in_pixelFormat ) { _error = IGNORE_FINISH; if( !_avformatOptions ) { // TODO avformat_alloc_context2 can guess format from filename // if format name is NULL, find a way to expose the feature if (avformat_alloc_output_context2(&_avformatOptions, NULL, _formatName.c_str(), filename().c_str()) < 0) { TUTTLE_CERR( "ffmpegWriter: output context allocation failed" ); return false; } _ofmt = _avformatOptions->oformat; TUTTLE_CERR( "ffmpegWriter: " << std::string(_ofmt->name) << " format selected" ); } if( !_stream ) { _codec = avcodec_find_encoder_by_name( _codecName.c_str() ); if (!_codec) { TUTTLE_CERR( "ffmpegWriter: codec not found" ); return false; } TUTTLE_CERR( "ffmpegWriter: " << std::string(_codec->name) << " codec selected" ); _stream = avformat_new_stream( _avformatOptions, _codec ); if( !_stream ) { TUTTLE_CERR( "ffmpegWriter: out of memory." ); return false; } avcodec_get_context_defaults3(_stream->codec, _codec); if( _videoPresetName.length() !=0 ) { TUTTLE_COUT( "ffmpegWriter: " << _videoPresetName << " preset selected" ); std::string presetFilename = getFilename( std::string(_codec->name), _videoPresetName ); PresetsOptions opts = getOptionsForPresetFilename( presetFilename ); PresetsOptions::iterator itOpt; for ( itOpt = opts.begin() ; itOpt != opts.end(); itOpt++ ) { int ret = av_opt_set( (void*)_stream->codec, (*itOpt).first.c_str(), (*itOpt).second.c_str(), 0); switch( ret ) { case AVERROR_OPTION_NOT_FOUND: TUTTLE_CERR( "ffmpegPreset: unable to find " << (*itOpt).first ); break; case AVERROR(EINVAL): TUTTLE_CERR( "ffmpegPreset: invalid value " << (*itOpt).second.c_str() << " for option " << (*itOpt).first ); break; case AVERROR(ERANGE): TUTTLE_CERR( "ffmpegPreset: invalid range for parameter " << (*itOpt).first << " : " << (*itOpt).second.c_str() ); break; } } } _stream->codec->bit_rate = _bitRate; _stream->codec->bit_rate_tolerance = _bitRateTolerance; _stream->codec->width = width(); _stream->codec->height = height(); _stream->codec->time_base = av_d2q( 1.0 / _fps, 100 ); _stream->codec->gop_size = _gopSize; _stream->codec->sample_rate = 48000; ///< samples per second _stream->codec->channels = 0; ///< number of audio channels if( _bFrames ) { _stream->codec->max_b_frames = _bFrames; _stream->codec->b_frame_strategy = 0; _stream->codec->b_quant_factor = 2.0; } _stream->codec->mb_decision = _mbDecision; int pixfmt_allowed = 0, k; if ( _codec->pix_fmts ) { for ( k = 0; _codec->pix_fmts[k] != PIX_FMT_NONE; k++ ) { if ( _codec->pix_fmts[k] == _out_pixelFormat ) { pixfmt_allowed = 1; break; } } } else { // If a codec does not contain a list of supported pixel // formats, just assume that _out_PixelFormat is valid pixfmt_allowed = 1; } if ( !pixfmt_allowed ) { // av_get_pix_fmt_name requires lavu 51.3.0 or higher TUTTLE_CERR( "ffmpegWriter: pixel format " << av_get_pix_fmt_name(_out_pixelFormat) << " not available in codec" ); _out_pixelFormat = _codec->pix_fmts[0]; TUTTLE_CERR( "ffmpegWriter: auto-selecting " << av_get_pix_fmt_name(_out_pixelFormat) ); } _stream->codec->pix_fmt = _out_pixelFormat; if( !strcmp( _avformatOptions->oformat->name, "mp4" ) || !strcmp( _avformatOptions->oformat->name, "mov" ) || !strcmp( _avformatOptions->oformat->name, "3gp" ) || !strcmp( _avformatOptions->oformat->name, "flv" ) ) _stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER; av_dump_format( _avformatOptions, 0, filename().c_str(), 1 ); if( avcodec_open2( _stream->codec, _codec, NULL ) < 0 ) { TUTTLE_CERR( "ffmpegWriter: unable to open codec." ); freeFormat(); return false; } if( !( _ofmt->flags & AVFMT_NOFILE ) ) { if( avio_open2( &_avformatOptions->pb, filename().c_str(), AVIO_FLAG_WRITE, NULL, NULL ) < 0 ) { TUTTLE_CERR( "ffmpegWriter: unable to open file." ); freeFormat(); return false; } } avformat_write_header( _avformatOptions, NULL ); } _error = CLEANUP; AVFrame* in_frame = avcodec_alloc_frame(); avcodec_get_frame_defaults( in_frame ); avpicture_fill( (AVPicture*)in_frame, in_buffer, in_pixelFormat, in_width, in_height ); AVFrame* out_frame = avcodec_alloc_frame(); avcodec_get_frame_defaults( out_frame ); int out_picSize = avpicture_get_size( _out_pixelFormat, width(), height() ); boost::uint8_t* out_buffer = (boost::uint8_t*) av_malloc( out_picSize ); avpicture_fill( (AVPicture*) out_frame, out_buffer, _out_pixelFormat, width(), height() ); _sws_context = sws_getCachedContext( _sws_context, in_width, in_height, in_pixelFormat, width(), height(), _out_pixelFormat, SWS_BICUBIC, NULL, NULL, NULL ); TUTTLE_COUT( "ffmpegWriter: input format: " << av_get_pix_fmt_name( in_pixelFormat ) ); TUTTLE_COUT( "ffmpegWriter: output format: " << av_get_pix_fmt_name( _out_pixelFormat ) ); if( !_sws_context ) { TUTTLE_CERR( "ffmpeg-conversion failed (" << in_pixelFormat << "->" << _out_pixelFormat << ")." ); return false; } int error = sws_scale( _sws_context, in_frame->data, in_frame->linesize, 0, height(), out_frame->data, out_frame->linesize ); if( error < 0 ) { TUTTLE_CERR( "ffmpeg-conversion failed (" << in_pixelFormat << "->" << _out_pixelFormat << ")." ); return false; } int ret = 0; if( ( _avformatOptions->oformat->flags & AVFMT_RAWPICTURE ) != 0 ) { AVPacket pkt; av_init_packet( &pkt ); pkt.flags |= AV_PKT_FLAG_KEY; pkt.stream_index = _stream->index; pkt.data = (boost::uint8_t*) out_frame; pkt.size = sizeof( AVPicture ); ret = av_interleaved_write_frame( _avformatOptions, &pkt ); } else { AVPacket pkt; int hasFrame = 0; av_init_packet( &pkt ); pkt.size = 0; pkt.data = NULL; pkt.stream_index = _stream->index; if( _stream->codec->coded_frame && _stream->codec->coded_frame->pts != static_cast<boost::int64_t>( AV_NOPTS_VALUE ) ) // static_cast<unsigned long> ( pkt.pts = av_rescale_q( _stream->codec->coded_frame->pts, _stream->codec->time_base, _stream->time_base ); if( _stream->codec->coded_frame && _stream->codec->coded_frame->key_frame ) pkt.flags |= AV_PKT_FLAG_KEY; out_frame->pts = pts++; ret = avcodec_encode_video2( _stream->codec, &pkt, out_frame, &hasFrame ); if ( ret < 0 ) return false; if ( hasFrame ) { ret = av_interleaved_write_frame( _avformatOptions, &pkt ); if ( ret < 0 ) { TUTTLE_CERR( "ffmpegWriter: error writing packet to file" ); return false; } } } av_free( out_buffer ); av_free( out_frame ); av_free( in_frame ); // in_buffer not free (function parameter) if( ret ) { TUTTLE_CERR( "ffmpegWriter: error writing frame to file." ); return false; } _error = SUCCESS; return true; }
int main(void) { struct pollfd sfd[3]; const long timeout=500; //connection timeout in seconds struct timespec ts_timeout; int size; field *pmessage; fldformat *frm; isomessage smessage; GOOGLE_PROTOBUF_VERIFY_VERSION; frm=loadNetFormat(); if(!frm) { printf("Error: Can't load format\n"); return 1; } printf("Message format loaded\n"); sfd[2].fd=tcpinit(); if(sfd[2].fd==-1) { printf("Error: Unable to start TCP connection\n"); freeFormat(frm); return 1; } sfd[0].fd=ipcopen((char *)"visa"); if(sfd[0].fd==-1) { printf("Error: Unable to connect to switch\n"); close(sfd[2].fd); freeFormat(frm); return 1; } if (signal(SIGINT, catch_sigint) == SIG_ERR) printf("Warning: unable to set the signal handler\n"); sfd[0].events=POLLIN; sfd[1].events=POLLIN; while (1) { printf("Waiting for a connection...\n"); errno=0; sfd[1].fd=tcpconnect(sfd[2].fd); if(sfd[1].fd==-1) { if(sigint_caught) { printf("onnection aborted^\n"); break; } printf("Connection error: %s\n", strerror(errno)); sleep(1); continue; } printf("Connected.\n"); while (1) { printf("Waiting for a message...\n"); ts_timeout.tv_sec=timeout; ts_timeout.tv_nsec=0; errno=0; size=ppoll(sfd, 2, &ts_timeout, NULL); //printf("poll: %d: %hd, %hd: %s\n", size, sfd[0].revents, sfd[1].revents, strerror(errno)); if(size==-1) { if(sigint_caught) { printf("losing connection^\n"); break; } printf("Error: poll (%hd, %hd): %s\n", sfd[0].revents, sfd[1].revents, strerror(errno)); if(sfd[1].revents) break; else { usleep(100000); continue; } } else if(size==0) { printf("Error: Connection is inactive, closing it %ld, %ld\n", ts_timeout.tv_sec, ts_timeout. tv_nsec); break; } if(sfd[1].revents & POLLIN) { printf("Receiving message from net\n"); size=tcprecvmsg(sfd[1].fd, &pmessage, frm); if(size==-1) { printf("Closing connection\n"); break; } else if(size==0) continue; print_message(pmessage); if(isNetMgmt(pmessage)) { if(isNetRequest(pmessage)) { if(!processNetMgmt(pmessage)) { printf("Error: Unable to process Network Management request. Message dropped.\n"); freeField(pmessage); continue; } print_message(pmessage); size=tcpsendmsg(sfd[1].fd, pmessage); if(size==-1) { printf("Closing connection\n"); freeField(pmessage); break; } else if(size==0) { freeField(pmessage); continue; } printf("Network Management Message sent (%d bytes)\n", size); } freeField(pmessage); continue; } if(translateNetToSwitch(&smessage, pmessage)!=0) { printf("Error: Unable to translate the message to format-independent representation.\n"); if(isNetRequest(pmessage)) { if(!declineNetMsg(pmessage)) { printf("Error: Unable to decline the request. Message dropped.\n"); freeField(pmessage); continue; } print_message(pmessage); size=tcpsendmsg(sfd[1].fd, pmessage); if(size==-1) { printf("Closing connection\n"); freeField(pmessage); break; } else if(size==0) { freeField(pmessage); continue; } printf("Decline message sent (%d bytes)\n", size); } freeField(pmessage); continue; } printf("Converted message:\n"); smessage.PrintDebugString(); size=ipcsendmsg(sfd[0].fd, &smessage, (char *)"switch"); if(size<=0) { printf("Error: Unable to send the message to switch\n"); if(isNetRequest(pmessage)) { if(!declineNetMsg(pmessage)) { printf("Error: Unable to decline the request. Message dropped.\n"); freeField(pmessage); continue; } print_message(pmessage); size=tcpsendmsg(sfd[1].fd, pmessage); if(size==-1) { printf("Closing connection\n"); freeField(pmessage); break; } else if(size==0) { freeField(pmessage); continue; } printf("Decline message sent (%d bytes)\n", size); } freeField(pmessage); continue; } freeField(pmessage); printf("Message sent, size is %d bytes.\n", size); } if(sfd[0].revents & POLLIN) { printf("Receiving message from switch\n"); if(ipcrecvmsg(sfd[0].fd, &smessage)<0) continue; printf("\nOutgoingMessage:\n"); smessage.PrintDebugString(); pmessage=translateSwitchToNet(&smessage, frm); if(!pmessage) { printf("Error: Unable to translate the message from format-independent representation.\n"); if(isRequest(&smessage)) { if(!declineMsg(&smessage)) { printf("Error: Unable to decline the request. Message dropped.\n"); continue; } smessage.PrintDebugString(); size=ipcsendmsg(sfd[0].fd, &smessage, (char *)"switch"); if(size<=0) { printf("Error: Unable to return the declined message to switch. Message dropped.\n"); continue; } printf("Decline message sent (%d bytes)\n", size); } continue; } print_message(pmessage); size=tcpsendmsg(sfd[1].fd, pmessage); freeField(pmessage); if(size==-1) { printf("Closing connection\n"); if(isRequest(&smessage)) { if(!declineMsg(&smessage)) { printf("Error: Unable to decline the request. Message dropped.\n"); continue; } smessage.PrintDebugString(); size=ipcsendmsg(sfd[0].fd, &smessage, (char *)"switch"); if(size<=0) { printf("Error: Unable to return the declined message to switch. Message dropped.\n"); continue; } printf("Decline message sent (%d bytes)\n", size); } break; } else if(size==0) { if(isRequest(&smessage)) { if(!declineMsg(&smessage)) { printf("Error: Unable to decline the request. Message dropped.\n"); continue; } smessage.PrintDebugString(); size=ipcsendmsg(sfd[0].fd, &smessage, (char *)"switch"); if(size<=0) { printf("Error: Unable to return the declined message to switch. Message dropped.\n"); continue; } printf("Decline message sent (%d bytes)\n", size); } continue; } printf("Message sent (%d bytes)\n", size); } } tcpclose(sfd[1].fd); printf("Disconnected.\n"); if(sigint_caught) break; } tcpclose(sfd[2].fd); ipcclose(sfd[0].fd); freeFormat(frm); google::protobuf::ShutdownProtobufLibrary(); return 0; }