]> git.sesse.net Git - nageru/blobdiff - h264encode.cpp
Fix a leak in the H.264 encoder.
[nageru] / h264encode.cpp
index 6e946d961f54b7510dbd515976d2d224d1165a93..a16a5ea0b376dc4ed5678a48b7c4417ef433533e 100644 (file)
@@ -1469,6 +1469,12 @@ static int render_picture(void)
     va_status = vaRenderPicture(va_dpy, context_id, &pic_param_buf, 1);
     CHECK_VASTATUS(va_status, "vaRenderPicture");
 
+    // Supposedly vaRenderPicture() is supposed to destroy the buffer implicitly,
+    // but if we don't delete it here, we get leaks. The GStreamer implementation
+    // does the same.
+    va_status = vaDestroyBuffer(va_dpy, pic_param_buf);
+    CHECK_VASTATUS(va_status, "vaDestroyBuffer");
+
     return 0;
 }
 
@@ -1635,11 +1641,17 @@ static int render_slice(void)
 
     va_status = vaCreateBuffer(va_dpy, context_id, VAEncSliceParameterBufferType,
                                sizeof(slice_param), 1, &slice_param, &slice_param_buf);
-    CHECK_VASTATUS(va_status, "vaCreateBuffer");;
+    CHECK_VASTATUS(va_status, "vaCreateBuffer");
 
     va_status = vaRenderPicture(va_dpy, context_id, &slice_param_buf, 1);
     CHECK_VASTATUS(va_status, "vaRenderPicture");
-    
+
+    // Supposedly vaRenderPicture() is supposed to destroy the buffer implicitly,
+    // but if we don't delete it here, we get leaks. The GStreamer implementation
+    // does the same.
+    va_status = vaDestroyBuffer(va_dpy, slice_param_buf);
+    CHECK_VASTATUS(va_status, "vaDestroyBuffer");
+
     return 0;
 }
 
@@ -1698,14 +1710,19 @@ int H264Encoder::save_codeddata(storage_task task)
 
         AVFrame *frame = avcodec_alloc_frame();
         frame->nb_samples = audio.size() / 2;
-        frame->format = AV_SAMPLE_FMT_FLTP;
+        frame->format = AV_SAMPLE_FMT_S32;
         frame->channel_layout = AV_CH_LAYOUT_STEREO;
 
-        unique_ptr<float[]> planar_samples(new float[audio.size()]);
-        avcodec_fill_audio_frame(frame, 2, AV_SAMPLE_FMT_FLTP, (const uint8_t*)planar_samples.get(), audio.size() * sizeof(float), 0);
-        for (int i = 0; i < frame->nb_samples; ++i) {
-            planar_samples[i] = audio[i * 2 + 0];
-            planar_samples[i + frame->nb_samples] = audio[i * 2 + 1];
+        unique_ptr<int32_t[]> int_samples(new int32_t[audio.size()]);
+        avcodec_fill_audio_frame(frame, 2, AV_SAMPLE_FMT_S32, (const uint8_t*)int_samples.get(), audio.size() * sizeof(int32_t), 0);
+        for (int i = 0; i < frame->nb_samples * 2; ++i) {
+            if (audio[i] >= 1.0f) {
+                int_samples[i] = 2147483647;
+            } else if (audio[i] <= -1.0f) {
+                int_samples[i] = -2147483647;
+            } else {
+                int_samples[i] = lrintf(audio[i] * 2147483647.0f);
+            }
         }
 
         AVPacket pkt;
@@ -1720,6 +1737,7 @@ int H264Encoder::save_codeddata(storage_task task)
         }
         // TODO: Delayed frames.
         avcodec_free_frame(&frame);
+        av_free_packet(&pkt);
     }
 
 #if 0