New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for Matroska's Ordered Chapters and Segment Linking #10678
Conversation
This is a little hard to review in its current state. Can you squash the commits to create a sensible history? The file you added contains a LOT of stuff. Try to separate this into as many files as possible - this usually shows good modularization and can reveal some architecture mistakes. |
All right. Will try to seperate the code. |
Nevermind. Just googled it. |
For safety reasons, you might want to backup the folder your working on. Just in case. |
If you need any advice with anything to get this PR into shape then #kodi-dev IRC channel is available |
@mojo-hakase do you still working on the squashing/restructuring or shall we start reviewing? |
I am rewriting the whole matroska parsing part and need some more time. Probably next week. Will post a comment if I'm ready. |
I would like you to review my code. |
Please squash prior to review, github used to lose comments when you force-pushed (I think now it just hides them) |
9282fb4
to
f63d71a
Compare
Ok, squashed it. |
@mojo-hakase sorry for the long silence. I really want to have that feature reviewed (and merged sometimes). I hope I can find some time in the next days. One question beforehand: why don't you use libebml? |
@ace20022 no problem, take your time. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I skimmed through the non-parser code. Nice work.
@Paxxi Could you please review the parser code when you have some time?
The parser classes/files need to go somewhere else, not sure where at the moment.
m_curChapter->demuxer->Flush(); | ||
} | ||
|
||
#define GET_PTS(x) ((x)->dts!=DVD_NOPTS_VALUE ? (x)->dts : (x)->pts) |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
double dispPts; | ||
|
||
packet = m_curChapter->demuxer->Read(); | ||
packet && (pts = GET_PTS(packet)); |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
return nullptr; | ||
packet = m_curChapter->demuxer->Read(); | ||
packet && (pts = GET_PTS(packet)); | ||
} |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
--chapterIdx; | ||
if (chapterIdx < 0 || unsigned(chapterIdx) >= m_chapters.size()) | ||
return 0; | ||
return (m_chapters[chapterIdx].startDispTime + 999) / 1000; |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
|
||
std::vector<CDemuxStream*> CDemuxTimeline::GetStreams() const | ||
{ | ||
return m_primaryDemuxer->GetStreams(); |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
|
||
CDVDDemux *m_primaryDemuxer; | ||
|
||
std::list<std::shared_ptr<CDVDDemux>> m_demuxer; |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
std::map<MatroskaSegmentUID,CDVDDemux*> segmentDemuxer; | ||
segmentDemuxer[""] = primaryDemuxer; | ||
segmentDemuxer[mkv.segment.infos.uid] = primaryDemuxer; | ||
std::list<std::string> searchDirs({""}); // should be a global setting |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
return timeline.release(); | ||
} | ||
|
||
// vim: ts=2 sw=2 expandtab |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
|
||
std::list<std::shared_ptr<CDVDDemux>> m_demuxer; | ||
std::list<std::shared_ptr<CDVDInputStream>> m_inputStreams; | ||
//std::map<CDVDDemux*,DemuxerInfo> m_demuxerInfos; |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
ChapterInfo *m_curChapter; | ||
}; | ||
|
||
// vim: ts=2 sw=2 expandtab |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
So... |
I'm guessing this would also need review by @FernetMenta |
This has to be discussed with ffmpeg: https://ffmpeg.org/pipermail/ffmpeg-devel/2008-December/043813.html Bypassing ffmpeg demuxer is the wrong strategy. |
@FernetMenta: What do you mean by "bypassing" ffmpeg demuxer?
What does the link have to do with it? |
Writing an additional demuxer for Kodi is wrong. If you want to add this functionality, you have to implement it in ffmpeg. |
I think not. I think the ffmpeg demuxer is not the right place to implement ordered chapters. Ordered Chapters are just metainformations meant as a hint for the player(!) in which order to play the media. Therefor it should not be implemented by a low level general purpose demuxer that is not dedicated to player applications only, since transmuxing and transcoding applications may not want this behaviour. We could add an boolean field to AVFormatContext, that tells the matroska demuxer in the case of ordered chapters what to you. Although, it seems off, to set a parameter for a specifig demuxer, before knowing what kind demuxer will be used. But it wouldn't be that bad. In my previous comment I have already written about the problems and the need of breaking the API, when implementing segment linking in the demuxer. All these problems are because ordered chapters and segment linking aren't meant to be done by the demuxer but by an additional layer in the player application. So, I think adding a new layer to the player, that is in charge of building the timeline and transparently seeking in the source, is the right way to implement this feature. Although direcly after the demuxer may not be the perfect place for it, but at first is the easiest. I will discuss this on the ffmpeg-devel irc channel. What do you think? |
Currently busy with real life job. Will replay later this week. |
Maybe, but this is not reflected by this code. I don't see this additional layer. You just implemented the demuxer interface. Some weaknesses I noticed in this code:
|
ebml,mkv parser: that's right. As I wrote in a previous comment, I would like to make some changes in the ffmpeg demuxer, so I won't need that parser code anymore. The Problem is with bypassing the demuxer factory. As I injected the TimelineDemuxer creation into the Factory, I could not prevent an endless recursiv call between TimelineDemuxer and DemuxerFactory. It's a result of my Code not really being an additional layer, as you correctly pointed out. I will reconsider my code and think of another way to implement this. I wish you all a Happy New Year. |
Is this still being worked on? It would be a shame for it to never get merged, given that the core logic has been implemented. |
…ld CreateTimeline
09b62ef
to
f2a66eb
Compare
@mojo-hakase this needs a rebase |
This would be a great addition for anime lovers community (because its the only place I find those). Maybe in the addon system there is a place for this ?! |
PR has merit but will labelled If the author would like it kept open please just request so on the PR. |
Description
Adds a timeline demuxer that holds a set of ffmpeg demuxer and transparently switch between them and seeks to right time in the real demuxer for playing matroska's ordered chapters correctly.
When the CDVDFactoryDemuxer successfully creates the CDVDDemuxFFmpeg from a file, the factory will try to create a CDemuxTimeline by calling CDemuxTimeline::CreateTimeline() with the created ffmpeg demuxer as parameter. That function will then check the file for ordered chapters. If the file doesn't use ordered chapters a nullptr is returned, and the factory returns the ffmpeg demuxer as usual.
If the file uses ordered chapters a CDemuxTimeline gets created. It takes over the ffmpeg demuxer as "primaryDemuxer", and gets returned by the factory instead of the ffmpeg demuxer. The timeline creation may involve searching for missing mkv segments in the same directory as the source file if necessary.
Motivation and Context
It implements an feature that is requested since 2009 and discussed in this thread in the kodi forum:
http://forum.kodi.tv/showthread.php?tid=55764
How Has This Been Tested?
As my patch affects the opening of the demuxer, i tested various files without ordered chapters for still being playable and various files with ordered chapters for now begin played correctly.
Screenshots (if appropriate):
Types of change
Checklist: