And I’m on an i7 8 core desktop with 32 GB ram, Win10, deploying to Windows and Linux oses.
Sincerely, -Blake Senftner Mad Computer Scientist > On Dec 18, 2016, at 9:22 AM, Blake Senftner <[email protected]> wrote: > > Hello, > > Working on video (no audio) playback library, I am only seeing frame rates of > 15 fps or less. My code started based on the Dranger examples, but has since > been updated to the latest APIs (such that I compile with no depreciated > warnings.) I am using Visual Studio 2013 Community. > > I have a 160x40 29.97 fps h264 clip with timecodes, and it plays back at > exactly half speed, consuming very little cpu. An rtsp h264 stream from an IP > camera plays back between 10 & 11 fps, while the latest full HD resolution > Rogue One trailer plays back at 15 fps (both only consuming < 20% CPU.) > > My code does not use SDL, so I am using neosmart cross platform pevents > (https://github.com/neosmart/pevents). > > I am using one thread to read packets, decode them to yuv & convert to RGB. > OpenGL does the display in the main thread. > > Does achieving higher frame rates require the packet reading and packet > decoding in separate threads? I thought the 160x40 file would decompress fast > enough that I’d need to add necessary timing logic to delay the frames, but > that is not the case. It plays > > Here’s the general logic of my playback setup, abbreviated for clarity, and > the packet reading is below that: > > ------------------------------------------------------------------------------------------ > avformat_open_input( &mp_format_context, [path to file or stream], NULL, NULL > ); > avformat_find_stream_info( mp_format_context, NULL ); > m_video_stream = -1; > for (ce_uint i = 0; i < (ce_uint)mp_format_context->nb_streams; i++) { > if > (mp_format_context->streams[i]->codecpar->codec_type==AVMEDIA_TYPE_VIDEO) { > m_video_stream = i; > break; > } > } > if (m_video_stream == -1) > return false; > > AVCodecParameters* codecPars = > mp_format_context->streams[m_video_stream]->codecpar; > > AVCodec* pCodec = avcodec_find_decoder( codecPars->codec_id ); > if (!pCodec) > return false; > > mp_codec_context = avcodec_alloc_context3( pCodec ); > if (avcodec_parameters_to_context( mp_codec_context, codecPars ) != 0) > return false; > > mp_codec_context->thread_count = 0; // tried 4, 8… makes no difference > > AVDictionary* codec_options = NULL; > av_dict_set( &codec_options, "threads", "auto", 0 ); // makes no difference, > tried 4 & 8 too > if (m_stream_type == 2) > av_dict_set( &codec_options, "rtsp_transport", "tcp", 0 ); // needed > for ffplay to work with my ip cam, makes no difference here... > > if (avcodec_open2( mp_codec_context, pCodec, &codec_options ) < 0) > return false; > > mp_decompressed_frame = av_frame_alloc(); > mp_display_frame = av_frame_alloc(); > if (mp_decompressed_frame == NULL || mp_display_frame == NULL) > return false; > > ce_int numBytes = av_image_get_buffer_size( AV_PIX_FMT_RGBA, > mp_codec_context->width, mp_codec_context->height, 1 ); > mp_display_buffer = (uint8_t *)av_malloc( numBytes*sizeof(uint8_t) ); > av_image_fill_arrays( mp_display_frame->data, mp_display_frame->linesize, > > mp_display_buffer, AV_PIX_FMT_RGBA, > mp_codec_context->width, mp_codec_context->height, 1 ); > > mp_sws_context = sws_getContext( mp_codec_context->width, > mp_codec_context->height, mp_codec_context->pix_fmt, > > > mp_codec_context->width, mp_codec_context->height, AV_PIX_FMT_RGBA, > > SWS_BILINEAR, NULL, > NULL, NULL ); > > ————————————————————————————————————————— > > In my packet reading thread, the logic is simple: > > —————————————————————————————————— > uint64_t milliseconds = 1; > > bool media_has_ended = false; > bool camera_has_terminated = false; > ce_uint packet_errors = 0; > > while (true) { > // this basically allows the thread to idle (sleep) but it will > // wake up if the events are signaled > dwWaitRes = neosmart::WaitForEvent(m_stop_local_spin_event, > milliseconds); > > if (0 == dwWaitRes) // stop event > break; > > else if (m_is_playing && !m_paused) { > > // I’ve got 16 packet buffers so I can look at their data, but > only use one at a time: > ce_uint curr_packet_index = m_total_video_packets % > CE_LIBAV_NUMVIDPKTS; > AVPacket* curr_packet = &m_packet[ curr_packet_index ]; > m_total_video_packets++; > > int stream_status = av_read_frame(mp_format_context, > curr_packet); > if (stream_status < 0) { > > if (m_stream_type == 0) { // end of media file // > stream_types: 0=Media, 1=USB, 2=IP > media_has_ended = true; > break; > } > else { // camera stream has terminated unexpectedly > camera_has_terminated = true; > break; > } > } > else { // stream delivered a packet fine > > if (curr_packet->stream_index == m_video_stream) { > > // Decode video frame(s): > int ret = avcodec_send_packet( > mp_codec_context, curr_packet ); > if (ret < 0) { > > if (ret == AVERROR_EOF && m_stream_type > == 0) { > media_has_ended = true; > break; > } > else packet_errors++; > } > else { > > while (!ret) > { > ret = avcodec_receive_frame( > mp_codec_context, mp_decompressed_frame ); > if (!ret) > handle_new_frame( > curr_packet, curr_packet_index ); > > } > > } > av_packet_unref(curr_packet); > > } // end stream delivered a packet > > } // end if (m_is_playing && !m_paused) > } // end while (true) > > if (media_has_ended) { > if (mp_stream_ended_callback) > (mp_stream_ended_callback)(m_frames_received, > mp_stream_ended_object); > > if (camera_has_terminated) > if (mp_term_callback) > (mp_term_callback)(mp_term_object); > > > —————————————————————————————————— > > > Sincerely, > -Blake Senftner > Mad Computer Scientist > > p.s. > > My ffmpeg libav* 3.2 libs are, downloaded pre-built from Zeranoe early > November, my versions are: > > libavutil 55. 34.100 / 55. 34.100 > libavcodec 57. 64.100 / 57. 64.100 > libavformat 57. 56.100 / 57. 56.100 > libavdevice 57. 1.100 / 57. 1.100 > libavfilter 6. 65.100 / 6. 65.100 > libswscale 4. 2.100 / 4. 2.100 > libswresample 2. 3.100 / 2. 3.100 > libpostproc 54. 1.100 / 54. 1.100 > > _______________________________________________ > Libav-user mailing list > [email protected] > http://ffmpeg.org/mailman/listinfo/libav-user _______________________________________________ Libav-user mailing list [email protected] http://ffmpeg.org/mailman/listinfo/libav-user
