#include "deferred_pipeline.hpp" #include #include #include #include #include #include class Frame { public: bool processed = false; size_t fid; char ftype; std::mutex m; std::condition_variable cv; std::vector depend_on; Frame(size_t i, char t) : fid{i}, ftype{t} {} }; std::vector> video; std::vector vec1; std::mutex global_m; void encode_frame(const size_t idx, const size_t num_threads, const size_t num_frames) { size_t fid; size_t iterations = 1+(num_frames-1)/num_threads; for (size_t i = 0; i < iterations; ++i) { fid = num_threads*i+idx; if (fid >= num_frames) { break; } // I frame does not have any depency if (video[fid]->ftype == 'I') { std::unique_lock lk(video[fid]->m); work_I(); video[fid]->processed = true; video[fid]->cv.notify_all(); continue; } else if (video[fid]->ftype == 'P') { // wait on the dependency { int depend_on_id = video[fid]->depend_on[0]; std::unique_lock lk(video[depend_on_id]->m); video[depend_on_id]->cv.wait(lk, [&]{ return video[depend_on_id]->processed; }); } // dependency is resolved { std::unique_lock lk(video[fid]->m); work_P(); video[fid]->processed = true; video[fid]->cv.notify_all(); } } else { // wait on the first dependency int depend_on_id = video[fid]->depend_on[0]; { std::unique_lock lk(video[depend_on_id]->m); video[depend_on_id]->cv.wait(lk, [&]{ return video[depend_on_id]->processed; }); } // wait on the second dependency if (video[fid]->depend_on.size() > 1) { depend_on_id = video[fid]->depend_on[1]; } { std::unique_lock lk(video[depend_on_id]->m); video[depend_on_id]->cv.wait(lk, [&]{ return video[depend_on_id]->processed; }); } // dependency is resolved { std::unique_lock lk(video[fid]->m); work_B(); video[fid]->processed = true; video[fid]->cv.notify_all(); } } } } std::chrono::microseconds measure_time_pthread( size_t num_threads, std::string type, size_t num_frames) { std::chrono::microseconds elapsed; std::vector threads; for (size_t i = 0; i < num_frames; ++i) { // x264 frame pattern is viedo_1 // video_1 has 128 frames in total if (type == "1") { std::unique_ptr p(new Frame(i, video_1[i%128])); video.emplace_back(std::move(p)); } // x264 frame pattern is video_2. // video_2 has 300 frames in total. else { std::unique_ptr p(new Frame(i, video_2[i%300])); video.emplace_back(std::move(p)); } } // construct the depend_on vector of each frame for (size_t i = 0; i < num_frames; ++i) { // I frames do not depend on other frames if (video[i]->ftype == 'I') { continue; } // P frames depend on its previous I or P frame // have one dependency else if (video[i]->ftype == 'P') { int p_idx = i-1; while(p_idx >= 0) { if (video[p_idx]->ftype == 'I' || video[p_idx]->ftype == 'P') { video[i]->depend_on.push_back(p_idx); break; } --p_idx; } } // B frames depend on its previous I or P frame and its later I or P frame // have up to two dependencies else { int p_idx = i-1, l_idx = i+1; while(p_idx >= 0) { if (video[p_idx]->ftype == 'I' || video[p_idx]->ftype == 'P') { video[i]->depend_on.push_back(p_idx); break; } --p_idx; } while(l_idx < static_cast(num_frames)) { if (video[l_idx]->ftype == 'I' || video[l_idx]->ftype == 'P') { video[i]->depend_on.push_back(l_idx); break; } ++l_idx; } } } auto beg = std::chrono::high_resolution_clock::now(); for (size_t i = 0; i < num_threads; ++i) { threads.emplace_back( std::thread(encode_frame, i, num_threads, num_frames)); } // join all threads for (size_t i = 0; i < num_threads; ++i) { threads[i].join(); } auto end = std::chrono::high_resolution_clock::now(); elapsed = std::chrono::duration_cast(end - beg); return elapsed; }