Av_read_pause和av_read_play挂了一根线

Av_read_pause and av_read_play hangs a thread

本文关键字:read 一根 pause av play Av      更新时间:2023-10-16

I have demuxer thread:

int SdlPlayer::Demuxer(void* opaque){
MainContext* main_context = static_cast<MainContext*>(opaque);
int video_stream_index = main_context->video_context_->stream_index_;
int audio_stream_index = main_context->audio_context_->stream_index_;
AVPacket packet;
while (!main_context->quit_){
    av_init_packet(&packet);
    if (main_context->is_paused_ != main_context->is_last_paused_) {
        main_context->is_last_paused_ = main_context->is_paused_;
        if (main_context->is_paused_){
            main_context->read_pause_return = av_read_pause(main_context->input_format_context);
        }
        else{
            av_read_play(main_context->input_format_context);
        }
    }
    if (main_context->is_paused_
        && (!strcmp(main_context->input_format_context->iformat->name, "rtsp")
        || (main_context->input_format_context->pb && !strncmp(main_context->path_.c_str(), "mmsh:", 5)))) {
        /* wait 10 ms to avoid trying to get another packet */
        /* XXX: horrible */
        SDL_Delay(10);
        continue;
    }
    if (av_read_frame((main_context->input_format_context), &packet) < 0) {
        main_context->OnFileEnd();
        av_free_packet(&packet);
        break;  // Eof or error
    }
    if (packet.stream_index == video_stream_index){
        main_context->video_context_->packet_queue_->Push(&packet);
    }
    else{
        if (packet.stream_index == audio_stream_index && main_context->audio_context_->has_audio_){
            main_context->audio_context_->packet_queue_->Push(&packet);
        }
    }
}
main_context->video_context_->packet_queue_->Eof();
if (main_context->audio_context_->has_audio_){
    main_context->audio_context_->packet_queue_->Eof();
}
return 0;}

我有改变的功能

main_context_->is_paused_ = 1;

或到

main_context_->is_paused_ = 0;

因此,当我暂停或取消暂停流时,函数av_read_play和av_read_pause经常挂在 ffmpeg 库中的某个地方。我找到了一个在 ffplay 中使用暂停的代码,并使用他们的示例,但它仍然挂起。我的代码或库中可能存在一些错误?

我更新了解复用器并将功能从解复用器中暂停移出:

int CFFmpegPlayer::Demuxer(void* opaque)
{
    CFFmpegPlayer* player = static_cast<CFFmpegPlayer*>(opaque);
    int video_stream_index = player->video_context_->stream_index_;
    int audio_stream_index = player->audio_context_->stream_index_;
    AVPacket* packet;
    while (!player->quit_){
        if (player->PauseDemuxer() == 1)
            continue;
        player->timeout_ = 1000;
        player->current_time_ = GetTickCount();
        player->enable_interrupt_callback_ = 1;
        packet = av_packet_alloc();
        int ret = av_read_frame((player->input_format_context_), packet);
        if (ret < 0) {
            player->enable_interrupt_callback_ = 0;
            if (ret == (int)AVERROR_EOF){
                break;  // Eof or error
            }
            player->WriteLogMessage("Error av_read_frame in demuxer");
            break;
        }
        player->enable_interrupt_callback_ = 0;
        if (packet->stream_index == video_stream_index){
            player->CalculateBitrate(packet);
            if (player->video_context_->packet_queue_->Push(packet) < 0){
                break;
            }
        }
        else{
            if (packet->stream_index == audio_stream_index &&     player->audio_context_->has_audio_){
                if (player->audio_context_->packet_queue_->Push(packet) < 0){
                break;
                }
            }
        }
        SafeReleasePacket(&packet);
    }
    SafeReleasePacket(&packet);
    player->video_context_->packet_queue_->Eof();
    if (player->audio_context_->has_audio_){
        player->audio_context_->packet_queue_->Eof();
        player->audio_context_->audio_frame_buffer_->Eof();
    }
    return 0;
}

暂停解复用器函数的代码是:

int CFFmpegPlayer::PauseDemuxer()
{
    if (is_paused_ != is_last_paused_) {
        is_last_paused_ = is_paused_;
        if (is_paused_){
            read_pause_return_ = av_read_pause(input_format_context_);
            StopAudio();
        }
        else{
            av_read_play(input_format_context_);
            StartAudio();
        }
    }
    if (is_paused_  && !strcmp(input_format_context_->iformat->name, "rtsp")) {
        /* wait 10 ms to avoid trying to get another packet */
        /* XXX: horrible */
        SDL_Delay(10);
        return 1;
    }
    return 0;
}

开始和停止音频是pause_on 0 或 1 的SDL_PauseAudioDevice实现的。

这样一切都很好。