<div dir="ltr"><div><div><div>Hi Guys,<br><br></div>I am working on a threaded video reader to spread the decode workload on some more cores and gain some speed. My source is included below:<br><br></div>The thing is that I dont see a time improvement when starting two processes instead of one. On a 80mb mp4 file it takes 6 seconds to decode the video, while doing two in parallel takes 12 seconds. I can see that two cores's are used 100 percent. Im on a fast SSD disk so I dont think im IO limited.<br><br></div><div>What could be the case. Is it the same decoder taht is doing all the work? Do I perhaps need to instantiate a context or something?<br></div><div><div><br></div><div>kind regards<br></div><div><br>-- <br>Jesper Taxbøl<br><br><br><br><br><div><div>#include "BlockReader.h"<br>#include <iostream><br>#include <stdio.h><br>#include <unistd.h><br><br>void frameReaderThread(char* fn, Queue<AVFrame*>* q)<br>{<br> clock_t end;<br> clock_t begin= clock();<br> double elapsed_secs;<br><br> AVCodec *pCodec;<br> int frame_count;<br> AVFrame *pAVFrame;<br> AVPacket packet;<br> AVFormatContext *pFormatCtx;<br> int videoStreamIndex;<br> int audioStreamIndex;<br> AVCodecContext *pCodecCtx = NULL;<br> AVCodecContext *pCodecCtxOrig = NULL;<br><br> cout << fn << endl;<br><br> frame_count = 0;<br><br> av_init_packet(&packet);<br><br> pFormatCtx = NULL;<br><br> if(avformat_open_input(&pFormatCtx, fn, NULL, NULL)!=0)<br> {<br> cout << "Could not open file: " << fn << endl;<br> exit(1);<br> }<br><br> // Retrieve stream information<br> if(avformat_find_stream_info(pFormatCtx, NULL)<0)<br> {<br> cout << "Cant find stream info" << endl;<br> exit(1);<br> }<br><br> // Dump information about file onto standard error<br> //av_dump_format(pFormatCtx, 0, fn, 0);<br><br> videoStreamIndex = -1;<br> audioStreamIndex = -1;<br><br> for(unsigned int i=0; i<pFormatCtx->nb_streams; i++)<br> {<br> if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO)<br> {<br> videoStreamIndex = i;<br> }<br> if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_AUDIO)<br> {<br> audioStreamIndex = i;<br> }<br> }<br><br> //cout << "video index " << videoStreamIndex << endl;<br> //cout << "audio index " << audioStreamIndex << endl;<br><br> if(videoStreamIndex == -1)<br> {<br> cout << "Unable to find a video index" << endl;<br> exit(1);<br> }<br><br> // Get a pointer to the codec context for the video stream<br> pCodecCtxOrig = pFormatCtx->streams[videoStreamIndex]->codec;<br><br> /* find the correct video decoder */<br> pCodec = avcodec_find_decoder(pCodecCtxOrig->codec_id);<br> if (!pCodec) {<br> fprintf(stderr, "Codec not found\n");<br> exit(1);<br> }<br><br> //Dont know if this is required<br> pCodecCtx = avcodec_alloc_context3(pCodec);<br> if(avcodec_copy_context(pCodecCtx, pCodecCtxOrig) != 0) {<br> fprintf(stderr, "Couldn't copy codec context");<br> exit(1);<br> }<br><br> cout << "Video codec is " << pCodec->name << endl;<br><br> /* open it */<br> if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {<br> fprintf(stderr, "Could not open codec\n");<br> exit(1);<br> }<br><br><br> bool run = true;<br><br><br> end = clock();<br> elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;<br> cout << "Prepare time: " << fn << " " << elapsed_secs << endl;<br> begin = clock();<br><br> do{<br> //Build a frame<br> //pAVFrame = new AVFrame();<br> pAVFrame = av_frame_alloc();<br><br> if (!pAVFrame) {<br> fprintf(stderr, "Could not allocate video frame\n");<br> return;<br> }<br><br> //Fetch packets until frame is built<br> do<br> {<br> /*while(q->size() > 50)<br> {<br> std::this_thread::sleep_for(std::chrono::milliseconds(1));<br> }*/<br><br> int read_bytes = av_read_frame(pFormatCtx, &packet);<br> if(read_bytes < 0)<br> {<br> run = false;<br> cout << "end of file reached" << endl;<br> }<br> else<br> {<br><br> int frameFinished;<br> if(packet.stream_index==videoStreamIndex)<br> {<br> //cout << "video frame " << frame_count++ << " " << fn << endl;<br> avcodec_decode_video2(pCodecCtx, pAVFrame, &frameFinished, &packet);<br> if(frameFinished)<br> {<br> //cout << "returning frame " << frame_count++ << endl;<br> q->push(av_frame_clone(pAVFrame));<br><br> }<br> }else<br> {<br> if(packet.stream_index==audioStreamIndex)<br> {<br> //cout << "audio frame" << endl;<br> }<br> else<br> {<br> //cout << "other frame" << packet.stream_index << endl;<br> }<br> }<br> }<br> }while(run);<br> //av_frame_free(&pAVFrame);<br> }while(run);<br><br> end = clock();<br> elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;<br> cout << "Decode time: " << fn << " " << elapsed_secs << endl;<br> begin = clock();<br><br> //Signal no more frames<br> q->push(NULL);<br> av_frame_free(&pAVFrame);<br><br> // Close the codecs<br> avcodec_close(pCodecCtx);<br> avcodec_close(pCodecCtxOrig);<br><br> // Close the video file<br> avformat_close_input(&pFormatCtx);<br>}<br><br>BlockReader::BlockReader(char* fn): Block()<br>{<br> cout << "BlockReader::Constructor "<< serial_number << " " << fn << endl;<br><br> //Spawn off thread to cache frames<br> std::thread t(frameReaderThread, fn, &frames);<br> t.detach();<br>}<br><br>AVFrame* BlockReader::getFrame(float t_seconds)<br>{<br> return frames.pop();<br>}<br><br>BlockReader::~BlockReader()<br>{<br> cout << "Blockreader::Destructor " << serial_number << endl;<br>}<br><br><br><br><br><div class="gmail_signature" data-smartmail="gmail_signature"><br><br></div>
</div></div></div></div></div>