brave-browser: Playlist crashes when playing large/long-running videos when they're cached
Description
Playlist crashes when switching between large/long-running videos (cached and uncached)
Steps to Reproduce
- install
1.62.89 - launch Brave
- set
brave://flags/#playlisttoEnabled - click
Relaunch - load a bunch of large/long-running vidoes (4+ hours or more, each, typically)
- queue at least one – if not 3 or 4 – for offline-media playback via the context-menu
- play any video
- now, switch between videos
NOTE: It appears to be the larger videos (which are slower to cache offline) which are still downloading that might be the problem, here - but I haven’t fully nailed it down
Actual result:
💥
Crash ID:
6c330f00-f35a-140b-0000-000000000000
[ 00 ] partition_alloc::internal::OnNoMemoryInternal(unsigned long) ( oom.cc:58 )
[ 01 ] partition_alloc::TerminateBecauseOutOfMemory(unsigned long) ( oom.cc:65 )
[ 02 ] partition_alloc::internal::OnNoMemory(unsigned long) ( oom.cc:75 )
[ 03 ] partition_alloc::internal::PartitionExcessiveAllocationSize(unsigned long) ( partition_oom.cc:19 )
[ 04 ] partition_alloc::internal::(anonymous namespace)::PartitionDirectMap(partition_alloc::PartitionRoot*, partition_alloc::internal::AllocFlags, unsigned long, unsigned long) ( partition_bucket.cc:228 )
[ 05 ] partition_alloc::internal::PartitionBucket::SlowPathAlloc(partition_alloc::PartitionRoot*, partition_alloc::internal::AllocFlags, unsigned long, unsigned long, bool*) ( partition_bucket.cc:1340 )
[ 06 ] void* partition_alloc::PartitionRoot::AllocInternalNoHooks<(partition_alloc::internal::AllocFlags)16>(unsigned long, unsigned long) ( partition_root.h:1191 )
[ 07 ] void* partition_alloc::PartitionRoot::AllocInternal<(partition_alloc::internal::AllocFlags)16>(unsigned long, unsigned long, char const*) ( partition_root.h:1953 )
[ 08 ] void* partition_alloc::PartitionRoot::AllocInline<(partition_alloc::internal::AllocFlags)16>(unsigned long, char const*) ( partition_root.h:467 )
[ 09 ] allocator_shim::internal::PartitionMalloc(allocator_shim::AllocatorDispatch const*, unsigned long, void*) ( allocator_shim_default_dispatch_to_partition_alloc.cc:240 )
[ 10 ] base::allocator::dispatcher::internal::DispatcherImpl<base::PoissonAllocationSampler>::AllocFn(allocator_shim::AllocatorDispatch const*, unsigned long, void*) ( dispatcher_internal.h:113 )
[ 11 ] ShimCppNew ( allocator_shim.cc:188 )
[ 12 ] operator new(unsigned long) ( allocator_shim_override_cpp_symbols.h:35 )
[ 13 ] std::__Cr::basic_string<char, std::__Cr::char_traits<char>, std::__Cr::allocator<char>>::append(unsigned long, char) ( new:272 )
[ 14 ] std::__Cr::basic_string<char, std::__Cr::char_traits<char>, std::__Cr::allocator<char>>::resize(unsigned long, char) ( string:3205 )
[ 15 ] std::__Cr::basic_string<char, std::__Cr::char_traits<char>, std::__Cr::allocator<char>>::resize(unsigned long) ( string:1177 )
[ 16 ] base::ReadStreamToStringWithMaxSize(__sFILE*, unsigned long, std::__Cr::basic_string<char, std::__Cr::char_traits<char>, std::__Cr::allocator<char>>*)::$_0::operator()(unsigned long) const ( file_util.cc:315 )
[ 17 ] decltype(std::declval<base::ReadStreamToStringWithMaxSize(__sFILE*, unsigned long, std::__Cr::basic_string<char, std::__Cr::char_traits<char>, std::__Cr::allocator<char>>*)::$_0 const&>()(std::declval<unsigned long>())) std::__Cr::__invoke<base::ReadStreamToStringWithMaxSize(__sFILE*, unsigned long, std::__Cr::basic_string<char, std::__Cr::char_traits<char>, std::__Cr::allocator<char>>*)::$_0 const&, unsigned long>(base::ReadStreamToStringWithMaxSize(__sFILE*, unsigned long, std::__Cr::basic_string<char, std::__Cr::char_traits<char>, std::__Cr::allocator<char>>*)::$_0 const&, unsigned long&&) ( invoke.h:344 )
[ 18 ] std::__Cr::invoke_result<base::ReadStreamToStringWithMaxSize(__sFILE*, unsigned long, std::__Cr::basic_string<char, std::__Cr::char_traits<char>, std::__Cr::allocator<char>>*)::$_0 const&, unsigned long>::type std::__Cr::invoke<base::ReadStreamToStringWithMaxSize(__sFILE*, unsigned long, std::__Cr::basic_string<char, std::__Cr::char_traits<char>, std::__Cr::allocator<char>>*)::$_0 const&, unsigned long>(base::ReadStreamToStringWithMaxSize(__sFILE*, unsigned long, std::__Cr::basic_string<char, std::__Cr::char_traits<char>, std::__Cr::allocator<char>>*)::$_0 const&, unsigned long&&) ( invoke.h:30 )
[ 19 ] base::span<unsigned char, 18446744073709551615ul, unsigned char*> absl::functional_internal::InvokeObject<base::ReadStreamToStringWithMaxSize(__sFILE*, unsigned long, std::__Cr::basic_string<char, std::__Cr::char_traits<char>, std::__Cr::allocator<char>>*)::$_0, base::span<unsigned char, 18446744073709551615ul, unsigned char*>, unsigned long>(absl::functional_internal::VoidPtr, absl::functional_internal::ForwardT<unsigned long>::type) ( function_ref.h:78 )
[ 20 ] absl::FunctionRef<base::span<unsigned char, 18446744073709551615ul, unsigned char*> (unsigned long)>::operator()(unsigned long) const ( function_ref.h:132 )
[ 21 ] base::FunctionRef<base::span<unsigned char, 18446744073709551615ul, unsigned char*> (unsigned long)>::operator()(unsigned long) const ( function_ref.h:90 )
[ 22 ] base::(anonymous namespace)::ReadStreamToSpanWithMaxSize(__sFILE*, unsigned long, base::FunctionRef<base::span<unsigned char, 18446744073709551615ul, unsigned char*> (unsigned long)>) ( file_util.cc:0 )
[ 23 ] base::ReadStreamToStringWithMaxSize(__sFILE*, unsigned long, std::__Cr::basic_string<char, std::__Cr::char_traits<char>, std::__Cr::allocator<char>>*) ( file_util.cc:313 )
[ 24 ] base::ReadFileToStringWithMaxSize(base::FilePath const&, std::__Cr::basic_string<char, std::__Cr::char_traits<char>, std::__Cr::allocator<char>>*, unsigned long) ( file_util.cc:362 )
[ 25 ] base::ReadFileToString(base::FilePath const&, std::__Cr::basic_string<char, std::__Cr::char_traits<char>, std::__Cr::allocator<char>>*) ( file_util.cc:348 )
[ 26 ] playlist::(anonymous namespace)::ReadFileToString(base::FilePath const&) ( playlist_data_source.cc:32 )
[ 27 ] base::OnceCallback<scoped_refptr<base::RefCountedBytes> ()>::Run() && ( callback.h:154 )
[ 28 ] void base::internal::ReturnAsParamAdapter<scoped_refptr<base::RefCountedBytes>>(base::OnceCallback<scoped_refptr<base::RefCountedBytes> ()>, std::__Cr::unique_ptr<scoped_refptr<base::RefCountedBytes>, std::__Cr::default_delete<scoped_refptr<base::RefCountedBytes>>>*) ( post_task_and_reply_with_result_internal.h:23 )
[ 29 ] base::OnceCallback<void ()>::Run() && ( callback.h:154 )
[ 30 ] base::internal::PostTaskAndReplyRelay::RunTaskAndPostReply(base::internal::PostTaskAndReplyRelay) ( post_task_and_reply_impl.h:45 )
[ 31 ] void base::internal::FunctorTraits<void (*)(base::internal::PostTaskAndReplyRelay), void>::Invoke<void (*)(base::internal::PostTaskAndReplyRelay), base::internal::PostTaskAndReplyRelay>(void (*&&)(base::internal::PostTaskAndReplyRelay), base::internal::PostTaskAndReplyRelay&&) ( bind_internal.h:631 )
[ 32 ] void base::internal::InvokeHelper<false, void, 0ul>::MakeItSo<void (*)(base::internal::PostTaskAndReplyRelay), std::__Cr::tuple<base::internal::PostTaskAndReplyRelay>>(void (*&&)(base::internal::PostTaskAndReplyRelay), std::__Cr::tuple<base::internal::PostTaskAndReplyRelay>&&) ( bind_internal.h:868 )
[ 33 ] void base::internal::Invoker<base::internal::BindState<void (*)(base::internal::PostTaskAndReplyRelay), base::internal::PostTaskAndReplyRelay>, void ()>::RunImpl<void (*)(base::internal::PostTaskAndReplyRelay), std::__Cr::tuple<base::internal::PostTaskAndReplyRelay>, 0ul>(void (*&&)(base::internal::PostTaskAndReplyRelay), std::__Cr::tuple<base::internal::PostTaskAndReplyRelay>&&, std::__Cr::integer_sequence<unsigned long, 0ul>) ( bind_internal.h:968 )
[ 34 ] base::internal::Invoker<base::internal::BindState<void (*)(base::internal::PostTaskAndReplyRelay), base::internal::PostTaskAndReplyRelay>, void ()>::RunOnce(base::internal::BindStateBase*) ( bind_internal.h:919 )
[ 35 ] base::TaskAnnotator::RunTaskImpl(base::PendingTask&) ( callback.h:154 )
[ 36 ] void base::TaskAnnotator::RunTask<base::internal::TaskTracker::RunTaskImpl(base::internal::Task&, base::TaskTraits const&, base::internal::TaskSource*, base::SequenceToken const&)::$_0>(perfetto::StaticString, base::PendingTask&, base::internal::TaskTracker::RunTaskImpl(base::internal::Task&, base::TaskTraits const&, base::internal::TaskSource*, base::SequenceToken const&)::$_0&&) ( task_annotator.h:89 )
[ 37 ] base::internal::TaskTracker::RunTaskImpl(base::internal::Task&, base::TaskTraits const&, base::internal::TaskSource*, base::SequenceToken const&) ( task_tracker.cc:644 )
[ 38 ] base::internal::TaskTracker::RunSkipOnShutdown(base::internal::Task&, base::TaskTraits const&, base::internal::TaskSource*, base::SequenceToken const&) ( task_tracker.cc:629 )
[ 39 ] base::internal::WorkerThread::RunWorker() ( task_tracker.cc:659 )
[ 40 ] base::internal::WorkerThread::RunPooledWorker() ( worker_thread.cc:359 )
[ 41 ] base::internal::WorkerThread::ThreadMain() ( worker_thread.cc:339 )
[ 42 ] base::(anonymous namespace)::ThreadFunc(void*) ( platform_thread_posix.cc:101 )
[ 43 ] _pthread_start
[ 44 ] thread_start
Expected result:
No crash
Reproduces how often:
100% with: multiple large files, at least stored for offline, media playing, and switching betweeen them
Brave version (brave://version info)
Brave | 1.62.89 Chromium: 120.0.6099.35 (Official Build) nightly (x86_64)
-- | --
Revision | f68a18538c0af7dba0f91c6176be4c1eee17101c
OS | macOS Version 11.7.10 (Build 20G1427)
Version/Channel Information:
- Can you reproduce this issue with the current release?
- Can you reproduce this issue with the beta channel?
- Can you reproduce this issue with the nightly channel?
Other Additional Information:
- Does the issue resolve itself when disabling Brave Shields?
- Does the issue resolve itself when disabling Brave Rewards?
- Is the issue reproducible on the latest version of Chrome?
Miscellaneous Information:
About this issue
- Original URL
- State: closed
- Created 7 months ago
- Comments: 20 (3 by maintainers)
Yay, I think we’re close to it. Succeeded in playing 24hr long video
Yes, that’s right.
That’s…pretty “reasonable.”
😆 - nice work as always!
it might not be allowed due to the CSP.
Also this seems to be difficult without explicit user interaction via
<input type=filefor security/privacy reason.So, not sure if it works, but I guess we should do something like from
PlaylistDataSourcechrome://playlist-data/{id}/media/should return the size of chunks and media typeUpdate:
It seems that Youtube videos(mp4) we caches are not in format that can be used for MediaSource. So I’m going to try gather chunks into byte array(not MediaSource’s source buffer), and set it to video tag’s src attribute.
Even if the byte array causes OOM, only renderer would crash. I think that’s better. But eventually, we’ll need to work on caching MediaSource object as is.
Just curious why we don’t play with local media file path and instead passing it via string? It’s bcause ofNVM Data source should pass that file’s data 😃 As we’re using customchrome-untrusted://?chrome-untrusted://playlist-data/...url for playlist data, we have its own data source.I think it’s worth to investigate how file:// scheme load big size media file. Maybe loading url something like
/Users/simon/Library/ApplicationSupport/BraveSoftware/Brave-Browser-Beta//Default/playlist/60A2BE63931C52698229F7F0C430D243/media_file.mp4in omnibox will play it well?Or how about trying local file path instead of custom media path if it’s possible from untrusted webui?