From 908ff306293391a15b45ceab80867c3990d09b3e Mon Sep 17 00:00:00 2001 From: martii Date: Thu, 10 Apr 2014 23:35:38 +0200 Subject: [PATCH] libeplayer3: work around duplicate ffmpeg stream ids by comparing stream addresses instead of pids (plus a couple of optimizations) --- libeplayer3/input.cpp | 18 ++-- libeplayer3/output.cpp | 2 + libeplayer3/player.cpp | 6 +- libeplayer3/writer/divx.cpp | 11 +-- libeplayer3/writer/misc.cpp | 18 ++-- libspark/playback_libeplayer3.cpp | 156 +++++++++++------------------- 6 files changed, 83 insertions(+), 128 deletions(-) diff --git a/libeplayer3/input.cpp b/libeplayer3/input.cpp index 2844dc8..988ab37 100644 --- a/libeplayer3/input.cpp +++ b/libeplayer3/input.cpp @@ -60,7 +60,7 @@ Input::~Input() int64_t calcPts(AVFormatContext *avfc, AVStream * stream, int64_t pts) { if (!avfc || !stream) { - fprintf(stderr, "player / stream null\n"); + fprintf(stderr, "context / stream null\n"); return INVALID_PTS_VALUE; } @@ -168,6 +168,7 @@ bool Input::Play() for (i = 0; i < avfc->nb_streams; i++) if (avfc->streams[i]->codec && avfc->streams[i]->codec->codec) avcodec_flush_buffers(avfc->streams[i]->codec); + player->output.ClearVideo(); } AVPacket packet; @@ -183,14 +184,13 @@ bool Input::Play() player->readCount += packet.size; - int pid = avfc->streams[packet.stream_index]->id; - + AVStream *stream = avfc->streams[packet.stream_index]; Track *_videoTrack = videoTrack; Track *_audioTrack = audioTrack; Track *_subtitleTrack = subtitleTrack; Track *_teletextTrack = teletextTrack; - if (_videoTrack && (_videoTrack->pid == pid)) { + if (_videoTrack && (_videoTrack->stream == stream)) { int64_t pts = calcPts(avfc, _videoTrack->stream, packet.pts); if (!player->output.Write(avfc, _videoTrack->stream, &packet, pts)) { if (warnVideoWrite) @@ -200,7 +200,7 @@ bool Input::Play() warnVideoWrite = 100; } } - } else if (_audioTrack && (_audioTrack->pid == pid)) { + } else if (_audioTrack && (_audioTrack->stream == stream)) { if (restart_audio_resampling) { restart_audio_resampling = false; player->output.Write(avfc, _audioTrack->stream, NULL, 0); @@ -216,7 +216,7 @@ bool Input::Play() } } } - } else if (_subtitleTrack && (_subtitleTrack->pid == pid)) { + } else if (_subtitleTrack && (_subtitleTrack->stream == stream)) { if (((AVStream *) _subtitleTrack->stream)->codec->codec) { AVSubtitle sub; memset(&sub, 0, sizeof(sub)); @@ -229,7 +229,7 @@ bool Input::Play() switch (sub.rects[0]->type) { case SUBTITLE_TEXT: // FIXME? case SUBTITLE_ASS: - dvbsub_ass_write(((AVStream *) _subtitleTrack->stream)->codec, &sub, pid); + dvbsub_ass_write(_subtitleTrack->stream->codec, &sub, _subtitleTrack->stream->id); break; case SUBTITLE_BITMAP: { int64_t pts = calcPts(avfc, _subtitleTrack->stream, packet.pts); @@ -242,8 +242,8 @@ bool Input::Play() } } } - } else if (_teletextTrack && (_teletextTrack->pid == pid)) { - teletext_write(pid, packet.data, packet.size); + } else if (_teletextTrack && (_teletextTrack->stream == stream)) { + teletext_write(_teletextTrack->stream->id, packet.data, packet.size); } av_free_packet(&packet); diff --git a/libeplayer3/output.cpp b/libeplayer3/output.cpp index b48ea60..acc5ac7 100644 --- a/libeplayer3/output.cpp +++ b/libeplayer3/output.cpp @@ -128,6 +128,7 @@ bool Output::Play() if (videoStream && videofd > -1) { videoWriter = Writer::GetWriter(videoStream->codec->codec_id, videoStream->codec->codec_type); + videoWriter->Init(); if (dioctl(videofd, VIDEO_SET_ENCODING, videoWriter->GetVideoEncoding(videoStream->codec->codec_id)) || dioctl(videofd, VIDEO_PLAY, NULL)) ret = false; @@ -135,6 +136,7 @@ bool Output::Play() if (audioStream && audiofd > -1) { audioWriter = Writer::GetWriter(audioStream->codec->codec_id, audioStream->codec->codec_type); + audioWriter->Init(); if (dioctl(audiofd, AUDIO_SET_ENCODING, audioWriter->GetAudioEncoding(audioStream->codec->codec_id)) || dioctl(audiofd, AUDIO_PLAY, NULL)) ret = false; diff --git a/libeplayer3/player.cpp b/libeplayer3/player.cpp index 06a1f5a..9e8b2ff 100644 --- a/libeplayer3/player.cpp +++ b/libeplayer3/player.cpp @@ -72,10 +72,7 @@ bool Player::Open(const char *Url, bool _noprobe) manager.clearTracks(); - if (*Url == '/') { - url = "file://"; - url += Url; - } else if (!strncmp("mms://", Url, 6)) { + if (!strncmp("mms://", Url, 6)) { url = "mmst"; url += Url + 3; isHttp = true; @@ -207,7 +204,6 @@ bool Player::Stop() bool ret = true; if (isPlaying) { - isPaused = false; isPlaying = false; isForwarding = false; diff --git a/libeplayer3/writer/divx.cpp b/libeplayer3/writer/divx.cpp index 4de3436..a8e75c8 100644 --- a/libeplayer3/writer/divx.cpp +++ b/libeplayer3/writer/divx.cpp @@ -54,16 +54,14 @@ bool WriterDIVX::Write(int fd, AVFormatContext * /* avfc */, AVStream *stream, A return false; uint8_t PesHeader[PES_MAX_HEADER_SIZE]; - uint8_t FakeHeaders[64]; // 64bytes should be enough to make the fake headers + uint8_t FakeHeaders[64] = { 0 }; // 64bytes should be enough to make the fake headers unsigned int FakeHeaderLength; uint8_t Version = 5; unsigned int FakeStartCode = (Version << 8) | PES_VERSION_FAKE_START_CODE; unsigned int usecPerFrame = 41708; /* Hellmaster1024: default value */ BitPacker_t ld = { FakeHeaders, 0, 32 }; - usecPerFrame = 1000000 / av_q2d(stream->r_frame_rate); - - memset(FakeHeaders, 0, sizeof(FakeHeaders)); + usecPerFrame = 1000000.0 / av_q2d(stream->r_frame_rate); /* Create info record for frame parser */ /* divx4 & 5 @@ -75,11 +73,10 @@ bool WriterDIVX::Write(int fd, AVFormatContext * /* avfc */, AVStream *stream, A PutBits(&ld, 0, 8); // profile = reserved PutBits(&ld, 0x1b2, 32); // startcode (user data) PutBits(&ld, 0x53545443, 32); // STTC - an embedded ST timecode from an avi file - PutBits(&ld, usecPerFrame, 32); - // microseconds per frame + PutBits(&ld, usecPerFrame, 32); // microseconds per frame FlushBits(&ld); - FakeHeaderLength = (ld.Ptr - (FakeHeaders)); + FakeHeaderLength = (ld.Ptr - FakeHeaders); struct iovec iov[4]; int ic = 0; diff --git a/libeplayer3/writer/misc.cpp b/libeplayer3/writer/misc.cpp index 68731d1..c63e659 100644 --- a/libeplayer3/writer/misc.cpp +++ b/libeplayer3/writer/misc.cpp @@ -38,9 +38,9 @@ void PutBits(BitPacker_t * ld, unsigned int code, unsigned int length) #ifdef DEBUG_PUTBITS if (ld->debug) - dprintf("code = %d, length = %d, bit_buf = 0x%x, bit_left = %d\n", - code, length, bit_buf, bit_left); -#endif /* DEBUG_PUTBITS */ + dprintf("code = %d, length = %d, bit_buf = 0x%x, bit_left = %d\n", + code, length, bit_buf, bit_left); +#endif if (length < bit_left) { /* fits into current buffer */ @@ -50,10 +50,10 @@ void PutBits(BitPacker_t * ld, unsigned int code, unsigned int length) /* doesn't fit */ bit_buf <<= bit_left; bit_buf |= code >> (length - bit_left); - ld->Ptr[0] = (char) (bit_buf >> 24); - ld->Ptr[1] = (char) (bit_buf >> 16); - ld->Ptr[2] = (char) (bit_buf >> 8); - ld->Ptr[3] = (char) bit_buf; + ld->Ptr[0] = (uint8_t) (bit_buf >> 24); + ld->Ptr[1] = (uint8_t) (bit_buf >> 16); + ld->Ptr[2] = (uint8_t) (bit_buf >> 8); + ld->Ptr[3] = (uint8_t) bit_buf; ld->Ptr += 4; length -= bit_left; bit_buf = code & ((1 << length) - 1); @@ -64,7 +64,7 @@ void PutBits(BitPacker_t * ld, unsigned int code, unsigned int length) #ifdef DEBUG_PUTBITS if (ld->debug) dprintf("bit_left = %d, bit_buf = 0x%x\n", bit_left, bit_buf); -#endif /* DEBUG_PUTBITS */ +#endif /* writeback */ ld->BitBuffer = bit_buf; @@ -78,7 +78,7 @@ void FlushBits(BitPacker_t * ld) #ifdef DEBUG_PUTBITS if (ld->debug) dprintf("flushing 0x%2.2x\n", ld->BitBuffer >> 24); -#endif /* DEBUG_PUTBITS */ +#endif *ld->Ptr++ = ld->BitBuffer >> 24; ld->BitBuffer <<= 8; ld->Remaining += 8; diff --git a/libspark/playback_libeplayer3.cpp b/libspark/playback_libeplayer3.cpp index 2da26b0..152b63b 100644 --- a/libspark/playback_libeplayer3.cpp +++ b/libspark/playback_libeplayer3.cpp @@ -17,18 +17,12 @@ extern cVideo *videoDecoder; //Used by Fileplay bool cPlayback::Open(playmode_t PlayMode) { - const char *aPLAYMODE[] = { - "PLAYMODE_TS", - "PLAYMODE_FILE" - }; - if (PlayMode != PLAYMODE_TS) { audioDecoder->closeDevice(); videoDecoder->closeDevice(); decoders_closed = true; } - printf("%s:%s - PlayMode=%s\n", __FILE__, __func__, aPLAYMODE[PlayMode]); pm = PlayMode; fn_ts = ""; fn_xml = ""; @@ -39,95 +33,73 @@ bool cPlayback::Open(playmode_t PlayMode) return 0; } -//Used by Fileplay void cPlayback::Close(void) { - printf("%s:%s\n", __FILE__, __func__); + printf("%s %s %d\n", __FILE__, __func__, __LINE__); -//Dagobert: movieplayer does not call stop, it calls close ;) + //Dagobert: movieplayer does not call stop, it calls close ;) Stop(); - if (decoders_closed) - { + if (decoders_closed) { audioDecoder->openDevice(); videoDecoder->openDevice(); decoders_closed = false; } } -//Used by Fileplay bool cPlayback::Start(char *filename, int vpid, int vtype, int apid, int ac3, unsigned int) { bool ret = false; bool isHTTP = false; no_probe = false; - printf("%s:%s - filename=%s vpid=%u vtype=%d apid=%u ac3=%d, no_probe=%d\n", - __FILE__, __func__, filename, vpid, vtype, apid, ac3, no_probe); + fprintf(stderr, "%s:%s - filename=%s vpid=%u vtype=%d apid=%u ac3=%d\n", __FILE__, __func__, filename, vpid, vtype, apid, ac3); init_jump = -1; - //try to open file - if(player && player->Open(filename, no_probe)) { - if (pm != PLAYMODE_TS) { - player->output.Open(); - - SetAPid(apid, 0); - ret = player->Play(); + std::string file; + if (*filename == '/') + file = "file://"; + file += filename; + + if (file.substr(0, 7) == "file://") { + if (file.substr(file.length() - 3) == ".ts") { + fn_xml = file.substr(7, file.length() - 2); + fn_xml += "xml"; + no_probe = true; } - } + } else + isHTTP = true; -/* konfetti: in case of upnp playing mp4 often leads to a - * paused playback but data is already injected which leads - * to errors ... - * and I don't see any sense of pausing direct after starting - * with the exception of timeshift. but this should be handled - * outside this lib or with another function! - */ - if (pm != PLAYMODE_TS) { - if ((ret) && (!isHTTP)) { - //pause playback in case of timeshift - //FIXME: no picture on tv - if (!player->Pause()) { - ret = false; - printf("failed to pause playback\n"); - } else - playing = true; - } else - playing = true; - } - - printf("%s:%s - return=%d\n", __FILE__, __func__, ret); - - fn_ts = std::string(filename); - if (fn_ts.length() > 3 && fn_ts.rfind(".ts") == fn_ts.length() - 3) { - fn_xml = fn_ts.substr(0, fn_ts.length() - 3) + ".xml"; - no_probe = true; - } - - if (pm == PLAYMODE_TS) { - struct stat s; - if (!stat(filename, &s)) - last_size = s.st_size; - if (player) { + if (player->Open(file.c_str(), no_probe)) { + if (pm == PLAYMODE_TS) { + struct stat s; + if (!stat(file.c_str(), &s)) + last_size = s.st_size; ret = true; videoDecoder->Stop(false); audioDecoder->Stop(); + } else { + playing = true; + player->output.Open(); + if (apid) + SetAPid(apid, 0); + ret = player->Play(); + if (ret && !isHTTP) + playing = ret = player->Pause(); } } return ret; } -//Used by Fileplay bool cPlayback::Stop(void) { printf("%s:%s playing %d\n", __FILE__, __func__, playing); - //if(playing==false) return false; player->Stop(); player->output.Close(); player->Close(); - playing=false; + playing = false; return true; } @@ -150,8 +122,7 @@ bool cPlayback::SetSpeed(int speed) { printf("%s:%s playing %d speed %d\n", __FILE__, __func__, playing, speed); - if (! decoders_closed) - { + if (!decoders_closed) { audioDecoder->closeDevice(); videoDecoder->closeDevice(); decoders_closed = true; @@ -160,45 +131,38 @@ bool cPlayback::SetSpeed(int speed) playing = player->Play(); } - if(playing==false) + if(!playing) return false; - - int result = 0; + + bool res = true; nPlaybackSpeed = speed; if (speed > 1) { /* direction switch ? */ - if (player->isBackWard) { - result = player->FastBackward(0); - } - result = player->FastForward(speed); + if (player->isBackWard) + player->FastBackward(0); + res = player->FastForward(speed); } else if (speed < 0) { - /* direction switch ? */ - if (player->isForwarding) { - result = player->Continue(); - } - result = player->FastBackward(speed); + /* direction switch ? */ + if (player->isForwarding) + player->Continue(); + res = player->FastBackward(speed); } else if (speed == 0) { - /* konfetti: hmmm accessing the member isn't very proper */ + /* konfetti: hmmm accessing the member isn't very proper */ if ((player->isForwarding) || (!player->isBackWard)) - player->Pause(); - else { - player->FastForward(0); - } - } else { - result = player->Continue(); + /* res = */ player->Pause(); + else + /* res = */ player->FastForward(0); + } else /* speed == 1 */ { + res = player->Continue(); } if (init_jump > -1) { SetPosition(init_jump); init_jump = -1; } - if (!result) { - printf("returning false\n"); - return false; - } - return true; + return res; } bool cPlayback::GetSpeed(int &speed) const @@ -221,16 +185,13 @@ bool cPlayback::GetPosition(int &position, int &duration) * by comparing the mtime with the mtime of the xml file */ if (pm == PLAYMODE_TS) { struct stat s; - if (!stat(fn_ts.c_str(), &s)) - { - if (! playing || last_size != s.st_size) - { + if (!stat(fn_ts.c_str(), &s)) { + if (!playing || last_size != s.st_size) { last_size = s.st_size; time_t curr_time = s.st_mtime; - if (!stat(fn_xml.c_str(), &s)) - { + if (!stat(fn_xml.c_str(), &s)) { duration = (curr_time - s.st_mtime) * 1000; - if (! playing) + if (!playing) return true; got_duration = true; } @@ -238,7 +199,8 @@ bool cPlayback::GetPosition(int &position, int &duration) } } - if(playing==false) return false; + if (!playing) + return false; if (!player->isPlaying) { printf("cPlayback::%s !!!!EOF!!!! < -1\n", __func__); @@ -263,19 +225,17 @@ bool cPlayback::GetPosition(int &position, int &duration) player->GetDuration(length); - if(length <= 0) { + if(length <= 0) duration = duration+1000; - } else { + else duration = length*1000.0; - } return true; } bool cPlayback::SetPosition(int position, bool absolute) { - if (playing == false) - { + if (!playing) { /* the calling sequence is: * Start() - paused * SetPosition() - which fails if not running @@ -359,7 +319,7 @@ void cPlayback::GetMetadata(std::vector &keys, std::vector