int cs_set_video_encoder_resolution(CSSession *cs, uint16_t width, uint16_t height) { vpx_codec_enc_cfg_t cfg = *cs->v_encoder.config.enc; if (cfg.g_w == width && cfg.g_h == height) return 0; if (width * height > cs->max_width * cs->max_height) { vpx_codec_ctx_t v_encoder = cs->v_encoder; if (init_video_encoder(cs, width, height, cs->video_bitrate) == -1) { cs->v_encoder = v_encoder; return cs_ErrorSettingVideoResolution; } vpx_codec_destroy(&v_encoder); return 0; } LOGGER_DEBUG("New video resolution: %u %u", width, height); cfg.g_w = width; cfg.g_h = height; int rc = vpx_codec_enc_config_set(&cs->v_encoder, &cfg); if ( rc != VPX_CODEC_OK) { LOGGER_ERROR("Failed to set encoder control setting: %s", vpx_codec_err_to_string(rc)); return cs_ErrorSettingVideoResolution; } return 0; }
CodecState *codec_init_session ( uint32_t audio_bitrate, uint16_t audio_frame_duration, uint32_t audio_sample_rate, uint32_t audio_channels, uint16_t video_width, uint16_t video_height, uint32_t video_bitrate ) { CodecState *retu = calloc(sizeof(CodecState), 1); assert(retu); retu->audio_bitrate = audio_bitrate; retu->audio_sample_rate = audio_sample_rate; /* Encoders */ if (!video_width || !video_height) { /* Disable video */ /*video_width = 320; video_height = 240; */ } else { retu->supported_actions |= ( 0 == init_video_encoder(retu, video_width, video_height, video_bitrate) ) ? v_encoding : 0; retu->supported_actions |= ( 0 == init_video_decoder(retu) ) ? v_decoding : 0; } retu->supported_actions |= ( 0 == init_audio_encoder(retu, audio_channels) ) ? a_encoding : 0; retu->supported_actions |= ( 0 == init_audio_decoder(retu, audio_channels) ) ? a_decoding : 0; return retu; }
CodecState *codec_init_session ( uint32_t audio_bitrate, uint16_t audio_frame_duration, uint32_t audio_sample_rate, uint32_t audio_channels, uint16_t video_width, uint16_t video_height, uint32_t video_bitrate ) { CodecState *retu = calloc(sizeof(CodecState), 1); if (!retu) return NULL; retu->audio_bitrate = audio_bitrate; retu->audio_sample_rate = audio_sample_rate; /* Encoders */ if (!video_width || !video_height) { /* Disable video */ /*video_width = 320; video_height = 240; */ } else { retu->capabilities |= ( 0 == init_video_encoder(retu, video_width, video_height, video_bitrate) ) ? v_encoding : 0; retu->capabilities |= ( 0 == init_video_decoder(retu) ) ? v_decoding : 0; } retu->capabilities |= ( 0 == init_audio_encoder(retu, audio_channels) ) ? a_encoding : 0; retu->capabilities |= ( 0 == init_audio_decoder(retu, audio_channels) ) ? a_decoding : 0; if ( retu->capabilities == 0 ) { /* everything failed */ free (retu); return NULL; } return retu; }
CSSession *cs_new(const ToxAvCSettings *cs_self, const ToxAvCSettings *cs_peer, uint32_t jbuf_size, int has_video) { CSSession *cs = calloc(sizeof(CSSession), 1); if (!cs) { LOGGER_WARNING("Allocation failed! Application might misbehave!"); return NULL; } if (create_recursive_mutex(cs->queue_mutex) != 0) { LOGGER_WARNING("Failed to create recursive mutex!"); free(cs); return NULL; } if ( !(cs->j_buf = jbuf_new(jbuf_size)) ) { LOGGER_WARNING("Jitter buffer creaton failed!"); goto error; } cs->audio_encoder_bitrate = cs_self->audio_bitrate; cs->audio_encoder_sample_rate = cs_self->audio_sample_rate; cs->audio_encoder_channels = cs_self->audio_channels; cs->audio_encoder_frame_duration = cs_self->audio_frame_duration; cs->audio_decoder_bitrate = cs_peer->audio_bitrate; cs->audio_decoder_sample_rate = cs_peer->audio_sample_rate; cs->audio_decoder_channels = cs_peer->audio_channels; cs->audio_decoder_frame_duration = cs_peer->audio_frame_duration; cs->capabilities |= ( 0 == init_audio_encoder(cs) ) ? cs_AudioEncoding : 0; cs->capabilities |= ( 0 == init_audio_decoder(cs) ) ? cs_AudioDecoding : 0; if ( !(cs->capabilities & cs_AudioEncoding) || !(cs->capabilities & cs_AudioDecoding) ) goto error; if ((cs->support_video = has_video)) { cs->max_video_frame_size = MAX_VIDEOFRAME_SIZE; cs->video_frame_piece_size = VIDEOFRAME_PIECE_SIZE; cs->capabilities |= ( 0 == init_video_encoder(cs, cs_self->max_video_width, cs_self->max_video_height, cs_self->video_bitrate) ) ? cs_VideoEncoding : 0; cs->capabilities |= ( 0 == init_video_decoder(cs) ) ? cs_VideoDecoding : 0; if ( !(cs->capabilities & cs_VideoEncoding) || !(cs->capabilities & cs_VideoDecoding) ) goto error; if ( !(cs->frame_buf = calloc(cs->max_video_frame_size, 1)) ) goto error; if ( !(cs->split_video_frame = calloc(cs->video_frame_piece_size + VIDEOFRAME_HEADER_SIZE, 1)) ) goto error; if ( !(cs->vbuf_raw = buffer_new(VIDEO_DECODE_BUFFER_SIZE)) ) goto error; } return cs; error: LOGGER_WARNING("Error initializing codec session! Application might misbehave!"); pthread_mutex_destroy(cs->queue_mutex); if ( cs->audio_encoder ) opus_encoder_destroy(cs->audio_encoder); if ( cs->audio_decoder ) opus_decoder_destroy(cs->audio_decoder); if (has_video) { if ( cs->capabilities & cs_VideoDecoding ) vpx_codec_destroy(&cs->v_decoder); if ( cs->capabilities & cs_VideoEncoding ) vpx_codec_destroy(&cs->v_encoder); buffer_free(cs->vbuf_raw); free(cs->frame_buf); free(cs->split_video_frame); } jbuf_free(cs->j_buf); free(cs); return NULL; }
void* process_videoencoder(void *param) { int sock = *(int *)param; free(param); printf("videoencoder new session sock=%d\n",sock); video_encoder_t* p_video_encoder = NULL; InputParams_videoencoder video_encoder_params; video_encoder_params.width = width; video_encoder_params.height = height; video_encoder_params.gopsize_min = gopsize_min; video_encoder_params.gopsize_max = gopsize_max; video_encoder_params.bitrate = encode_bitrate; video_encoder_params.fps = fps; p_video_encoder = init_video_encoder(&video_encoder_params); if(p_video_encoder == NULL) { printf("videoencoder: init_video_encoder fail..\n"); return NULL; } int buffer_size = width*height*3/2+24; char *buffer = (char *)malloc(buffer_size); if(buffer == NULL) { printf("videoencoder malloc buffer fail..\n"); return NULL; } char *input_video_sample; int input_video_sample_size; int output_video_sample_size = width*height*3/2; char *output_video_sample = (char *)malloc(buffer_size); if(output_video_sample == NULL) { fprintf(stderr ,"malloc buffer fail..\n"); return NULL; } int len = -1; int ret = -1; int type; int length; int x; int y; int w; int h; msg_head head; struct timeval tv; long time_us1,time_us2,time_us3,time_us4; while (1) { gettimeofday(&tv,NULL); time_us1 = tv.tv_sec*1000 + tv.tv_usec/1000; printf("time_us1 =%ld start recv\n",time_us1); len = recv(sock,&head,sizeof(head),0); if(len == 0) { fprintf(stderr ,"connect broken error len=%d..\n",len); break; } if(len < 0) { fprintf(stderr ,"recv data error len=%d..\n",len); continue; } type = head.type; length = head.length; x=head.x; y=head.y; w=head.w; h=head.h; if(length != 16+w*h*3/2) { fprintf(stderr ,"length error len=%d..\n",len); continue; } len = recv_len(sock,buffer,buffer_size,w*h*3/2); if(len != w*h*3/2) { fprintf(stderr ,"recv data error len=%d..\n",len); continue; } input_video_sample = buffer; input_video_sample_size = w * h *3/2; gettimeofday(&tv,NULL); time_us2 = tv.tv_sec*1000 + tv.tv_usec/1000; printf("time_us2 =%ld type=%d length=%d x=%d y=%d w=%d h=%d\n",time_us2,head.type,head.length,head.x,head.y,head.w,head.h); output_video_sample_size = width*height*3/2; ret = encode_video_sample_inc(p_video_encoder,input_video_sample,input_video_sample_size, output_video_sample,&output_video_sample_size,x,y,w,h); if(ret < 0) { fprintf(stderr ,"encode_video_sample_inc error ret=%d..\n",ret); continue; } gettimeofday(&tv,NULL); time_us3 = tv.tv_sec*1000 + tv.tv_usec/1000; printf("time_us3 =%ld encode_video_sample length=%d\n",time_us3,output_video_sample_size); head.type = 2; head.length = 4*4 + output_video_sample_size; head.x = 0; head.y = 0; head.w = 0; head.h = 0; len = send(sock,&head,sizeof(head),0); if(len < 0) { fprintf(stderr ,"send head error ret=%d..\n",len); continue; } len = send(sock,output_video_sample,output_video_sample_size,0); if(len < 0) { fprintf(stderr ,"send output_video_sample error ret=%d..\n",len); continue; } gettimeofday(&tv,NULL); time_us4 = tv.tv_sec*1000 + tv.tv_usec/1000; printf("time_us4 =%ld send over\n",time_us4); } uninit_video_encoder(p_video_encoder); }
int main(int argc,char** argv) { if(argc < 4) { printf("erro param \n"); return -1; } int width = atoi(argv[2]); int height = atoi(argv[3]); printf("file path %s ,w =%d,h=%d \n",argv[1],width,height); int gopsize_min = 15; int gopsize_max = 15; int encode_bitrate=4500000; int fps = 25; InputParams_videoencoder video_encoder_params; video_encoder_params.width = width; video_encoder_params.height = height; video_encoder_params.gopsize_min = gopsize_min; video_encoder_params.gopsize_max = gopsize_max; video_encoder_params.bitrate = encode_bitrate; video_encoder_params.fps = fps; p_video_encoder = init_video_encoder(&video_encoder_params); if(p_video_encoder == NULL) { fprintf(stderr ,"avencoder: init_video_encoder fail..\n"); return -1; } printf("file path %s ,w =%d,h=%d \n",argv[1],width,height); p_video_source_sample = (char *)malloc(n_video_source_sample_size); if( p_video_source_sample == NULL) { fprintf(stderr ,"avencoder: malloc fail..\n"); return -2; } p_video_encode_sample = (char *)malloc(n_video_encode_sample_size); if( p_video_encode_sample == NULL) { fprintf(stderr ,"avencoder: malloc fail..\n"); return -2; } FILE *fp = fopen(argv[1],"rb"); FILE* fpout = fopen("out.es","wb+"); if(fp==NULL) { printf("---file open failed \n"); return -7; } printf("---beging read data \n"); //循环读取数据 while(1) { n_video_source_sample =fread(p_video_source_sample,1,width*height*3/2,fp); //编码视频 printf("====read dat len =%d \n",n_video_source_sample); if(n_video_source_sample <= 0) break; n_video_encode_sample = n_video_encode_sample_size; //ret = encode_video_sample_inc(p_video_encoder,p_video_source_sample,n_video_source_sample,p_video_encode_sample,&n_video_encode_sample,x,y,w,h); int ret = encode_video_sample(p_video_encoder,(unsigned char*)p_video_source_sample,n_video_source_sample,p_video_encode_sample,&n_video_encode_sample); if(ret < 0) { fprintf(stderr ,"avencoder: encode_video_sample fail..\n"); continue; } fwrite(p_video_encode_sample,1,n_video_encode_sample,fpout); } printf("---over\n"); return 0; }
int main(int argc,char **argv) { const char *short_options = "i:w:h:b:d:p:s:g:f:l:?"; struct option long_options[] = { {"help", no_argument, NULL, '?'}, {"index", required_argument, NULL, 'i'}, {"width", required_argument, NULL, 'w'}, {"height", required_argument, NULL, 'h'}, {"bitrate", required_argument, NULL, 'b'}, {"sbitrate",required_argument, NULL, 's'}, {"destaddr",required_argument, NULL, 'd'}, {"pids", required_argument, NULL, 'p'}, {"gopsize", required_argument, NULL, 'g'}, {"fps", required_argument, NULL, 'f'}, {"logfile", required_argument, NULL, 'l'}, {NULL, 0, NULL, 0}, }; int c = -1; bool has_index = false; bool has_destaddr = false; bool has_ebitrate = false; bool has_sbitrate = false; while(1) { c = getopt_long(argc, argv, short_options, long_options, NULL); if(c == -1) break; switch(c) { case '?': printf("Usage:%s [options] index destaddr ....\n",argv[0]); printf("avencoder version %s\n",version_str); printf("-? --help Display this usage information.\n"); printf("-i --index Set the index.\n"); printf("-w --width Set the width.\n"); printf("-h --height Set the height.\n"); printf("-b --bitrate Set the encoder bitrate .\n"); printf("-s --sbitrate Set the smooth bitrate.\n"); printf("-d --destaddr Set the dest addr (ip:port).\n"); printf("-p --pids Set the service_id pmt_pid video_pid audio_pid (pmt_pid:service_id:video_pid:audio_pid).\n"); printf("-g --gopsize Set the video encode gopsize (gopsize_min:gopsize_max).\n"); printf("-l --logfile Set the log file path.\n"); printf("Example: %s --index 0 --width 1280 --height 720 --bitrate 4000000 --pids 1024:1:64:65 --gopsize 5:100 --destaddr 192.168.60.248:14000.\n",argv[0]); printf("Example: %s -i 0 -w 1280 -h 720 -b 4000000 -p 1024:1:64:65 -g 5:100 -d 192.168.60.248:14000.\n",argv[0]); return -1; case 'i': m_index = atoi(optarg); has_index = true; break; case 'w': width = atoi(optarg); break; case 'h': height = atoi(optarg); break; case 'b': encode_bitrate = atoi(optarg); has_ebitrate = true; break; case 's': smooth_bitrate = atoi(optarg); has_sbitrate = true; break; case 'd': if(sscanf(optarg,"%[^:]:%d",destip,&destport) != 2) { fprintf(stderr ,"avencoder: error destip:destport.%s.\n",optarg); return -2; } strncpy(destip_record,destip,sizeof(destip_record)); destport_record = destport; has_destaddr = true; break; case 'p': if(sscanf(optarg,"%d:%d:%d:%d",&pmt_pid,&service_id,&video_pid,&audio_pid) != 4) { fprintf(stderr ,"avencoder: error pmt_pid:service_id:video_pid:audio_pid.%s.\n",optarg); return -3; } break; case 'g': if(sscanf(optarg,"%d:%d",&gopsize_min,&gopsize_max) != 2) { gopsize_min = gopsize_max = atoi(optarg); } break; case 'f': fps = atoi(optarg); break; case 'l': memset(logfile,0,sizeof(logfile)); strncpy(logfile,optarg,sizeof(logfile)); break; } } if(has_index == false || has_destaddr == false) { fprintf(stderr ,"avencoder: index and destaddr is must,not empty.\n"); return -3; } if(has_ebitrate == true && has_sbitrate == false) smooth_bitrate = encode_bitrate*3; else if(has_ebitrate == false && has_sbitrate == true) encode_bitrate = smooth_bitrate/3; if(encode_bitrate < 0) encode_bitrate = 4*1024*1024; //TODO 检查各个参数的有效性 printf("avencoder version %s\n",version_str); printf("++++++index=%d|width=%d|height=%d|smooth_bitrate=%d|encode_bitrate=%d|destip=%s|destport=%d++++++\n",m_index,width,height,smooth_bitrate,encode_bitrate,destip,destport); printf("++++++pmt_pid=%d|service_id=%d|video_pid=%d|audio_pid=%d|gopsize_min=%d|gopsize_max=%d|logfile=%s++++++\n",pmt_pid,service_id,video_pid,audio_pid,gopsize_min,gopsize_max,logfile); InputParams_audiosource audio_source_params; InputParams_videosource video_source_params; InputParams_videoencoder video_encoder_params; InputParams_avmuxer avmuxer_params; InputParams_tssmooth tssmooth_params; audio_source_params.index = m_index; p_audio_source = init_audio_source(&audio_source_params); if(p_audio_source == NULL) { fprintf(stderr ,"avencoder: init_audio_source fail..\n"); return -1; } video_source_params.index = m_index; video_source_params.width = width; video_source_params.height = height; p_video_source = init_video_source(&video_source_params); if(p_video_source == NULL) { fprintf(stderr ,"avencoder: init_video_source fail..\n"); return -1; } p_audio_encoder = init_audio_encoder(); if(p_audio_encoder == NULL) { fprintf(stderr ,"avencoder: init_audio_encoder fail..\n"); return -1; } video_encoder_params.width = width; video_encoder_params.height = height; video_encoder_params.gopsize_min = gopsize_min; video_encoder_params.gopsize_max = gopsize_max; video_encoder_params.bitrate = encode_bitrate; video_encoder_params.fps = fps; p_video_encoder = init_video_encoder(&video_encoder_params); if(p_video_encoder == NULL) { fprintf(stderr ,"avencoder: init_video_encoder fail..\n"); return -1; } #if 0 if(smooth_bitrate > 0) { memset(&tssmooth_params,0,sizeof(tssmooth_params)); tssmooth_params.index = m_index; tssmooth_params.listen_udp_port = 0; strcpy(tssmooth_params.dst_udp_ip,destip); tssmooth_params.dst_udp_port = destport; tssmooth_params.bit_rate = smooth_bitrate; tssmooth_params.buffer_max_size = 10*1024*1024; p_tssmooth = init_tssmooth(&tssmooth_params); if(p_tssmooth == NULL) { fprintf(stderr ,"avencoder: init_smooth fail..\n"); return -1; } strcpy(destip,tssmooth_params.listen_udp_ip); destport = tssmooth_params.listen_udp_port; printf("++++++now dest addr is modify destip=%s|destport=%d++++++\n",destip,destport); } #endif avmuxer_params.codecID = KY_CODEC_ID_H264; avmuxer_params.nWidth = width; avmuxer_params.nHeight = height; avmuxer_params.nBitRate = encode_bitrate; avmuxer_params.nPeakBitRate = smooth_bitrate; avmuxer_params.nSamplerate = 48000; avmuxer_params.nFramerate = fps; snprintf(avmuxer_params.monitorName,sizeof(avmuxer_params.monitorName),"%d.monitor",m_index); snprintf(avmuxer_params.appName,sizeof(avmuxer_params.appName),"%s",argv[0]); strcpy(avmuxer_params.destip,destip); avmuxer_params.destport = destport; avmuxer_params.index = m_index; avmuxer_params.pmt_pid = pmt_pid; avmuxer_params.service_id = service_id; avmuxer_params.video_pid = video_pid; avmuxer_params.audio_pid = audio_pid; p_avmuxer = init_ts_muxer(&avmuxer_params); if(p_avmuxer == NULL) { fprintf(stderr ,"avencoder: init_ts_muxer fail..\n"); return -1; } p_audio_source_sample = (char *)malloc(n_audio_source_sample_size); p_video_source_sample = (char *)malloc(n_video_source_sample_size); if(p_audio_source_sample == NULL || p_video_source_sample == NULL) { fprintf(stderr ,"avencoder: malloc fail..\n"); return -2; } p_audio_encode_sample = (char *)malloc(n_audio_encode_sample_size); p_video_encode_sample = (char *)malloc(n_video_encode_sample_size); if(p_audio_encode_sample == NULL || p_video_encode_sample == NULL) { fprintf(stderr ,"avencoder: malloc fail..\n"); return -2; } pthread_t pthread; int ret = pthread_create(&pthread, NULL, statistics_process, NULL); if(ret != 0) { printf("avencoder: pthread_create fail!...\n"); return -3; } double videopts = 0.0; double audiopts = 0.0; struct timeval tv; long start_time_us,end_time_us; gettimeofday(&tv,NULL); start_time_us = end_time_us = tv.tv_sec*1000 + tv.tv_usec/1000; while(1) { gettimeofday(&tv,NULL); start_time_us = tv.tv_sec*1000 + tv.tv_usec/1000; write_video_frames(); video_pts(p_avmuxer,&videopts); audio_pts(p_avmuxer,&audiopts); //printf("++++++++++videopts = [%lf] audiopts = [%lf]+++++++++\n",videopts,audiopts); while(audiopts < videopts) { write_audio_frames(); video_pts(p_avmuxer,&videopts); audio_pts(p_avmuxer,&audiopts); //printf("----------videopts = [%lf] audiopts = [%lf]---------\n",videopts,audiopts); } gettimeofday(&tv,NULL); end_time_us = tv.tv_sec*1000 + tv.tv_usec/1000; //if(end_time_us - start_time_us >= 40) // printf("1++++++++++start_time_us = [%ld] end_time_us = [%ld]+++++diff=%ld++++\n",start_time_us,end_time_us,end_time_us - start_time_us); if(end_time_us - start_time_us < delaytimeus) usleep((delaytimeus-(end_time_us - start_time_us))*1000); } uninit_audio_source(p_audio_source); uninit_video_source(p_video_source); uninit_audio_encoder(p_audio_encoder); uninit_video_encoder(p_video_encoder); uninit_ts_muxer(p_avmuxer); if(smooth_bitrate > 0 && p_tssmooth) uninit_tssmooth(p_tssmooth); return 0; }