Lines 542-575
gst_ffmpegvidenc_propose_allocation (GstVideoEncoder * encoder,
Link Here
|
542 |
query); |
541 |
query); |
543 |
} |
542 |
} |
544 |
|
543 |
|
545 |
static void |
|
|
546 |
ffmpegenc_setup_working_buf (GstFFMpegVidEnc * ffmpegenc) |
547 |
{ |
548 |
guint wanted_size = |
549 |
ffmpegenc->context->width * ffmpegenc->context->height * 6 + |
550 |
FF_MIN_BUFFER_SIZE; |
551 |
|
552 |
/* Above is the buffer size used by ffmpeg/ffmpeg.c */ |
553 |
|
554 |
if (ffmpegenc->working_buf == NULL || |
555 |
ffmpegenc->working_buf_size != wanted_size) { |
556 |
if (ffmpegenc->working_buf) |
557 |
g_free (ffmpegenc->working_buf); |
558 |
ffmpegenc->working_buf_size = wanted_size; |
559 |
ffmpegenc->working_buf = g_malloc (ffmpegenc->working_buf_size); |
560 |
} |
561 |
ffmpegenc->buffer_size = wanted_size; |
562 |
} |
563 |
|
564 |
static GstFlowReturn |
544 |
static GstFlowReturn |
565 |
gst_ffmpegvidenc_handle_frame (GstVideoEncoder * encoder, |
545 |
gst_ffmpegvidenc_handle_frame (GstVideoEncoder * encoder, |
566 |
GstVideoCodecFrame * frame) |
546 |
GstVideoCodecFrame * frame) |
567 |
{ |
547 |
{ |
568 |
GstFFMpegVidEnc *ffmpegenc = (GstFFMpegVidEnc *) encoder; |
548 |
GstFFMpegVidEnc *ffmpegenc = (GstFFMpegVidEnc *) encoder; |
569 |
GstBuffer *outbuf; |
549 |
GstBuffer *outbuf; |
570 |
gint ret_size = 0, c; |
550 |
gint ret = 0, c; |
571 |
GstVideoInfo *info = &ffmpegenc->input_state->info; |
551 |
GstVideoInfo *info = &ffmpegenc->input_state->info; |
572 |
GstVideoFrame vframe; |
552 |
GstVideoFrame vframe; |
|
|
553 |
AVPacket pkt; |
554 |
int have_data = 0; |
573 |
|
555 |
|
574 |
if (GST_VIDEO_CODEC_FRAME_IS_FORCE_KEYFRAME (frame)) |
556 |
if (GST_VIDEO_CODEC_FRAME_IS_FORCE_KEYFRAME (frame)) |
575 |
ffmpegenc->picture->pict_type = AV_PICTURE_TYPE_I; |
557 |
ffmpegenc->picture->pict_type = AV_PICTURE_TYPE_I; |
Lines 595-612
gst_ffmpegvidenc_handle_frame (GstVideoEncoder * encoder,
Link Here
|
595 |
gst_ffmpeg_time_gst_to_ff (frame->pts / |
577 |
gst_ffmpeg_time_gst_to_ff (frame->pts / |
596 |
ffmpegenc->context->ticks_per_frame, ffmpegenc->context->time_base); |
578 |
ffmpegenc->context->ticks_per_frame, ffmpegenc->context->time_base); |
597 |
|
579 |
|
598 |
ffmpegenc_setup_working_buf (ffmpegenc); |
580 |
have_data = 0; |
|
|
581 |
memset (&pkt, 0, sizeof (pkt)); |
599 |
|
582 |
|
600 |
ret_size = avcodec_encode_video (ffmpegenc->context, |
583 |
ret = |
601 |
ffmpegenc->working_buf, ffmpegenc->working_buf_size, ffmpegenc->picture); |
584 |
avcodec_encode_video2 (ffmpegenc->context, &pkt, ffmpegenc->picture, |
|
|
585 |
&have_data); |
602 |
|
586 |
|
603 |
gst_video_frame_unmap (&vframe); |
587 |
gst_video_frame_unmap (&vframe); |
604 |
|
588 |
|
605 |
if (ret_size < 0) |
589 |
if (ret < 0) |
606 |
goto encode_fail; |
590 |
goto encode_fail; |
607 |
|
591 |
|
608 |
/* Encoder needs more data */ |
592 |
/* Encoder needs more data */ |
609 |
if (!ret_size) |
593 |
if (!have_data) |
610 |
return GST_FLOW_OK; |
594 |
return GST_FLOW_OK; |
611 |
|
595 |
|
612 |
/* save stats info if there is some as well as a stats file */ |
596 |
/* save stats info if there is some as well as a stats file */ |
Lines 621-635
gst_ffmpegvidenc_handle_frame (GstVideoEncoder * encoder,
Link Here
|
621 |
/* Get oldest frame */ |
605 |
/* Get oldest frame */ |
622 |
frame = gst_video_encoder_get_oldest_frame (encoder); |
606 |
frame = gst_video_encoder_get_oldest_frame (encoder); |
623 |
|
607 |
|
624 |
/* Allocate output buffer */ |
608 |
outbuf = |
625 |
if (gst_video_encoder_allocate_output_frame (encoder, frame, |
609 |
gst_buffer_new_wrapped_full (0, pkt.data, pkt.size, 0, pkt.size, pkt.data, |
626 |
ret_size) != GST_FLOW_OK) { |
610 |
av_free); |
627 |
gst_video_codec_frame_unref (frame); |
611 |
frame->output_buffer = outbuf; |
628 |
goto alloc_fail; |
|
|
629 |
} |
630 |
|
631 |
outbuf = frame->output_buffer; |
632 |
gst_buffer_fill (outbuf, 0, ffmpegenc->working_buf, ret_size); |
633 |
|
612 |
|
634 |
/* buggy codec may not set coded_frame */ |
613 |
/* buggy codec may not set coded_frame */ |
635 |
if (ffmpegenc->context->coded_frame) { |
614 |
if (ffmpegenc->context->coded_frame) { |
Lines 655-670
encode_fail:
Link Here
|
655 |
#endif /* GST_DISABLE_GST_DEBUG */ |
634 |
#endif /* GST_DISABLE_GST_DEBUG */ |
656 |
return GST_FLOW_OK; |
635 |
return GST_FLOW_OK; |
657 |
} |
636 |
} |
658 |
alloc_fail: |
|
|
659 |
{ |
660 |
#ifndef GST_DISABLE_GST_DEBUG |
661 |
GstFFMpegVidEncClass *oclass = |
662 |
(GstFFMpegVidEncClass *) (G_OBJECT_GET_CLASS (ffmpegenc)); |
663 |
GST_ERROR_OBJECT (ffmpegenc, |
664 |
"avenc_%s: failed to allocate buffer", oclass->in_plugin->name); |
665 |
#endif /* GST_DISABLE_GST_DEBUG */ |
666 |
return GST_FLOW_ERROR; |
667 |
} |
668 |
} |
637 |
} |
669 |
|
638 |
|
670 |
static GstFlowReturn |
639 |
static GstFlowReturn |
Lines 673-679
gst_ffmpegvidenc_flush_buffers (GstFFMpegVidEnc * ffmpegenc, gboolean send)
Link Here
|
673 |
GstVideoCodecFrame *frame; |
642 |
GstVideoCodecFrame *frame; |
674 |
GstFlowReturn flow_ret = GST_FLOW_OK; |
643 |
GstFlowReturn flow_ret = GST_FLOW_OK; |
675 |
GstBuffer *outbuf; |
644 |
GstBuffer *outbuf; |
676 |
gint ret_size; |
645 |
gint ret; |
|
|
646 |
AVPacket pkt; |
647 |
int have_data = 0; |
677 |
|
648 |
|
678 |
GST_DEBUG_OBJECT (ffmpegenc, "flushing buffers with sending %d", send); |
649 |
GST_DEBUG_OBJECT (ffmpegenc, "flushing buffers with sending %d", send); |
679 |
|
650 |
|
Lines 683-695
gst_ffmpegvidenc_flush_buffers (GstFFMpegVidEnc * ffmpegenc, gboolean send)
Link Here
|
683 |
|
654 |
|
684 |
while ((frame = |
655 |
while ((frame = |
685 |
gst_video_encoder_get_oldest_frame (GST_VIDEO_ENCODER (ffmpegenc)))) { |
656 |
gst_video_encoder_get_oldest_frame (GST_VIDEO_ENCODER (ffmpegenc)))) { |
|
|
657 |
memset (&pkt, 0, sizeof (pkt)); |
658 |
have_data = 0; |
686 |
|
659 |
|
687 |
ffmpegenc_setup_working_buf (ffmpegenc); |
660 |
ret = avcodec_encode_video2 (ffmpegenc->context, &pkt, NULL, &have_data); |
688 |
|
661 |
|
689 |
ret_size = avcodec_encode_video (ffmpegenc->context, |
662 |
if (ret < 0) { /* there should be something, notify and give up */ |
690 |
ffmpegenc->working_buf, ffmpegenc->working_buf_size, NULL); |
|
|
691 |
|
692 |
if (ret_size < 0) { /* there should be something, notify and give up */ |
693 |
#ifndef GST_DISABLE_GST_DEBUG |
663 |
#ifndef GST_DISABLE_GST_DEBUG |
694 |
GstFFMpegVidEncClass *oclass = |
664 |
GstFFMpegVidEncClass *oclass = |
695 |
(GstFFMpegVidEncClass *) (G_OBJECT_GET_CLASS (ffmpegenc)); |
665 |
(GstFFMpegVidEncClass *) (G_OBJECT_GET_CLASS (ffmpegenc)); |
Lines 707-726
gst_ffmpegvidenc_flush_buffers (GstFFMpegVidEnc * ffmpegenc, gboolean send)
Link Here
|
707 |
(("Could not write to file \"%s\"."), ffmpegenc->filename), |
677 |
(("Could not write to file \"%s\"."), ffmpegenc->filename), |
708 |
GST_ERROR_SYSTEM); |
678 |
GST_ERROR_SYSTEM); |
709 |
|
679 |
|
710 |
if (send) { |
680 |
if (send && have_data) { |
711 |
if (gst_video_encoder_allocate_output_frame (GST_VIDEO_ENCODER |
681 |
outbuf = gst_buffer_new_wrapped_full (0, pkt.data, pkt.size, 0, pkt.size, |
712 |
(ffmpegenc), frame, ret_size) != GST_FLOW_OK) { |
682 |
pkt.data, av_free); |
713 |
#ifndef GST_DISABLE_GST_DEBUG |
683 |
frame->output_buffer = outbuf; |
714 |
GstFFMpegVidEncClass *oclass = |
|
|
715 |
(GstFFMpegVidEncClass *) (G_OBJECT_GET_CLASS (ffmpegenc)); |
716 |
GST_WARNING_OBJECT (ffmpegenc, |
717 |
"avenc_%s: failed to allocate buffer", oclass->in_plugin->name); |
718 |
#endif /* GST_DISABLE_GST_DEBUG */ |
719 |
gst_video_codec_frame_unref (frame); |
720 |
break; |
721 |
} |
722 |
outbuf = frame->output_buffer; |
723 |
gst_buffer_fill (outbuf, 0, ffmpegenc->working_buf, ret_size); |
724 |
|
684 |
|
725 |
if (ffmpegenc->context->coded_frame->key_frame) |
685 |
if (ffmpegenc->context->coded_frame->key_frame) |
726 |
GST_VIDEO_CODEC_FRAME_SET_SYNC_POINT (frame); |
686 |
GST_VIDEO_CODEC_FRAME_SET_SYNC_POINT (frame); |
Lines 855-864
gst_ffmpegvidenc_stop (GstVideoEncoder * encoder)
Link Here
|
855 |
fclose (ffmpegenc->file); |
815 |
fclose (ffmpegenc->file); |
856 |
ffmpegenc->file = NULL; |
816 |
ffmpegenc->file = NULL; |
857 |
} |
817 |
} |
858 |
if (ffmpegenc->working_buf) { |
|
|
859 |
g_free (ffmpegenc->working_buf); |
860 |
ffmpegenc->working_buf = NULL; |
861 |
} |
862 |
if (ffmpegenc->input_state) { |
818 |
if (ffmpegenc->input_state) { |
863 |
gst_video_codec_state_unref (ffmpegenc->input_state); |
819 |
gst_video_codec_state_unref (ffmpegenc->input_state); |
864 |
ffmpegenc->input_state = NULL; |
820 |
ffmpegenc->input_state = NULL; |
865 |
- |
|
|