add ffmpeg vaapi hw encode, colorpicker fix alpha, titler layout timecode, booby...
authorGood Guy <[email protected]>
Mon, 6 May 2019 23:08:59 +0000 (17:08 -0600)
committerGood Guy <[email protected]>
Mon, 6 May 2019 23:08:59 +0000 (17:08 -0600)
cinelerra-5.1/cinelerra/colorpicker.C
cinelerra-5.1/cinelerra/ffmpeg.C
cinelerra-5.1/cinelerra/ffmpeg.h
cinelerra-5.1/ffmpeg/video/h264_vaapi.mp4 [new file with mode: 0644]
cinelerra-5.1/ffmpeg/video/hevc_vaapi.mp4 [new file with mode: 0644]
cinelerra-5.1/ffmpeg/video/mjpeg_vaapi.mp4 [new file with mode: 0644]
cinelerra-5.1/ffmpeg/video/mpeg2_vaapi.mp4 [new file with mode: 0644]
cinelerra-5.1/plugins/titler/titlerwindow.C
cinelerra-5.1/plugins/titler/titlerwindow.h

index 7238d59d043a2adab7472bba5b5ef91e4565626f..927807b619e0462c3d8f115cc11001c0ae7094c5 100644 (file)
@@ -1405,7 +1405,7 @@ void ColorCircleButton::create_objects()
 void ColorCircleButton::set_color(int color)
 {
        this->color = (color & 0xffffff);
-       this->alpha = (~color>>24);
+       this->alpha = (~color>>24) & 0xff;
        int r = (color>>16) & 0xff;
        int g = (color>>8) & 0xff;
        int b = (color>>0) & 0xff;
index 9f13ec0d3cf8c5593bf04cf366ff9c9dcfa7d2c9..33941868268de5f49194f57f4f463a55c5acf953 100644 (file)
@@ -99,6 +99,12 @@ void FFrame::dequeue()
        fst->dequeue(this);
 }
 
+void FFrame::set_hw_frame(AVFrame *frame)
+{
+       av_frame_free(&frm);
+       frm = frame;
+}
+
 int FFAudioStream::read(float *fp, long len)
 {
        long n = len * nch;
@@ -383,10 +389,12 @@ int FFStream::decode_activate()
                                ret = avcodec_open2(avctx, decoder, &copts);
                        }
                        if( ret >= 0 && hw_type != AV_HWDEVICE_TYPE_NONE ) {
-                               ret = read_packet();
+                               if( need_packet ) {
+                                       need_packet = 0;
+                                       ret = read_packet();
+                               }
                                if( ret >= 0 ) {
                                        AVPacket *pkt = (AVPacket*)ipkt;
-                                       need_packet = 0;
                                        ret = avcodec_send_packet(avctx, pkt);
                                        if( ret < 0 || hw_pix_fmt == AV_PIX_FMT_NONE ) {
                                                ff_err(ret, "HW device init failed, using SW decode.\nfile:%s\n",
@@ -396,9 +404,11 @@ int FFStream::decode_activate()
                                                av_buffer_unref(&hw_device_ctx);
                                                hw_device_ctx = 0;
                                                hw_type = AV_HWDEVICE_TYPE_NONE;
-                                               flushed = 0;
-                                               st_eof(0);
-                                               need_packet = 1;
+                                               int flags = AVSEEK_FLAG_BACKWARD | AVSEEK_FLAG_ANY;
+                                               int idx = st->index;
+                                               av_seek_frame(fmt_ctx, idx, INT64_MIN, flags);
+                                               need_packet = 1;  flushed = 0;
+                                               seeked = 1;  st_eof(0);
                                                ret = 0;
                                                continue;
                                        }
@@ -1045,6 +1055,75 @@ void FFVideoStream::decode_hw_format(AVCodec *decoder, AVHWDeviceType type)
        }
 }
 
+AVHWDeviceType FFVideoStream::encode_hw_activate(const char *hw_dev)
+{
+       AVBufferRef *hw_device_ctx = 0;
+       AVBufferRef *hw_frames_ref = 0;
+       AVHWDeviceType type = AV_HWDEVICE_TYPE_NONE;
+       if( strcmp(_("none"), hw_dev) ) {
+               type = av_hwdevice_find_type_by_name(hw_dev);
+               if( type != AV_HWDEVICE_TYPE_VAAPI ) {
+                       fprintf(stderr, "currently, only vaapi hw encode is supported\n");
+                       type = AV_HWDEVICE_TYPE_NONE;
+               }
+       }
+       if( type != AV_HWDEVICE_TYPE_NONE ) {
+               int ret = av_hwdevice_ctx_create(&hw_device_ctx, AV_HWDEVICE_TYPE_VAAPI, 0, 0, 0);
+               if( ret < 0 ) {
+                       ff_err(ret, "Failed to create a HW device.\n");
+                       type = AV_HWDEVICE_TYPE_NONE;
+               }
+       }
+       if( type != AV_HWDEVICE_TYPE_NONE ) {
+               hw_frames_ref = av_hwframe_ctx_alloc(hw_device_ctx);
+               if( !hw_frames_ref ) {
+                       fprintf(stderr, "Failed to create HW frame context.\n");
+                       type = AV_HWDEVICE_TYPE_NONE;
+               }
+       }
+       if( type != AV_HWDEVICE_TYPE_NONE ) {
+               AVHWFramesContext *frames_ctx = (AVHWFramesContext *)(hw_frames_ref->data);
+               frames_ctx->format = AV_PIX_FMT_VAAPI;
+               frames_ctx->sw_format = AV_PIX_FMT_NV12;
+               frames_ctx->width = width;
+               frames_ctx->height = height;
+               frames_ctx->initial_pool_size = 0; // 200;
+               int ret = av_hwframe_ctx_init(hw_frames_ref);
+               if( ret >= 0 ) {
+                       avctx->hw_frames_ctx = av_buffer_ref(hw_frames_ref);
+                       if( !avctx->hw_frames_ctx ) ret = AVERROR(ENOMEM);
+               }
+               if( ret < 0 ) {
+                       ff_err(ret, "Failed to initialize HW frame context.\n");
+                       type = AV_HWDEVICE_TYPE_NONE;
+               }
+               av_buffer_unref(&hw_frames_ref);
+       }
+       return type;
+}
+
+int FFVideoStream::encode_hw_write(FFrame *picture)
+{
+       int ret = 0;
+       AVFrame *hw_frm = 0;
+       switch( avctx->pix_fmt ) {
+       case AV_PIX_FMT_VAAPI:
+               hw_frm = av_frame_alloc();
+               if( !hw_frm ) { ret = AVERROR(ENOMEM);  break; }
+               ret = av_hwframe_get_buffer(avctx->hw_frames_ctx, hw_frm, 0);
+               if( ret < 0 ) break;
+               ret = av_hwframe_transfer_data(hw_frm, *picture, 0);
+               if( ret < 0 ) break;
+               picture->set_hw_frame(hw_frm);
+               return 0;
+       default:
+               return 0;
+       }
+       av_frame_free(&hw_frm);
+       ff_err(ret, "Error while transferring frame data to GPU.\n");
+       return ret;
+}
+
 int FFVideoStream::decode_frame(AVFrame *frame)
 {
        int first_frame = seeked;  seeked = 0;
@@ -1103,7 +1182,14 @@ int FFVideoStream::video_seek(int64_t pos)
 
 int FFVideoStream::init_frame(AVFrame *picture)
 {
-       picture->format = avctx->pix_fmt;
+       switch( avctx->pix_fmt ) {
+       case AV_PIX_FMT_VAAPI:
+               picture->format = AV_PIX_FMT_NV12;
+               break;
+       default:
+               picture->format = avctx->pix_fmt;
+               break;
+       }
        picture->width  = avctx->width;
        picture->height = avctx->height;
        int ret = av_frame_get_buffer(picture, 32);
@@ -1121,6 +1207,8 @@ int FFVideoStream::encode(VFrame *vframe)
                frame->pts = curr_pos;
                ret = convert_pixfmt(vframe, frame);
        }
+       if( ret >= 0 && avctx->hw_frames_ctx )
+               encode_hw_write(picture);
        if( ret >= 0 ) {
                picture->queue(curr_pos);
                ++curr_pos;
@@ -2393,10 +2481,23 @@ int FFMPEG::open_encoder(const char *type, const char *spec)
                        vid->height = asset->height;
                        vid->frame_rate = asset->frame_rate;
 
-                       AVPixelFormat pix_fmt = av_get_pix_fmt(asset->ff_pixel_format);
+                       AVPixelFormat pix_fmt = AV_PIX_FMT_NONE;
+                       if( opt_hw_dev != 0 ) {
+                               AVHWDeviceType hw_type = vid->encode_hw_activate(opt_hw_dev);
+                               switch( hw_type ) {
+                               case AV_HWDEVICE_TYPE_VAAPI:
+                                       pix_fmt = AV_PIX_FMT_VAAPI;
+                                       break;
+                               case AV_HWDEVICE_TYPE_NONE:
+                               default:
+                                       pix_fmt = av_get_pix_fmt(asset->ff_pixel_format);
+                                       break;
+                               }
+                       }
                        if( pix_fmt == AV_PIX_FMT_NONE )
                                pix_fmt = codec->pix_fmts ? codec->pix_fmts[0] : AV_PIX_FMT_YUV420P;
                        ctx->pix_fmt = pix_fmt;
+
                        const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
                        int mask_w = (1<<desc->log2_chroma_w)-1;
                        ctx->width = (vid->width+mask_w) & ~mask_w;
index 15659944c9b3ef57ae599e2eac3527099b438db0..9bfd268adb7bd624f2473dfda6047ec467b44474 100644 (file)
@@ -68,6 +68,7 @@ public:
        int initted() { return init; }
        void queue(int64_t pos);
        void dequeue();
+       void set_hw_frame(AVFrame *frame);
 };
 
 class FFStream {
@@ -235,6 +236,8 @@ public:
        int decode_frame(AVFrame *frame);
        AVHWDeviceType decode_hw_activate();
        void decode_hw_format(AVCodec *decoder, AVHWDeviceType type);
+       AVHWDeviceType encode_hw_activate(const char *hw_dev);
+       int encode_hw_write(FFrame *picture);
        int encode_frame(AVFrame *frame);
        int create_filter(const char *filter_spec, AVCodecParameters *avpar);
        void load_markers();
diff --git a/cinelerra-5.1/ffmpeg/video/h264_vaapi.mp4 b/cinelerra-5.1/ffmpeg/video/h264_vaapi.mp4
new file mode 100644 (file)
index 0000000..085d70d
--- /dev/null
@@ -0,0 +1,3 @@
+mp4 h264_vaapi
+cin_hw_dev=vaapi
+profile=high
diff --git a/cinelerra-5.1/ffmpeg/video/hevc_vaapi.mp4 b/cinelerra-5.1/ffmpeg/video/hevc_vaapi.mp4
new file mode 100644 (file)
index 0000000..4e57f2b
--- /dev/null
@@ -0,0 +1,2 @@
+mp4 hevc_vaapi
+cin_hw_dev=vaapi
diff --git a/cinelerra-5.1/ffmpeg/video/mjpeg_vaapi.mp4 b/cinelerra-5.1/ffmpeg/video/mjpeg_vaapi.mp4
new file mode 100644 (file)
index 0000000..14a00d8
--- /dev/null
@@ -0,0 +1,2 @@
+mp4 mjpeg_vaapi
+cin_hw_dev=vaapi
diff --git a/cinelerra-5.1/ffmpeg/video/mpeg2_vaapi.mp4 b/cinelerra-5.1/ffmpeg/video/mpeg2_vaapi.mp4
new file mode 100644 (file)
index 0000000..f13cbb0
--- /dev/null
@@ -0,0 +1,2 @@
+mp4 mpeg2_vaapi
+cin_hw_dev=vaapi
index 251389cd3240a5782c8330528a86acb506e6b883..0cf4c8fe31d4221e658143c46bd0b8990d931a16 100644 (file)
@@ -367,10 +367,16 @@ void TitleWindow::create_objects()
        stroker->create_objects();
        x += stroker->get_w() + margin;
 #endif
-       y += outline_title->get_h() + margin;
-       add_tool(timecode = new TitleTimecode(client, this, x1=x, y));
-       x += timecode->get_w() + margin;
-       add_tool(timecode_format = new TitleTimecodeFormat(client, this, x, y,
+       add_tool(timecode = new TitleTimecode(client, this, x, y));
+       y += timecode->get_h() + margin;
+       int tw = 0;
+       for( int i=0; i<lengthof(timeunit_formats); ++i ) {
+               char text[BCSTRLEN];
+               Units::print_time_format(timeunit_formats[i], text);
+               int w = get_text_width(MEDIUMFONT, text);
+               if( tw < w ) tw = w;
+       }
+       add_tool(timecode_format = new TitleTimecodeFormat(client, this, x, y, tw,
                Units::print_time_format(client->config.timecode_format, string)));
        timecode_format->create_objects();
        y += timecode_format->get_h() + margin;
@@ -806,7 +812,9 @@ void TitleOutlineColorButton::handle_done_event(int result)
 {
        if( result ) {
                handle_new_color(orig_color, orig_alpha);
+               window->lock_window("TitleColorButton::handle_done_event");
                update_gui(orig_color);
+               window->unlock_window();
        }
 }
 
@@ -852,8 +860,8 @@ int TitleTimecode::handle_event()
 }
 
 TitleTimecodeFormat::TitleTimecodeFormat(TitleMain *client, TitleWindow *window,
-               int x, int y, const char *text)
- : BC_PopupMenu(x, y, 100, text, 1)
+               int x, int y, int tw, const char *text)
+ : BC_PopupMenu(x, y, BC_PopupMenu::calculate_w(tw)+10, text, 1)
 {
        this->client = client;
        this->window = window;
index 10ca4724cc6336a7a3f684ea83fcd2fbd86b094b..43145ebf21078652ee3cfd1b416d7c8e6ee50c01 100644 (file)
@@ -332,7 +332,8 @@ public:
 class TitleTimecodeFormat : public BC_PopupMenu
 {
 public:
-       TitleTimecodeFormat(TitleMain *client, TitleWindow *window, int x, int y, const char *text);
+       TitleTimecodeFormat(TitleMain *client, TitleWindow *window,
+               int x, int y, int tw, const char *text);
        void create_objects();
        int update(int timecode_format);
        int handle_event();