c - FFmpeg video from file to network -


i working ffmpeg in video streaming solution on rtp. bugs me how stream @ correct framerate. using sleep in main streaming loop:

while (av_read_frame (input_format_ctx, &packet) >= 0) { // read video packet long eof not reached or error occurr         if(packet.stream_index == 0) {             if (av_interleaved_write_frame(output_format_ctx, &packet) < 0) { // write packet output stream                 av_packet_unref(&packet); // wipe packet                 av_free_packet(&packet); // release packet , finishes if problem occured                 break;              }             av_packet_unref(&packet); // wipe packet             av_free_packet(&packet); // release packet         }          current_time = getsystemtime(); // system time         adaptativesleep ((last_time + 1/(output_framerate)) - current_time); // sleep according framerate         last_time = getsystemtime(); // finish      } 

is there correct way of letting ffmpeg handle framerate?

thanks in advance

p.s.: remux stream, result ffmpeg runs through file in few seconds witought "sleep".

the avcodeccontext.pkt_timebase , avcodeccontext.time_base need keep stream running smoothly. each stream has own pkt_timebase. when broadcasting, use 1 stream sync system clock. use avpacket.pts , ffmpegs function av_q2d() convert pts value seconds double value.

double time_base = av_q2d(ctx->pkt_timebase); int64_t time_stamp = packet->pts; double packet_time = time_base * time_stamp; // time stamp in seconds 

from there sync first streams packet system clock. pauses between sending following packets easier handle.

the following function nothing streaming illustrate syncing system clock.

ffvideoframe *ffmpeg::getvideoframe(double r_time) { // r_time current system time     ffvideoframe *vframe = nullptr;      double timestamp;     double clock_current_time = r_time - sys_clock_start;     double clock_current_frame = 0.0;      mutex_vid_queues.lock();      int vid_queue_size = vid_queue.size();      if (playback_started) {         if (vid_queue_size > max_vid_overrun) { // keep buffer queues low             playback_clock_start += 0.75;             logd("timeshift buffers on max_vid_overrun");         } else if (vid_queue_size < 20) {             playback_clock_start -= 0.4; // resync             logd("timeshift buffers below 20");         }     }      if (!playback_started) {         // queued video buffers need @ least 1 second network stream          if (((vid_queue_size > min_vid_frames_start_non_network && !isnetworkstream)                 || (vid_queue_size > min_vid_frames_start && isnetworkstream))                 ) {              playback_started = true;              vframe = vid_queue.front();             vid_queue.pop_front();              playback_clock_start = vframe->timestamp_f; // set stream start time time stamp              sys_clock_start = r_time; // set system start time current time         }     } else {         bool in_bounds = true;         ffvideoframe *frame_temp;         int drop_count = 0;          while (in_bounds) {             if (vid_queue_size == 0) {                 in_bounds = false;             } else {                 frame_temp = vid_queue.front();                  timestamp = frame_temp->timestamp_f;                 clock_current_frame = timestamp - playback_clock_start;                  if (clock_current_frame > clock_current_time) {                     in_bounds = false;                 } else {                      // adds 0.xx of second tolerance video playback removed here                     // may increased @ point                      vid_queue.pop_front();                     vid_queue_size--;                      if (isnetworkstream                         && fabs(clock_current_time - clock_current_frame) < 0.05) {                         in_bounds = false;                     }                      if (vframe) {                         vid_unused.push_back(vframe);                         drop_count++;                     }                      vframe = frame_temp;                 }             }         }          // if rendering takes long dropped frames occur          if (drop_count > 0) logd("dumped %d video frames", drop_count);     }      mutex_vid_queues.unlock();      if (vframe) clock_last_frame = (int64_t)timestamp;      return vframe; } 

Comments

Popular posts from this blog

PHP and MySQL WP -

android - InAppBilling registering BroadcastReceiver in AndroidManifest -

go - golang pprof for c library code -