Skip to content
This repository

fixed: Stream flags would show for non-video files/items (fixes #14176) #2486

Merged
merged 8 commits into from over 1 year ago

3 participants

arnova jmarshallnz
arnova
Collaborator

No description provided.

xbmc/video/VideoThumbLoader.cpp
... ... @@ -200,7 +200,11 @@ bool CVideoThumbLoader::LoadItem(CFileItem* pItem)
200 200
201 201 m_database->Open();
202 202
203   - if (pItem->HasVideoInfoTag() && !pItem->GetVideoInfoTag()->HasStreamDetails() && pItem->IsVideo())
  203 + if (pItem->HasVideoInfoTag() && !pItem->GetVideoInfoTag()->HasStreamDetails() &&
  204 + (pItem->GetVideoInfoTag()->m_type.empty() ||
  205 + pItem->GetVideoInfoTag()->m_type == "movie" ||
  206 + pItem->GetVideoInfoTag()->m_type == "episode" ||
  207 + pItem->GetVideoInfoTag()->m_type == "musicvideo"))
204 208 {
2
jmarshallnz Owner

I think in this block we can rule out folders with a not a folder check? Basically any files will do, right?

What checks for stream details for files not in the library that have stream details extracted already but don't have an info tag set? Are they taken care of somewhere else? Or do you never get a video file without an info tag in here?

This doesn't apply to the block below however.

arnova Collaborator
arnova added a note

Yup, just files will do: updated with !m_bIsFolder check.

Afaik as soon as an item gets stream details extracted (thumbs and/or flags) it gets automatically added to the library. I've tested this myself and it seems to work fine.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Compiled with this patch

Only thing it did was reset all my Files view modes to List instead of mediainfo

Library was unscaved from view reset but still shows issues on tv shows and movie sets in various views. SO unfortunately unless Im missing something, no joy.

uNi

arnova
Collaborator

@uNiversaI : I think I understand why, the logic at the end of loaditem has always been flawed (which I just noticed now). I'll fix it up which should take care of it.

arnova
Collaborator

@uNiversaI / @jmarshallnz : Updated PR with another fix, please let me know whether it's ok.

Ok presuming that only that last patch is applied. I can confirm that the rogue flag being pulled for non file items, does indeed fix the issue.

Thank you @arnova for addressing this large annoyance and @jm for queuing this under the radar.

thanks again, gratitude.

It also would be worth mentioning that with aeed179 it also works for extracting the listing SD/HD (blue/green) flag for multiepisodes showname S01E01E02.extension type scenario, as previously the second episode was listed without that flag until playback was initiated/stopped.
It also worked if file was not in library and previously had been, haven't tested if file was not in library at any point and haven't test stacked/non stacked files, but can test all those scenarios out.

If testing is welcome for this last bit let me know what commits to pull and compile as its gotten somewhat confusing now which is the patch(s) to pull/compile, presume its's 2c48b89 and 4c063c7.

Please provide instructions and I will test it and confirm its those two last patches needed only.

Thanks again.

arnova
Collaborator

@jmarshallnz : I updated the PR. It also includes a fixed for the automatic extraction of flags/thumbs which didn't previously work for items without a videoinfotag. Let me know whether it's ok now.

jmarshallnz
Owner

I think some of the first and third commits could be squashed, right?

arnova
Collaborator

@jmarshallnz : Updated and squashed (as much as seemed logical). Let me know whether there's anything missing and/or needs reshuffling/squashing.

arnova
Collaborator

@jmarshallnz: Ping. Only thing I'm not 100% sure about is the approach I chose in IsVideo(bool). alternatively we could also use the infotag's filename to determine whether it's a video file...

xbmc/video/VideoDatabase.cpp
((23 lines not shown))
3112 3115
  3116 + if (fileId < 0)
  3117 + return false;
  3118 +
  3119 + return GetStreamDetails(*item.GetVideoInfoTag());
  3120 +}
6
jmarshallnz Owner

I think this could be improved slightly as follows:

if (fileId < 0)
  fileId = GetFileId(item);

if (fileId < 0)
  return false;

// have a file id, get stream details if available (creates tag either way)
item.GetVideoInfoTag()->m_iFileId = fileId;
return GetStreamDetails(*item.GetVideoInfoTag());
arnova Collaborator
arnova added a note

Why would we want to do a GetFileId(item) if the its VideoInfoTag may already have a fileid, seems like waisting a db call...?

jmarshallnz Owner

Thus the if statement?

arnova Collaborator
arnova added a note

If you mean by "thus":

if (fileId >= 0)
item.GetVideoInfoTag()->m_iFileId = fileId;

Then yes...

jmarshallnz Owner

Not sure what you are referring to. I mean exactly the code I wrote in place of the block that I commented on. If you already have the fileId from the infotag, then fileId >= 0 so the if (fileId < 0) blocks aren't executed, thus no db lookup other than the streamdetails call.

arnova Collaborator
arnova added a note

Oh crap, I missed the piece of code that gets the FileId from the infotag before that block. Sorry: still early here in Holland.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
xbmc/video/VideoThumbLoader.cpp
((6 lines not shown))
105 105 {
  106 + // Only extract details when we either don't have an infotag or no streamdetails already
2
jmarshallnz Owner

not sure the comment here adds anything other than confusion. Maybe

// no tag or no details set, so extract them.

arnova Collaborator
arnova added a note

Agreed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
xbmc/video/VideoThumbLoader.cpp
... ... @@ -200,7 +201,7 @@ bool CVideoThumbLoader::LoadItem(CFileItem* pItem)
200 201
201 202 m_database->Open();
202 203
203   - if (pItem->HasVideoInfoTag() && !pItem->GetVideoInfoTag()->HasStreamDetails() && pItem->IsVideo())
  204 + if ((pItem->m_bIsFolder || pItem->IsVideo(true)) && (!pItem->HasVideoInfoTag() || !pItem->GetVideoInfoTag()->HasStreamDetails() ) )
9
jmarshallnz Owner

this conditional either is wrong or needs some explanation. I would think we should be able to go with ignoring the video type here, as that should be taken care of in the database function anyway (no fileid can be derived -> no details)

arnova Collaborator
arnova added a note

Well the idea was again that we want to prevent useles db calls and thus at least make sure it's an item that could possibly have streamdetails (videofile or folder), right?

jmarshallnz Owner

Sure, but you allow all folder items anyway, most of which won't have a fileid.

arnova Collaborator
arnova added a note

That's true. Well I'm all for preventing db calls where possible (especially beneficial for eg. ARM), so if you really want no longer want to check the file-type here, I'll change it.

jmarshallnz Owner

I agree with the principle, but it's proving tricky to get a nice conditional. :) I think the only folders allowed are those with a fileid already available in the videoinfotag, so maybe something like:

if (!HasVideoInfoTag() || !GetVideoInfoTag()->HasStreamDetails()) // no stream details
{
  if ((HasVideoInfoTag() && GetVideoInfoTag()->m_iFileId >= 0) // file (or maybe folder) is in the database
  || (IsVideo() && !m_bIsFolder)) // some other video file for which we haven't yet got any database details
    // grab them there streamdetails from the db.
}

Something similar may then work for the extraction stuff below maybe?

arnova Collaborator
arnova added a note

Yeah at first sight that seems to make sense. I'll let it run through my mind a few times to make sure it's the best approach

arnova Collaborator
arnova added a note

I'm not entirely sure about the folder thing, although I can't think of a scenario right now. I do think this seems slightly better:

if (!HasVideoInfoTag() || !GetVideoInfoTag()->HasStreamDetails()) // no stream details
{
if ((HasVideoInfoTag() && GetVideoInfoTag()->m_iFileId >= 0) // file (or maybe folder) is in the database
|| (IsVideo(true)) // some other video file for which we haven't yet got any database details
// grab them there streamdetails from the db.
}

Agreed?

jmarshallnz Owner

IsVideo(true) just does !m_bIsFolder && IsVideo() pretty much - only difference is we only go with the infotag if m_type is not set or set to movie, episode or musicvideo. Given that the only other times m_type is set is for folder items from the database, this seems not required.

You'll notice I've subtly got around all uses of IsVideo(true) :p

arnova Collaborator
arnova added a note

Well, honestly I don't see the point of doing it the way you propose if we might as well use IsVideo(true) for that. But I'm fine with it either way, as I just like to wrap this PR up ASAP.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
xbmc/FileItem.cpp
((17 lines not shown))
  765 + if (filesOnly)
  766 + {
  767 + if (m_bIsFolder)
  768 + return false;
  769 +
  770 + if (HasVideoInfoTag() &&
  771 + (GetVideoInfoTag()->m_type == "movie" ||
  772 + GetVideoInfoTag()->m_type == "episode" ||
  773 + GetVideoInfoTag()->m_type == "musicvideo") )
  774 + return true;
  775 + }
  776 + else
  777 + {
  778 + if (HasVideoInfoTag()) return true;
  779 + if (HasMusicInfoTag()) return false;
  780 + if (HasPictureInfoTag()) return false;
2
jmarshallnz Owner

These two should be done in both branches (move out as per PVR)

arnova Collaborator
arnova added a note

Ah yes, makes sense.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
xbmc/video/VideoThumbLoader.cpp
... ... @@ -244,10 +249,10 @@ bool CVideoThumbLoader::LoadItem(CFileItem* pItem)
244 249 SetArt(*pItem, artwork);
245 250 }
246 251
247   - // thumbnails are special-cased due to auto-generation
248   - if (!pItem->m_bIsFolder && pItem->IsVideo())
  252 + // We can only extract flags/thumbs for file-like items
  253 + if (pItem->IsVideo(true))
5
jmarshallnz Owner

I'm not sure if this actually makes any difference. Does anything return true for the original conditional but false for the new one?

arnova Collaborator
arnova added a note

Yup: This is where a very old bug was creeping. We would always try to extract thumbs/flags for m_type==tvshow here due to the IsVideo() returning true because of HasVideoInfoTag()...

jmarshallnz Owner

Yes, but !pItem->m_bIsFolder is false for tvshows, right?

arnova Collaborator
arnova added a note

Hmm yes (at least I like to believe it does). Oh I recall now where the actual problem I mentioned was: it was in the block below that handles the flag-extraction. If you want this back to the way it was, I'll change it back, I'm fine with it either way.

arnova Collaborator
arnova added a note

Same goes for the one here: Either IsVideo(true) or "IsVideo() && !m_bIsFolder" is fine.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
arnova
Collaborator

@jmarshallnz : All updated/squashed. As you can see I've kept the 2 uses of IsVideo(true) as I really believe those are much safer/accurate to determine whether those blocks should be run. Especially if the surrounding code is ever going to be changed (again). Relying on the fact that hitting the HasVideoInfoTag() in IsVideo() won't happen due to other factors in the equation isn't going to do it for me, and I really don't want this to bite us/me in the tail again...

jmarshallnz
Owner

The reason I prefer (!pItem->m_bIsFolder && pItem->IsVideo()) is because it's obvious from reading the code what the conditions are. Now it's masked behind IsVideo(true) so needs a comment so you know what it means. Self-documenting code seems better to me, particularly when it's simple.

The tricky bit here was that some folders can have streamdetails previously assigned. This is taken care of by the check for m_iFileId, so the tricky bit isn't even affected by this conditional.

The simple bit is determining when to generate stream details or auto-thumbs. In this case you need only make sure you don't have a folder and that it's a video. Nice and simple to understand.

arnova
Collaborator

@jmarshallnz: If you put it that way I agree. I updated the PR, I do wonder whether you want to get rid of the commit that implements IsVideo(bool) now?

jmarshallnz
Owner

I think so, yeah. maybe replace it with a bit of doxy (on IsVideo, IsMusic, IsPicture) about the potential issue?

arnova
Collaborator

@jmarshallnz: Removed the commit for IsVideo(bool) + added doxygen.

jmarshallnz
Owner

Looks good with that minor change - merge away once done.

arnova arnova merged commit d1d4334 into from
arnova arnova closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
20 xbmc/FileItem.h
@@ -104,11 +104,31 @@ class CFileItem :
104 104 virtual bool IsFileItem() const { return true; };
105 105
106 106 bool Exists(bool bUseCache = true) const;
  107 +
  108 + /*!
  109 + \brief Check whether an item is a video item. Note that this returns true for
  110 + anything with a video info tag, so that may include eg. folders.
  111 + \return true if item is video, false otherwise.
  112 + */
107 113 bool IsVideo() const;
  114 +
108 115 bool IsDiscStub() const;
  116 +
  117 + /*!
  118 + \brief Check whether an item is a picture item. Note that this returns true for
  119 + anything with a picture info tag, so that may include eg. folders.
  120 + \return true if item is picture, false otherwise.
  121 + */
109 122 bool IsPicture() const;
110 123 bool IsLyrics() const;
  124 +
  125 + /*!
  126 + \brief Check whether an item is an audio item. Note that this returns true for
  127 + anything with a music info tag, so that may include eg. folders.
  128 + \return true if item is audio, false otherwise.
  129 + */
111 130 bool IsAudio() const;
  131 +
112 132 bool IsKaraoke() const;
113 133 bool IsCUESheet() const;
114 134 bool IsInternetStream(const bool bStrictCheck = false) const;
5 xbmc/cores/dvdplayer/DVDFileInfo.cpp
@@ -295,8 +295,9 @@ bool CDVDFileInfo::GetFileStreamDetails(CFileItem *pItem)
295 295 CStdString strFileNameAndPath;
296 296 if (pItem->HasVideoInfoTag())
297 297 strFileNameAndPath = pItem->GetVideoInfoTag()->m_strFileNameAndPath;
298   - else
299   - return false;
  298 +
  299 + if (strFileNameAndPath.empty())
  300 + strFileNameAndPath = pItem->GetPath();
300 301
301 302 CStdString playablePath = strFileNameAndPath;
302 303 if (URIUtils::IsStack(playablePath))
20 xbmc/video/VideoDatabase.cpp
@@ -3100,16 +3100,22 @@ CVideoInfoTag CVideoDatabase::GetDetailsByTypeAndId(VIDEODB_CONTENT_TYPE type, i
3100 3100
3101 3101 bool CVideoDatabase::GetStreamDetails(CFileItem& item)
3102 3102 {
3103   - if (!item.HasVideoInfoTag())
3104   - return false;
  3103 + // Note that this function (possibly) creates VideoInfoTags for items that don't have one yet!
  3104 + int fileId = -1;
3105 3105
3106   - CVideoInfoTag *tag = item.GetVideoInfoTag();
3107   - if (tag->m_iFileId < 0)
3108   - tag->m_iFileId = GetFileId(item);
  3106 + if (item.HasVideoInfoTag())
  3107 + fileId = item.GetVideoInfoTag()->m_iFileId;
3109 3108
3110   - return GetStreamDetails(*tag);
3111   -}
  3109 + if (fileId < 0)
  3110 + fileId = GetFileId(item);
3112 3111
  3112 + if (fileId < 0)
  3113 + return false;
  3114 +
  3115 + // Have a file id, get stream details if available (creates tag either way)
  3116 + item.GetVideoInfoTag()->m_iFileId = fileId;
  3117 + return GetStreamDetails(*item.GetVideoInfoTag());
  3118 +}
3113 3119
3114 3120 bool CVideoDatabase::GetStreamDetails(CVideoInfoTag& tag) const
3115 3121 {
65 xbmc/video/VideoThumbLoader.cpp
@@ -101,8 +101,9 @@ bool CThumbExtractor::DoWork()
101 101 m_item.SetArt("thumb", m_target);
102 102 }
103 103 }
104   - else if (m_item.HasVideoInfoTag() && !m_item.GetVideoInfoTag()->HasStreamDetails())
  104 + else if (!m_item.HasVideoInfoTag() || !m_item.GetVideoInfoTag()->HasStreamDetails())
105 105 {
  106 + // No tag or no details set, so extract them
106 107 CLog::Log(LOGDEBUG,"%s - trying to extract filestream details from video file %s", __FUNCTION__, m_item.GetPath().c_str());
107 108 result = CDVDFileInfo::GetFileStreamDetails(&m_item);
108 109 }
@@ -200,10 +201,14 @@ bool CVideoThumbLoader::LoadItem(CFileItem* pItem)
200 201
201 202 m_database->Open();
202 203
203   - if (pItem->HasVideoInfoTag() && !pItem->GetVideoInfoTag()->HasStreamDetails() && pItem->IsVideo())
  204 + if (!pItem->HasVideoInfoTag() || !pItem->GetVideoInfoTag()->HasStreamDetails()) // no stream details
204 205 {
205   - if (m_database->GetStreamDetails(*pItem))
206   - pItem->SetInvalid();
  206 + if ((pItem->HasVideoInfoTag() && pItem->GetVideoInfoTag()->m_iFileId >= 0) // file (or maybe folder) is in the database
  207 + || (!pItem->m_bIsFolder && pItem->IsVideo())) // Some other video file for which we haven't yet got any database details
  208 + {
  209 + if (m_database->GetStreamDetails(*pItem))
  210 + pItem->SetInvalid();
  211 + }
207 212 }
208 213
209 214 // video db items normally have info in the database
@@ -211,7 +216,11 @@ bool CVideoThumbLoader::LoadItem(CFileItem* pItem)
211 216 {
212 217 FillLibraryArt(*pItem);
213 218
214   - if (!pItem->IsVideo() && !pItem->m_bIsFolder)
  219 + if (!pItem->GetVideoInfoTag()->m_type.empty() &&
  220 + pItem->GetVideoInfoTag()->m_type != "movie" &&
  221 + pItem->GetVideoInfoTag()->m_type != "tvshow" &&
  222 + pItem->GetVideoInfoTag()->m_type != "episode" &&
  223 + pItem->GetVideoInfoTag()->m_type != "musicvideo")
215 224 {
216 225 m_database->Close();
217 226 return true; // nothing else to be done
@@ -244,10 +253,10 @@ bool CVideoThumbLoader::LoadItem(CFileItem* pItem)
244 253 SetArt(*pItem, artwork);
245 254 }
246 255
247   - // thumbnails are special-cased due to auto-generation
  256 + // We can only extract flags/thumbs for file-like items
248 257 if (!pItem->m_bIsFolder && pItem->IsVideo())
249 258 {
250   - // An auto-generated thumb may have been cached on a different device - check we have it here
  259 + // An auto-generated thumb may have been cached on a different device - check we have it here
251 260 CStdString url = pItem->GetArt("thumb");
252 261 if (url.compare(0, 14, "image://video@") == 0 && !CTextureCache::Get().HasCachedImage(url))
253 262 pItem->SetArt("thumb", "");
@@ -262,13 +271,17 @@ bool CVideoThumbLoader::LoadItem(CFileItem* pItem)
262 271 pItem->SetProperty("HasAutoThumb", true);
263 272 pItem->SetProperty("AutoThumbImage", thumbURL);
264 273 pItem->SetArt("thumb", thumbURL);
265   - // Item has cached autogen image but no art entry. Save it to db.
266   - CVideoInfoTag* info = pItem->GetVideoInfoTag();
267   - if (info->m_iDbId > 0 && !info->m_type.empty())
268   - m_database->SetArtForItem(info->m_iDbId, info->m_type, "thumb", thumbURL);
  274 +
  275 + if (pItem->HasVideoInfoTag())
  276 + {
  277 + // Item has cached autogen image but no art entry. Save it to db.
  278 + CVideoInfoTag* info = pItem->GetVideoInfoTag();
  279 + if (info->m_iDbId > 0 && !info->m_type.empty())
  280 + m_database->SetArtForItem(info->m_iDbId, info->m_type, "thumb", thumbURL);
  281 + }
269 282 }
270 283 else if (g_guiSettings.GetBool("myvideos.extractthumb") &&
271   - g_guiSettings.GetBool("myvideos.extractflags"))
  284 + g_guiSettings.GetBool("myvideos.extractflags"))
272 285 {
273 286 CFileItem item(*pItem);
274 287 CStdString path(item.GetPath());
@@ -282,21 +295,20 @@ bool CVideoThumbLoader::LoadItem(CFileItem* pItem)
282 295 return true;
283 296 }
284 297 }
285   - }
286 298
287   - // flag extraction
288   - if (!pItem->m_bIsFolder &&
289   - pItem->HasVideoInfoTag() &&
290   - g_guiSettings.GetBool("myvideos.extractflags") &&
291   - (!pItem->GetVideoInfoTag()->HasStreamDetails() ||
  299 + // flag extraction
  300 + if (g_guiSettings.GetBool("myvideos.extractflags") &&
  301 + (!pItem->HasVideoInfoTag() ||
  302 + !pItem->GetVideoInfoTag()->HasStreamDetails() ||
292 303 pItem->GetVideoInfoTag()->m_streamDetails.GetVideoDuration() <= 0))
293   - {
294   - CFileItem item(*pItem);
295   - CStdString path(item.GetPath());
296   - if (URIUtils::IsInRAR(item.GetPath()))
297   - SetupRarOptions(item,path);
298   - CThumbExtractor* extract = new CThumbExtractor(item,path,false);
299   - AddJob(extract);
  304 + {
  305 + CFileItem item(*pItem);
  306 + CStdString path(item.GetPath());
  307 + if (URIUtils::IsInRAR(item.GetPath()))
  308 + SetupRarOptions(item,path);
  309 + CThumbExtractor* extract = new CThumbExtractor(item,path,false);
  310 + AddJob(extract);
  311 + }
300 312 }
301 313
302 314 m_database->Close();
@@ -439,11 +451,10 @@ void CVideoThumbLoader::OnJobComplete(unsigned int jobID, bool success, CJob* jo
439 451 db.SetArtForItem(info->m_iDbId, info->m_type, "thumb", loader->m_item.GetArt("thumb"));
440 452 db.Close();
441 453 }
442   -
443 454 }
444 455
445 456 if (m_pStreamDetailsObs)
446   - m_pStreamDetailsObs->OnStreamDetails(info->m_streamDetails, info->m_strFileNameAndPath, info->m_iFileId);
  457 + m_pStreamDetailsObs->OnStreamDetails(info->m_streamDetails, !info->m_strFileNameAndPath.IsEmpty() ? info->m_strFileNameAndPath : loader->m_item.GetPath(), info->m_iFileId);
447 458 if (m_pObserver)
448 459 m_pObserver->OnItemLoaded(&loader->m_item);
449 460 CFileItemPtr pItem(new CFileItem(loader->m_item));

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.