我有解复用器线程:
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;
}
PauseDemuxer函数的代码为:
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;
}
启动和停止音频是SDL_PauseAudioDevice的实现,其中pause_on为0或1。
这样,一切正常。