Skip to content

Commit

Permalink
Check if window size changed and resize it (#1037)
Browse files Browse the repository at this point in the history
* Check if window size changed and resize it

* Change bool to int (?)

* Code samples
  • Loading branch information
jonata authored Oct 10, 2024
1 parent 7acb1f1 commit d688641
Show file tree
Hide file tree
Showing 4 changed files with 448 additions and 7 deletions.
26 changes: 19 additions & 7 deletions src/modules/sdl2/consumer_sdl2.c
Original file line number Diff line number Diff line change
Expand Up @@ -573,6 +573,7 @@ static int consumer_play_video(consumer_sdl self, mlt_frame frame)
int video_off = mlt_properties_get_int(properties, "video_off");
int preview_off = mlt_properties_get_int(properties, "preview_off");
int display_off = video_off | preview_off;
uintptr_t window_id = mlt_properties_get_int(self->properties, "window_id");

if (self->running && !display_off) {
if (!self->sdl_window) {
Expand All @@ -585,13 +586,24 @@ static int consumer_play_video(consumer_sdl self, mlt_frame frame)
mlt_frame_get_image(frame, &image, &vfmt, &width, &height, 0);

if (self->running) {
// Determine window's new display aspect ratio
int x = mlt_properties_get_int(properties, "window_width");
if (x && x != self->window_width)
self->window_width = x;
x = mlt_properties_get_int(properties, "window_height");
if (x && x != self->window_height)
self->window_height = x;
// Determine window's new display aspect ratio, and resize if it's an existing window
int w = mlt_properties_get_int(properties, "window_width");
int h = mlt_properties_get_int(properties, "window_height");
int width_changed = (w && w != self->window_width);
int height_changed = (h && h != self->window_height);

if (width_changed || height_changed) {
if (width_changed) {
self->window_width = w;
}
if (height_changed) {
self->window_height = h;
}
if (window_id) {
SDL_SetWindowSize(self->sdl_window, self->window_width, self->window_height);
}
}

double this_aspect = (double) self->window_width / self->window_height;

// Get the display aspect ratio
Expand Down
142 changes: 142 additions & 0 deletions src/swig/python/play_gtk.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
import gi
import sys
import mlt7 as mlt

gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, Gdk, GObject, GLib

VIDEO = 'video.mp4'

class VideoPlayer(Gtk.Window):
def __init__(self):
super().__init__(title="MLT Video Player")
self.set_default_size(800, 600)
self.connect("destroy", self.on_destroy)

# Initialize the mlt system
mlt.Factory().init()

# Create a default profile
self.profile = mlt.Profile()

# Create a producer for the video
self.producer = mlt.Producer(self.profile, VIDEO)
if self.producer.is_valid():
self.profile.from_producer(self.producer)
self.producer = mlt.Producer(self.profile, VIDEO)

# Create the consumer for rendering using SDL2
self.consumer = mlt.Consumer(self.profile, "sdl2")

# GTK Layout
self.layout = Gtk.VBox(spacing=6)
self.add(self.layout)

# Create the drawing area for the video
self.drawing_area = Gtk.DrawingArea()
self.drawing_area.set_size_request(800, 450)
self.drawing_area.connect("size-allocate",self.drawing_area_resized)
self.layout.pack_start(self.drawing_area, True, True, 0)
self.drawing_area.realize()
print(int(self.drawing_area.get_window().get_xid()))
self.consumer.set('window_id', str(self.drawing_area.get_window().get_xid()))

if not self.consumer.is_valid():
print("Failed to open the sdl2 consumer")
sys.exit(1)

# Create a multitrack playlist and set it to the tractor
self.playlist = mlt.Playlist(self.profile)
self.playlist.append(self.producer)

self.tractor = mlt.Tractor()
self.tractor.set_track(self.playlist, 0)

# Connect the producer to the consumer
self.consumer.connect(self.tractor)

# Control Buttons
controls_box = Gtk.HBox(spacing=6)
self.layout.pack_start(controls_box, False, False, 0)

# Play button
self.play_button = Gtk.Button.new_with_label("Play")
self.play_button.connect("clicked", self.play_video)
controls_box.pack_start(self.play_button, False, False, 0)

# Pause button
self.pause_button = Gtk.Button.new_with_label("Pause")
self.pause_button.connect("clicked", self.pause_video)
controls_box.pack_start(self.pause_button, False, False, 0)

# Stop button
self.stop_button = Gtk.Button.new_with_label("Stop")
self.stop_button.connect("clicked", self.stop_video)
controls_box.pack_start(self.stop_button, False, False, 0)

# Slider
self.timeline_slider = Gtk.Scale.new_with_range(Gtk.Orientation.HORIZONTAL, 0, 1000, 1)
self.timeline_slider.set_draw_value(False)
self.slider_handler_id = self.timeline_slider.connect("value-changed", self.on_slider_changed)
self.timeline_slider.connect("button-release-event", self.on_slider_button_release)
controls_box.pack_start(self.timeline_slider, True, True, 0)

# Timer to update the slider
self.update_timer = GLib.timeout_add(1000 // 24, self.update_slider)

# Start the consumer
self.consumer.start()
self.pause_video()

def drawing_area_resized(self, widget, _):
self.consumer.set('window_width', widget.get_allocated_width())
self.consumer.set('window_height', widget.get_allocated_height())

def update_slider(self):
position = self.consumer.position()
playtime = self.tractor.get_playtime()
if playtime > 0:
value = int((position / playtime) * 1000)
self.timeline_slider.handler_block(self.slider_handler_id)
self.timeline_slider.set_value(value)
self.timeline_slider.handler_unblock(self.slider_handler_id)
return True

def play_video(self, button):
self.tractor.set_speed(1)
self.consumer.set('volume', 1)

def pause_video(self, button=None):
if not self.consumer.is_stopped():
self.tractor.set_speed(0)
self.consumer.set('volume', 0)

def stop_video(self, button):
self.tractor.seek(0)
self.tractor.set_speed(0)
self.timeline_slider.set_value(0)

def on_slider_changed(self, slider):
value = slider.get_value()
self.consumer.set('volume', 0)
playtime = self.tractor.get_playtime()
self.tractor.seek(int((value / 1000.0) * playtime))

def on_slider_button_release(self, slider, _):
if not self.tractor.get_speed() == 0:
self.consumer.set('volume', 1)

def on_destroy(self, widget):
self.consumer.stop()
mlt.Factory().close()
Gtk.main_quit()

if __name__ == "__main__":
# Initialize GTK
GObject.threads_init()
Gtk.init(sys.argv)

# Create and run the video player
player = VideoPlayer()
player.show_all()
Gtk.main()
143 changes: 143 additions & 0 deletions src/swig/python/play_pyqt6.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
import mlt7 as mlt
import sys

from PyQt6.QtWidgets import QApplication, QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QSlider, QStyle
from PyQt6.QtCore import Qt, QTimer

VIDEO = 'video.mp4'


class VideoPlayer(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("MLT Video Player")

layout = QVBoxLayout()

class video_viewer(QWidget):
"""The main window (QWidget) class"""
def __init__(self):
super().__init__()
self.setMinimumSize(380, 260)

def resizeEvent(self, event):
self.window().consumer.set('window_width', self.width())
self.window().consumer.set('window_height', self.height())
event.accept()

self.video_viewer = video_viewer()
layout.addWidget(self.video_viewer, 1)

buttons_layout = QHBoxLayout()

self.play_button = QPushButton()
self.play_button.setFlat(True)
self.play_button.setIcon(self.style().standardIcon(QStyle.StandardPixmap.SP_MediaPlay))
self.play_button.clicked.connect(self.play_video)
buttons_layout.addWidget(self.play_button)

self.pause_button = QPushButton()
self.pause_button.setFlat(True)
self.pause_button.setIcon(self.style().standardIcon(QStyle.StandardPixmap.SP_MediaPause))
self.pause_button.clicked.connect(self.pause_video)
buttons_layout.addWidget(self.pause_button)

self.stop_button = QPushButton()
self.stop_button.setFlat(True)
self.stop_button.setIcon(self.style().standardIcon(QStyle.StandardPixmap.SP_MediaStop))
self.stop_button.clicked.connect(self.stop_video)
buttons_layout.addWidget(self.stop_button)

self.timeline_slider = QSlider(Qt.Orientation.Horizontal)
self.timeline_slider.setRange(0, 1000)
self.timeline_slider.sliderPressed.connect(self.stop_update_slider)
self.timeline_slider.sliderMoved.connect(self.timeline_slider_changed)
self.timeline_slider.sliderReleased.connect(self.set_volume_back_to_normal)
buttons_layout.addWidget(self.timeline_slider)

layout.addLayout(buttons_layout)

self.setLayout(layout)

self.timer = QTimer(self)
self.timer.timeout.connect(self.update_slider)

# Start the mlt system
mlt.Factory().init()

# Establish a default (usually "dv_pal") profile
self.profile = mlt.Profile()

# Create the producer
self.producer = mlt.Producer(self.profile, VIDEO)

if self.producer.is_valid():
# Derive a profile based on the producer
self.profile.from_producer(self.producer)
# Reload the producer using the derived profile
self.producer = mlt.Producer(self.profile, VIDEO)

# Create the consumer
self.consumer = mlt.Consumer(self.profile, "sdl2")
self.consumer.set('window_id', str(int(self.video_viewer.winId()))) # PyQt6 requires str or int for set('window_id')

if not self.consumer.is_valid():
print("Failed to open the sdl2 consumer")
sys.exit(1)

# Setup a multitrack
self.playlist = mlt.Playlist(self.profile)
self.playlist.append(self.producer)

self.tractor = mlt.Tractor()
self.tractor.set_track(self.playlist, 0)

# Connect the producer to the consumer
self.consumer.connect(self.tractor)

# Start the consumer
self.consumer.start()
self.pause_video()

def update_slider(self):
self.timeline_slider.setValue(int((self.consumer.position() / self.tractor.get_playtime()) * 1000))

def play_video(self):
self.tractor.set_speed(1)
self.consumer.set('volume', 1)
self.timer.start(int(1000 / 24))

def pause_video(self):
if not self.consumer.is_stopped():
self.tractor.set_speed(0)
self.consumer.set('volume', 0)

def stop_video(self):
self.tractor.seek(0)
self.tractor.set_speed(0)
self.timeline_slider.setValue(0)
self.timer.stop()

def timeline_slider_changed(self, value):
self.consumer.set('volume', 0)
self.tractor.seek(int((value / 1000.0) * self.tractor.get_playtime()))

def stop_update_slider(self):
self.timer.stop()

def set_volume_back_to_normal(self):
if not self.tractor.get_speed() == 0:
self.consumer.set('volume', 1)
self.timer.start(int(1000 / 24))

def closeEvent(self, event):
self.consumer.stop()
event.accept()

if __name__ == "__main__":
app = QApplication(sys.argv)

player = VideoPlayer()
player.show()

sys.exit(app.exec())
Loading

0 comments on commit d688641

Please sign in to comment.