AVStream *stream = avformat_new_stream(avctx.get(), nullptr);
if (stream == nullptr) {
fprintf(stderr, "avformat_new_stream() failed\n");
- exit(1);
+ abort();
}
stream->time_base = AVRational{ 1, TIMEBASE };
stream->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
}
if (avformat_write_header(avctx.get(), &options) < 0) {
fprintf(stderr, "avformat_write_header() failed\n");
- exit(1);
+ abort();
}
// Initialize VA-API.
any_frames_to_be_encoded.notify_all();
}
-void MJPEGEncoder::finish_frame(RefCountedFrame frame)
-{
- PBOFrameAllocator::Userdata *userdata = (PBOFrameAllocator::Userdata *)frame->userdata;
-
- if (userdata->data_copy_current_src == PBOFrameAllocator::Userdata::FROM_VA_API) {
- VAResources resources __attribute__((unused)) = move(userdata->va_resources);
- ReleaseVAResources release = move(userdata->va_resources_release);
-
- VAStatus va_status = vaUnmapBuffer(va_dpy->va_dpy, resources.image.buf);
- CHECK_VASTATUS(va_status, "vaUnmapBuffer");
- }
-}
-
int MJPEGEncoder::get_mjpeg_stream_for_card(unsigned card_index)
{
// Only bother doing MJPEG encoding if there are any connected clients
if (av_write_frame(avctx.get(), &pkt) < 0) {
fprintf(stderr, "av_write_frame() failed\n");
- exit(1);
+ abort();
}
}
void MJPEGEncoder::release_va_resources(MJPEGEncoder::VAResources resources)
{
lock_guard<mutex> lock(va_resources_mutex);
- if (va_resources_freelist.size() > 10) {
+ if (va_resources_freelist.size() > 50) {
auto it = va_resources_freelist.end();
--it;
va_status = vaDestroySurfaces(va_dpy->va_dpy, &it->surface, 1);
CHECK_VASTATUS(va_status, "vaDestroySurfaces");
+ va_status = vaDestroyImage(va_dpy->va_dpy, it->image.image_id);
+ CHECK_VASTATUS(va_status, "vaDestroyImage");
+
va_resources_freelist.erase(it);
}
VABufferDestroyer destroy_slice_param(va_dpy->va_dpy, slice_param_buffer);
if (userdata->data_copy_current_src == PBOFrameAllocator::Userdata::FROM_VA_API) {
+ // The pixel data is already put into the image by the caller.
va_status = vaUnmapBuffer(va_dpy->va_dpy, resources.image.buf);
CHECK_VASTATUS(va_status, "vaUnmapBuffer");
- // The pixel data is already put into the image by the caller.
} else {
assert(userdata->data_copy_current_src == PBOFrameAllocator::Userdata::FROM_MALLOC);
CHECK_VASTATUS(va_status, "vaUnmapBuffer");
}
+ qf.frame->data_copy = nullptr;
+
// Seemingly vaPutImage() (which triggers a GPU copy) is much nicer to the
// CPU than vaDeriveImage() and copying directly into the GPU's buffers.
// Exactly why is unclear, but it seems to involve L3 cache usage when there