c++ - libavcodec, how to transcode video with different frame rates? -
i'm grabbing video frames camera via v4l, , need transcode them in mpeg4 format successively stream them via rtp.
everything "works" there's don't while re-encoding: input stream produces 15fps, while output @ 25fps, , every input frame converted in 1 single video object sequence (i verified simple check on output bitstream). guess receiver correctly parsing mpeg4 bitstream rtp packetization somehow wrong. how supposed split encoded bitstream in 1 or more avpacket ? maybe i'm missing obvious , need b/p frame markers, think i'm not using encode api correctly.
here excerpt of code, based on available ffmpeg samples:
// input frame avframe *picture; // input frame color-space converted avframe *planar; // input format context, video4linux2 avformatcontext *ifmtctx; // output codec context, mpeg4 avcodeccontext *octx; // [ init ] // ... octx->time_base.num = 1; octx->time_base.den = 25; octx->gop_size = 10; octx->max_b_frames = 1; octx->bit_rate = 384000; octx->pix_fmt = pix_fmt_yuv420p; for(;;) { // read frame rdres = av_read_frame( ifmtctx, &pkt ); if ( rdres >= 0 && pkt.size > 0 ) { // decode icdcctx->reordered_opaque = pkt.pts; int decoderes = avcodec_decode_video2( icdcctx, picture, &gotpicture, &pkt ); if ( decoderes >= 0 && gotpicture ) { // scale / convert color space avpicture_fill((avpicture *)planar, planarbuf.get(), octx->pix_fmt, octx->width, octx->height); sws_scale(sws, picture->data, picture->linesize, 0, icdcctx->height, planar->data, planar->linesize); // encode bytearray encbuf( 65536 ); int encsize = avcodec_encode_video( octx, encbuf.get(), encbuf.size(), planar ); // happens every gop end while( encsize == 0 ) encsize = avcodec_encode_video( octx, encbuf.get(), encbuf.size(), 0 ); // send transcoded bitstream result pts if ( encsize > 0 ) enqueueframe( octx->coded_frame->pts, encbuf.get(), encsize ); } } }
most simple solution use 2 threads. first thread things outlined in question (decoding, scaling / color-space conversion, coding). partially transcoded frames written intermediate queue shared second thread. maximum length of queue in particular case (converting lower higher bitrate) 1 frame. second thread reading in loop frames input queue this:
void fpsconverter::threadproc() { timebeginperiod(1); dword start_time = timegettime(); int frame_counter = 0; while(!shouldfinish()) { frame *frame = null; dword time_begin = timegettime(); readinputframe(frame); writetooutputqueue(frame); dword time_end = timegettime(); dword next_frame_time = start_time + ++frame_counter * frame_time; dword time_to_sleep = next_frame_time - time_end; if (time_to_sleep > 0) { sleep(time_to_sleep); } } timeendperiod(1); }
when cpu power sufficient , higher fidelity , smoothness required compute output frame not 1 frame more frames sort of interpolation (similar techniques used in mpeg codecs). closer output frame time stamp input frame time stamp, more weight should assign particular input frame.
Comments
Post a Comment