gpt4 book ai didi

c++ - ffplay 不能播放超过一首歌曲

转载 作者:行者123 更新时间:2023-12-04 23:13:11 24 4
gpt4 key购买 nike

我从 http://ffmpeg.org/doxygen/trunk/ffplay_8c-source.html 获取了 ffplay.c 文件并将其重新编辑为 cpp 文件以嵌入到我的 win32 gui 应用程序中。我对其进行了以下更改。

  • 将 int main 函数变为本地函数如下,我可以通过 HWND 嵌入播放器
  • void Ffplay::play_song(string file, HWND parent, bool* successfull)
    {
    int flags;
    VideoState* is;
    input_filename = file;
    /* register all codecs, demux and protocols */
    #if CONFIG_AVDEVICE
    avdevice_register_all();
    #endif
    //avformat_network_init();
    //check whether the filename is valid
    if (input_filename.empty())
    {
    logger.log(logger.LEVEL_ERROR, "filename %s is not valid\n", file);
    return;
    }
    if (display_disable)
    {
    video_disable = 1;
    }
    flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER;
    if (audio_disable)
    flags &= ~SDL_INIT_AUDIO;
    else
    {
    /* Try to work around an occasional ALSA buffer underflow issue when the
    * period size is NPOT due to ALSA resampling by forcing the buffer size. */
    if (!SDL_getenv("SDL_AUDIO_ALSA_SET_BUFFER_SIZE"))
    SDL_setenv("SDL_AUDIO_ALSA_SET_BUFFER_SIZE", "1", 1);
    }
    if (display_disable)
    flags &= ~SDL_INIT_VIDEO;
    SDL_SetMainReady();
    if (SDL_Init(flags))
    {
    logger.log(logger.LEVEL_ERROR, "Could not initialize SDL - %s\n", SDL_GetError());
    logger.log(logger.LEVEL_ERROR, "(Did you set the DISPLAY variable?)\n");
    return;
    }
    //Initialize optional fields of a packet with default values.
    //Note, this does not touch the data and size members, which have to be initialized separately.
    av_init_packet(&flush_pkt);
    flush_pkt.data = (uint8_t*)&flush_pkt;

    if (!display_disable)
    {
    int flags = SDL_WINDOW_HIDDEN;
    if (alwaysontop)
    #if SDL_VERSION_ATLEAST(2,0,5)
    flags |= SDL_WINDOW_ALWAYS_ON_TOP;
    #else
    logger.log(logger.LEVEL_INFO, "SDL version doesn't support SDL_WINDOW_ALWAYS_ON_TOP. Feature will be inactive.\n");
    #endif
    if (borderless)
    flags |= SDL_WINDOW_BORDERLESS;
    else
    flags |= SDL_WINDOW_RESIZABLE;
    SDL_InitSubSystem(flags);
    ShowWindow(parent, true);
    //window = SDL_CreateWindow(program_name, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, default_width, default_height, flags);
    window = SDL_CreateWindowFrom(parent);
    SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
    if (window) {
    renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
    if (!renderer)
    {
    logger.log(logger.LEVEL_ERROR, "Failed to initialize a hardware accelerated renderer: %s\n", SDL_GetError());
    renderer = SDL_CreateRenderer(window, -1, 0);
    }
    if (renderer)
    {
    if (!SDL_GetRendererInfo(renderer, &renderer_info))
    {
    logger.log(logger.LEVEL_INFO, "Initialized %s renderer.\n", renderer_info.name);
    }
    }
    }
    if (!window || !renderer || !renderer_info.num_texture_formats)
    {
    logger.log(logger.LEVEL_ERROR, "Failed to create window or renderer: %s\n", SDL_GetError());
    return;
    }
    }

    is = stream_open(input_filename.c_str(), file_iformat);
    if (!is)
    {
    logger.log(logger.LEVEL_ERROR, "Failed to initialize VideoState!\n");
    return;
    }
    //the song is playing now
    *successfull = true;
    event_loop(is);
    //the song has quit;
    *successfull = false;
    }
  • 更改了回调函数,因为 c++ 不能使用静态函数,例如
  • void Ffplay::static_sdl_audio_callback(void* opaque, Uint8* stream, int len)
    {
    static_cast<Ffplay*>(opaque)->sdl_audio_callback(opaque, stream, len);
    }

    关闭不会从主文件更改为关闭音频和 sdl 框架
    void Ffplay::do_exit(VideoState* is)
    {
    abort = true;
    if(is)
    {
    stream_close(is);
    }
    if (renderer)
    SDL_DestroyRenderer(renderer);
    if (window)
    SDL_DestroyWindow(window);
    #if CONFIG_AVFILTER
    av_freep(&vfilters_list);
    #endif
    avformat_network_deinit();
    SDL_Quit();

    }

    我从主 gui 调用函数如下
    ft=std::async(launch::async, &Menu::play_song, this, songs_to_play.at(0));
    menu::play_song功能是:
    void Menu::play_song(wstring song_path)
    {
    ready_to_play_song = false;
    OutputDebugString(L"\nbefore song\n");
    using std::future;
    using std::async;
    using std::launch;

    string input{ song_path.begin(),song_path.end() };
    Ffplay ffplay;
    ffplay.play_song(input, h_sdl_window, &song_opened);

    OutputDebugString(L"\nafter song\n");
    ready_to_play_song = true;
    }

    问题是我只能播放一首歌。如果我调用 menu::play_song再次运行声音丢失,视频/艺术封面有时也丢失。似乎有些资源没有被释放或类似的东西。

    我已将问题本地化到此功能
    int Ffplay::packet_queue_get(PacketQueue* q, AVPacket* pkt, int block, int* serial)
    {

    MyAVPacketList* pkt1;
    int ret;
    int count=0;
    SDL_LockMutex(q->mutex);

    for (;;)
    {


    if (q->abort_request)
    {
    ret = -1;
    break;
    }

    pkt1 = q->first_pkt;
    if (pkt1) {
    q->first_pkt = pkt1->next;
    if (!q->first_pkt)
    q->last_pkt = NULL;
    q->nb_packets--;
    q->size -= pkt1->pkt.size + sizeof(*pkt1);
    q->duration -= pkt1->pkt.duration;
    *pkt = pkt1->pkt;
    if (serial)
    *serial = pkt1->serial;
    av_free(pkt1);
    ret = 1;
    break;
    }
    else if (!block) {
    ret = 0;
    break;
    }
    else
    {
    logger.log(logger.LEVEL_INFO, "packet_queue before");
    SDL_CondWait(q->cond, q->mutex);
    logger.log(logger.LEVEL_INFO, "packet_queue after");

    }
    }
    SDL_UnlockMutex(q->mutex);
    return ret;
    }

    调用 SDL_CondWait(q->cond, q->mutex);永远不会回来

    最佳答案

    首先,抱歉这个问题有点含糊,因为我无法上传很多代码,因为它很长,这就是为什么我将链接发布到与我的相似的原始链接,唯一的区别是我已经从 C 静态更改了函数那些到 C++ 公共(public)的。

    问题是变量 SDL_AudioDeviceID audio_dev
    使用分配变量audio_dev = SDL_OpenAudioDevice(NULL, 0, &wanted_spec, &spec, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE | SDL_AUDIO_ALLOW_CHANNELS_CHANGE)没有按计划分配变量,在使用 SDL_CloseAudioDevice(audio_dev); 关闭音频设备时音频设备变量为 0,因此设备未关闭,因此第二首歌曲缺少声音或视频可能挂起。
    这是使用各种线程调用本地回调函数的结果,这些函数按照 SDL api 的预期被强制转换为静态性质。

    答案是将设备变量更改为静态变量 static SDL_AudioDeviceID audio_dev;因此可以从程序中的任何位置访问该变量

    关于c++ - ffplay 不能播放超过一首歌曲,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60018856/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com