ffmpgeg ffplay sdl ocx播放器控件推广
目前主要存在的问题就是无法准确的设置h264的帧率,貌似无解,如有解决方法,欢迎指正
直接上代码:
int getFileSize(const char* sFile) { FILE* f = fopen(sFile, "rb"); fseek(f,0,SEEK_END); int s = ftell(f); fclose(f); return s; } class CJpgQueue { public: CJpgQueue() { } ~CJpgQueue() { } void AppendPicFromFile(string szFile) { int s = getFileSize(szFile.c_str()); FILE* f = fopen(szFile.c_str(), "rb"); char* buffer = new char[s]; fread(buffer,1,s,f); string data ; data.append(buffer,s); m_lstJpg.push_back(data); delete[] buffer; } string* GetData(int i) { if (m_lstJpg.empty()) { return NULL; } int index = i%m_lstJpg.size(); list<string>::iterator it; int j = 0; for (it=m_lstJpg.begin();it!=m_lstJpg.end();it++,j++) { if (index == j) { return &*it; } } return NULL; } private: list<string> m_lstJpg; }; int read_src_frame(int i,CJpgQueue* q, AVPacket* packet) { string* s = q->GetData(i); packet->data = (uint8_t *)s->data(); packet->size = s->size(); return 0; } #define CHECKPOINT(p) { if(!p) throw "NULL"; } #define THROWERROR { char err[256]; sprintf(err,"error line:%d \r\n",__LINE__);throw err; } #define CHECKCONDITION(p) { if(!(p)) THROWERROR } int _tmain(int argc, _TCHAR* argv[]) { //FileConvert* fc = new FileConvert(); //fc->DecodeVideo("d:\\wildlife.wmv","d:\\wildlife.mp4"); //FILE* out = fopen("d:\\pgm\\out.h264","wb"); //写h264裸流 //FILE* outyuv = fopen("d:\\pgm\\out.yuv420p","wb"); //just testing int err = 0; try{ CJpgQueue picQueue; for (int i=0;i<8;i++) { char name[200]={0}; sprintf(name,"d:\\pgm\\image\\%d.jpg",i); picQueue.AppendPicFromFile(string(name)); } av_register_all(); AVCodec* dec = avcodec_find_decoder(AV_CODEC_ID_MJPEG); CHECKPOINT(dec) AVCodecContext* dec_ctx = avcodec_alloc_context3(dec); CHECKPOINT(dec_ctx) dec_ctx->width = 1024; dec_ctx->height = 768; dec_ctx->pix_fmt = AV_PIX_FMT_YUVJ444P; if(dec->capabilities&CODEC_CAP_TRUNCATED) dec_ctx->flags|= CODEC_FLAG_TRUNCATED; /* we do not send complete frames */ if(avcodec_open2(dec_ctx,dec,NULL)<0) THROWERROR AVFormatContext* ofmt_ctx=NULL; const char* filename = "d:\\pgm\\out.mp4"; err = avformat_alloc_output_context2(&ofmt_ctx,NULL,"mp4",filename); CHECKCONDITION(err>=0) AVCodec* enc = avcodec_find_encoder(AV_CODEC_ID_H264); CHECKPOINT(enc); AVStream* video_stream=avformat_new_stream(ofmt_ctx, enc); CHECKPOINT(video_stream); video_stream->id = ofmt_ctx->nb_streams -1; AVCodecContext* enc_ctx = video_stream->codec; CHECKPOINT(enc_ctx); //AVCodecContext* enc_ctx = avcodec_alloc_context3(enc); //CHECKPOINT(enc) enc_ctx->codec_id = enc->id; enc_ctx->codec_type = AVMEDIA_TYPE_VIDEO; int bitrate = 1800*1000; enc_ctx->bit_rate = bitrate; enc_ctx->rc_min_rate = bitrate; enc_ctx->rc_max_rate = bitrate; enc_ctx->bit_rate_tolerance= bitrate; enc_ctx->rc_buffer_size = bitrate; enc_ctx->rc_initial_buffer_occupancy = enc_ctx->rc_buffer_size*3/4; enc_ctx->rc_initial_cplx = 0.5; enc_ctx->rc_buffer_aggressivity = (float)1.0; enc_ctx->qmin = 10; enc_ctx->qmax = 30; enc_ctx->qcompress = 0.6; enc_ctx->max_qdiff = 4; enc_ctx->width = 640; enc_ctx->height = 480; enc_ctx->pix_fmt = AV_PIX_FMT_YUV420P; enc_ctx->time_base.den = 25; enc_ctx->time_base.num = 1; enc_ctx->gop_size = 12; enc_ctx->max_b_frames = 3; av_opt_set(enc_ctx->priv_data, "preset", "slow", 0); if (avcodec_open2(enc_ctx,enc,NULL)<0) THROWERROR if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER) { enc_ctx->flags |= CODEC_FLAG_GLOBAL_HEADER; } if (!(ofmt_ctx->oformat->flags & AVFMT_NOFILE)) { err = avio_open(&ofmt_ctx->pb,filename,AVIO_FLAG_WRITE); CHECKCONDITION(err>=0) } err = avformat_write_header(ofmt_ctx,NULL); //不写文件头 av_interleaved_write报除0错误 CHECKCONDITION(err>=0) SwsContext* sws_cxt = sws_getContext(dec_ctx->width,dec_ctx->height,dec_ctx->pix_fmt, enc_ctx->width,enc_ctx->height,enc_ctx->pix_fmt,SWS_BILINEAR,NULL,NULL,NULL); CHECKPOINT(sws_cxt); AVFrame* src_frame = avcodec_alloc_frame(); CHECKPOINT(src_frame); AVPacket src_packet; av_init_packet(&src_packet); src_packet.data = NULL; src_packet.size = 0; AVFrame* dst_frame = avcodec_alloc_frame(); CHECKPOINT(dst_frame) int dst_size = av_image_alloc(dst_frame->data,dst_frame->linesize, enc_ctx->width,enc_ctx->height, enc_ctx->pix_fmt,32); dst_frame->width = enc_ctx->width; dst_frame->height = enc_ctx->height; dst_frame->format = (int)enc_ctx->pix_fmt; dst_frame->pts = 0; AVPacket dst_packet; av_init_packet(&dst_packet); dst_packet.data = NULL; dst_packet.size = 0; int count = 0; int j = 0; while(read_src_frame(j,&picQueue,&src_packet) >=0) { if (count>=200) { break; } int got_frame = 0; if(avcodec_decode_video2(dec_ctx, src_frame,&got_frame,&src_packet )<0) THROWERROR if(got_frame) { sws_scale(sws_cxt, src_frame->data,src_frame->linesize,0,src_frame->height, dst_frame->data,dst_frame->linesize); //写yuv420到文件测试 //for(int h=0;h<enc_ctx->height;h++) //{ // fwrite(dst_frame->data[0] + h * dst_frame->linesize[0],1,enc_ctx->width,outyuv); //} //for(int h=0;h<enc_ctx->height/2;h++) //{ // fwrite(dst_frame->data[1] + h * dst_frame->linesize[1],1,enc_ctx->width/2,outyuv); //}for(int h=0;h<enc_ctx->height/2;h++) //{ // fwrite(dst_frame->data[2] + h * dst_frame->linesize[2],1,enc_ctx->width/2,outyuv); //}fflush(outyuv); int got_packet = 0; if(avcodec_encode_video2(enc_ctx,&dst_packet,dst_frame,&got_packet)<0) THROWERROR; if (got_packet) { //int ret = fwrite(dst_packet.data,1,dst_packet.size, out); //fflush(out); //dst_packet.pts = dst_packet.dts = dst_frame->pts; if(enc_ctx->coded_frame->key_frame) dst_packet.flags |= AV_PKT_FLAG_KEY; dst_packet.stream_index = video_stream->index; dst_packet.dts=dst_packet.pts= dst_frame->pts; err = av_interleaved_write_frame(ofmt_ctx, &dst_packet); CHECKCONDITION(err>=0) av_free_packet(&dst_packet); dst_packet.data = NULL; //重置否则出错 dst_packet.size = 0; } count++; j++; dst_frame->pts += av_rescale_q(1, video_stream->codec->time_base, video_stream->time_base);; } } av_write_trailer(ofmt_ctx); } catch(exception e) { std::cout<<e.what()<<endl; } //fclose(out); return 0; }