视频播放不能在检测触摸点的时候正确切换视频

Viewed 137

重现步骤

期待结果和实际结果


我希望可以在检测到触摸后自动播放我指定的1_1视频,同时在未检测到触摸的时候循环播放上一个视频


软硬件版本信息

错误日志


icroPython v1.1 on 2024-09-15; k230_canmv_01studio with K230
加载并播放 /sdcard/examples/utils/1_1.mp4
codec_id: 0
track_id: 1
width: 800
height: 480
audio not support codecid: 0
video track h264
buffer pool : 5
input_pool_id:5,input_pool_size:1044480,input_pool_cnt:4
output_pool_id:6,output_pool_size:3133440,output_pool_cnt:6
视频开始播放
检测到触摸事件:(track_id: 3, event: 0, width: 48, x: 577, y: 198, timestamp: 0,)
点0: X=577 Y=198

检测到触摸,切换视频到 /sdcard/examples/2_2.mp4
视频播放结束
destory_pool input 5
destory_pool output 6
触摸切换时释放资源成功
加载并播放 /sdcard/examples/2_2.mp4
codec_id: 0
track_id: 1
width: 800
height: 480
audio not support codecid: 0
video track h264
buffer pool : 3
播放失败: MediaManager, vb config failed(-1610317806)
准备重新播放当前视频...
加载并播放 /sdcard/examples/2_2.mp4
实际上2-2并没有被播放
````****`



3 Answers
from media.player import Player, Display, K_PLAYER_EVENT_EOF
from machine import TOUCH
import time
import gc

# 初始化状态变量
start_play = False
current_video = "/sdcard/examples/utils/1_1.mp4"
video_player = None

def player_event(event, data):
    global start_play
    if event == K_PLAYER_EVENT_EOF:
        print("视频播放结束")
        start_play = False

def play_mp4_test(filename):
    global start_play, video_player
    try:
        # 清理之前的播放器实例
        if video_player is not None:
            try:
                video_player.stop()
                del video_player
                gc.collect()
                print("已释放旧播放器资源")
            except Exception as e:
                print(f"资源释放异常: {e}")
            finally:
                video_player = None

        print(f"加载并播放 {filename}")
        
        # 选择适合的显示输出方式
        # player = Player(Display.VIRT)  # 虚拟显示
        player = Player(Display.ST7701)  # 实际硬件显示
        
        player.load(filename)
        player.set_event_callback(player_event)
        player.start()
        start_play = True
        print("视频开始播放")
        return player
    except Exception as e:
        print(f"播放失败: {e}")
        return None

# 初始化触摸设备
tp = TOUCH(0)

def check_touch():
    """检测触摸事件并返回坐标"""
    p = tp.read()
    if p:
        print(f"检测到触摸事件:{p}")
        # 打印前5个触摸点(如果有)
        for i in range(min(5, len(p))):
            print(f'点{i}: X={p[i].x:<4} Y={p[i].y}')
        return True
    return False

if __name__ == "__main__":
    # 初始播放
    video_player = play_mp4_test(current_video)

    while True:
        try:
            # 检测触摸事件
            if check_touch():
                # 切换视频逻辑
                new_video = "/sdcard/examples/2_2.mp4" if current_video.endswith("1_1.mp4") else "/sdcard/examples/utils/1_1.mp4"
                
                print(f"\n检测到触摸,切换视频到 {new_video}")
                current_video = new_video
                
                # 主动触发资源释放
                if video_player is not None:
                    try:
                        video_player.stop()
                        del video_player
                        gc.collect()
                        print("触摸切换时释放资源成功")
                    except Exception as e:
                        print(f"触摸切换释放失败: {e}")
                    finally:
                        video_player = None
                
                # 创建新播放器实例
                video_player = play_mp4_test(current_video)

            # 自动重播逻辑
            if not start_play and video_player is None:
                print("准备重新播放当前视频...")
                video_player = play_mp4_test(current_video)

            time.sleep(0.1)  # 降低CPU占用

        except KeyboardInterrupt:
            print("程序终止")
            break
        except Exception as e:
            print(f"主循环异常: {e}")
            time.sleep(1)  # 防止错误循环

    # 程序退出前清理
    if video_player is not None:
        try:
            video_player.stop()
            del video_player
            gc.collect()
        except:
            pass

github下载新版本PreRelease固件,先使用CanMV/sdcard/examples/01-Media/mp4muxer录制两个mp4文件,然后再使用如下代码实现触屏轮换播放:

# MP4 Demuxer Example
#
# This script demuxes an MP4 file, extracting video and audio streams.
# Supported video codecs: H.264, H.265
# Supported audio codecs: G.711A, G.711U

from media.media import *
from mpp.mp4_format import *
from mpp.mp4_format_struct import *
from media.pyaudio import *
import media.g711 as g711
from mpp.payload_struct import *
import media.vdecoder as vdecoder
from media.display import *
import uctypes
import time
import _thread
import os
from media.display import *
from machine import TOUCH

# 初始化状态变量
cur_state=1
current_video = "/sdcard/examples/test_1.mp4"

def demuxer_mp4(filename,vdec):
    mp4_cfg = k_mp4_config_s()
    video_info = k_mp4_video_info_s()
    video_track = False
    audio_info = k_mp4_audio_info_s()
    audio_track = False
    mp4_handle = k_u64_ptr()

    mp4_cfg.config_type = K_MP4_CONFIG_DEMUXER
    mp4_cfg.muxer_config.file_name[:] = bytes(filename, 'utf-8')
    mp4_cfg.muxer_config.fmp4_flag = 0

    ret = kd_mp4_create(mp4_handle, mp4_cfg)
    if ret:
        raise OSError("kd_mp4_create failed:",filename)

    file_info = k_mp4_file_info_s()
    kd_mp4_get_file_info(mp4_handle.value, file_info)
    #print("=====file_info: track_num:",file_info.track_num,"duration:",file_info.duration)

    for i in range(file_info.track_num):
        track_info = k_mp4_track_info_s()
        ret = kd_mp4_get_track_by_index(mp4_handle.value, i, track_info)
        if (ret < 0):
            raise ValueError("kd_mp4_get_track_by_index failed")

        if (track_info.track_type == K_MP4_STREAM_VIDEO):
            if (track_info.video_info.codec_id == K_MP4_CODEC_ID_H264 or track_info.video_info.codec_id == K_MP4_CODEC_ID_H265):
                video_track = True
                video_info = track_info.video_info
                print("    codec_id: ", video_info.codec_id)
                print("    track_id: ", video_info.track_id)
                print("    width: ", video_info.width)
                print("    height: ", video_info.height)
            else:
                print("video not support codecid:",track_info.video_info.codec_id)
        elif (track_info.track_type == K_MP4_STREAM_AUDIO):
            if (track_info.audio_info.codec_id == K_MP4_CODEC_ID_G711A or track_info.audio_info.codec_id == K_MP4_CODEC_ID_G711U):
                audio_track = True
                audio_info = track_info.audio_info
                print("    codec_id: ", audio_info.codec_id)
                print("    track_id: ", audio_info.track_id)
                print("    channels: ", audio_info.channels)
                print("    sample_rate: ", audio_info.sample_rate)
                print("    bit_per_sample: ", audio_info.bit_per_sample)
                #audio_info.channels = 2
            else:
                print("audio not support codecid:",track_info.audio_info.codec_id)

    if (video_track == False):
        raise ValueError("video track not found")

    # 记录初始系统时间
    start_system_time = time.ticks_ms()
    # 记录初始视频时间戳
    start_video_timestamp = 0

    while (True):
        frame_data =  k_mp4_frame_data_s()
        ret = kd_mp4_get_frame(mp4_handle.value, frame_data)
        if (ret < 0):
            raise OSError("get frame data failed")

        if (frame_data.eof):
            break

        if (frame_data.codec_id == K_MP4_CODEC_ID_H264 or frame_data.codec_id == K_MP4_CODEC_ID_H265):
            data = uctypes.bytes_at(frame_data.data,frame_data.data_length)
            vdec.decode(data)
            # 计算视频时间戳经历的时长
            video_timestamp_elapsed = frame_data.time_stamp - start_video_timestamp
            # 计算系统时间戳经历的时长
            current_system_time = time.ticks_ms()
            system_time_elapsed = current_system_time - start_system_time

            # 如果系统时间戳经历的时长小于视频时间戳经历的时长,进行延时
            if system_time_elapsed < video_timestamp_elapsed:
                time.sleep_ms(video_timestamp_elapsed - system_time_elapsed)

        elif(frame_data.codec_id == K_MP4_CODEC_ID_G711A or frame_data.codec_id == K_MP4_CODEC_ID_G711U):
            data = uctypes.bytes_at(frame_data.data,frame_data.data_length)
            print("audio frame_data.codec_id:",frame_data.codec_id,"data_length:",frame_data.data_length,"timestamp:",frame_data.time_stamp)

    kd_mp4_destroy(mp4_handle.value)

# 初始化触摸设备
tp = TOUCH(0)

def check_touch():
    """检测触摸事件并返回坐标"""
    p = tp.read()
    if p:
        print(f"检测到触摸事件:{p}")
        # 打印前5个触摸点(如果有)
        for i in range(min(5, len(p))):
            print(f'点{i}: X={p[i].x:<4} Y={p[i].y}')
        return True
    return False

if __name__ == "__main__":
    os.exitpoint(os.EXITPOINT_ENABLE)
    Display.init(Display.ST7701,to_ide=True)
    vdec = vdecoder.Decoder(K_PT_H264)
    MediaManager.init()
    vdec.create()
    bind_info = vdec.bind_info(width=ALIGN_UP(800, 16),height=480,chn=vdec.get_vdec_channel())
    Display.bind_layer(**bind_info, layer = Display.LAYER_VIDEO1)
    vdec.start()
    # 初始播放
    demuxer_mp4("/sdcard/examples/test_1.mp4",vdec)
    while True:
        try:
            # 检测触摸事件
            if check_touch():
                # 切换视频逻辑
                if cur_state==1:
                    demuxer_mp4("/sdcard/examples/test_2.mp4",vdec)
                    cur_state=2
                elif cur_state==2:
                    demuxer_mp4("/sdcard/examples/test_1.mp4",vdec)
                    cur_state=1
            time.sleep_ms(100)  # 降低CPU占用
        except Exception as e:
            print(e)
            break
    vdec.stop()
    # 销毁video decoder
    vdec.destroy()
    time.sleep(1)
    Display.deinit()
    time.sleep_ms(50)
    MediaManager.deinit()

您好,请更新到最新代码后再使用您的demo进行测试。之前的问题是由于MediaManager.deinit调用后未完全释放vb资源导致,目前此问题已修复。