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

Popular posts from this blog

android - Spacing between the stars of a rating bar? -

aspxgridview - Devexpress grid - header filter does not work if column is initially hidden -

c# - How to execute a particular part of code asynchronously in a class -