Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(60)

Side by Side Diff: media/filters/ffmpeg_demuxer.cc

Issue 1735003004: Implement reading of media track info from WebM and MP4 containers (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@demuxer-tracks2
Patch Set: rebase Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « media/BUILD.gn ('k') | media/filters/ffmpeg_demuxer_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "media/filters/ffmpeg_demuxer.h" 5 #include "media/filters/ffmpeg_demuxer.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <utility> 8 #include <utility>
9 9
10 #include "base/base64.h" 10 #include "base/base64.h"
11 #include "base/bind.h" 11 #include "base/bind.h"
12 #include "base/callback_helpers.h" 12 #include "base/callback_helpers.h"
13 #include "base/macros.h" 13 #include "base/macros.h"
14 #include "base/memory/scoped_ptr.h" 14 #include "base/memory/scoped_ptr.h"
15 #include "base/metrics/histogram_macros.h" 15 #include "base/metrics/histogram_macros.h"
16 #include "base/metrics/sparse_histogram.h" 16 #include "base/metrics/sparse_histogram.h"
17 #include "base/single_thread_task_runner.h" 17 #include "base/single_thread_task_runner.h"
18 #include "base/strings/string_number_conversions.h" 18 #include "base/strings/string_number_conversions.h"
19 #include "base/strings/string_util.h" 19 #include "base/strings/string_util.h"
20 #include "base/strings/stringprintf.h" 20 #include "base/strings/stringprintf.h"
21 #include "base/sys_byteorder.h" 21 #include "base/sys_byteorder.h"
22 #include "base/task_runner_util.h" 22 #include "base/task_runner_util.h"
23 #include "base/thread_task_runner_handle.h" 23 #include "base/thread_task_runner_handle.h"
24 #include "base/time/time.h" 24 #include "base/time/time.h"
25 #include "media/audio/sample_rates.h" 25 #include "media/audio/sample_rates.h"
26 #include "media/base/bind_to_current_loop.h" 26 #include "media/base/bind_to_current_loop.h"
27 #include "media/base/decrypt_config.h" 27 #include "media/base/decrypt_config.h"
28 #include "media/base/limits.h" 28 #include "media/base/limits.h"
29 #include "media/base/media_log.h" 29 #include "media/base/media_log.h"
30 #include "media/base/media_tracks.h"
30 #include "media/base/timestamp_constants.h" 31 #include "media/base/timestamp_constants.h"
31 #include "media/ffmpeg/ffmpeg_common.h" 32 #include "media/ffmpeg/ffmpeg_common.h"
32 #include "media/filters/ffmpeg_aac_bitstream_converter.h" 33 #include "media/filters/ffmpeg_aac_bitstream_converter.h"
33 #include "media/filters/ffmpeg_bitstream_converter.h" 34 #include "media/filters/ffmpeg_bitstream_converter.h"
34 #include "media/filters/ffmpeg_glue.h" 35 #include "media/filters/ffmpeg_glue.h"
35 #include "media/filters/ffmpeg_h264_to_annex_b_bitstream_converter.h" 36 #include "media/filters/ffmpeg_h264_to_annex_b_bitstream_converter.h"
36 #include "media/filters/webvtt_util.h" 37 #include "media/filters/webvtt_util.h"
37 #include "media/formats/webm/webm_crypto_helpers.h" 38 #include "media/formats/webm/webm_crypto_helpers.h"
38 #include "media/media_features.h" 39 #include "media/media_features.h"
39 40
(...skipping 1042 matching lines...) Expand 10 before | Expand all | Expand 10 after
1082 if (packet_buffer->pkt.pts != static_cast<int64_t>(AV_NOPTS_VALUE)) { 1083 if (packet_buffer->pkt.pts != static_cast<int64_t>(AV_NOPTS_VALUE)) {
1083 const base::TimeDelta packet_pts = 1084 const base::TimeDelta packet_pts =
1084 ConvertFromTimeBase(stream->time_base, packet_buffer->pkt.pts); 1085 ConvertFromTimeBase(stream->time_base, packet_buffer->pkt.pts);
1085 if (packet_pts < start_time_estimates[stream->index]) 1086 if (packet_pts < start_time_estimates[stream->index])
1086 start_time_estimates[stream->index] = packet_pts; 1087 start_time_estimates[stream->index] = packet_pts;
1087 } 1088 }
1088 packet_buffer = packet_buffer->next; 1089 packet_buffer = packet_buffer->next;
1089 } 1090 }
1090 } 1091 }
1091 1092
1093 scoped_ptr<MediaTracks> media_tracks(new MediaTracks());
1092 AVStream* audio_stream = NULL; 1094 AVStream* audio_stream = NULL;
1093 AudioDecoderConfig audio_config; 1095 AudioDecoderConfig audio_config;
1094 AVStream* video_stream = NULL; 1096 AVStream* video_stream = NULL;
1095 VideoDecoderConfig video_config; 1097 VideoDecoderConfig video_config;
1096 1098
1097 // If available, |start_time_| will be set to the lowest stream start time. 1099 // If available, |start_time_| will be set to the lowest stream start time.
1098 start_time_ = kInfiniteDuration(); 1100 start_time_ = kInfiniteDuration();
1099 1101
1100 base::TimeDelta max_duration; 1102 base::TimeDelta max_duration;
1101 for (size_t i = 0; i < format_context->nb_streams; ++i) { 1103 for (size_t i = 0; i < format_context->nb_streams; ++i) {
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
1151 // things like: codec, channel layout, sample/pixel format, etc... 1153 // things like: codec, channel layout, sample/pixel format, etc...
1152 scoped_ptr<FFmpegDemuxerStream> demuxer_stream = 1154 scoped_ptr<FFmpegDemuxerStream> demuxer_stream =
1153 FFmpegDemuxerStream::Create(this, stream, media_log_); 1155 FFmpegDemuxerStream::Create(this, stream, media_log_);
1154 if (demuxer_stream.get()) { 1156 if (demuxer_stream.get()) {
1155 streams_[i] = demuxer_stream.release(); 1157 streams_[i] = demuxer_stream.release();
1156 } else { 1158 } else {
1157 // This AVStream does not successfully convert. 1159 // This AVStream does not successfully convert.
1158 continue; 1160 continue;
1159 } 1161 }
1160 1162
1163 std::string track_id = base::IntToString(stream->id);
1164 std::string track_label = streams_[i]->GetMetadata("handler_name");
1165 std::string track_language = streams_[i]->GetMetadata("language");
1166
1167 // Some metadata is named differently in FFmpeg for webm files.
1168 if (strstr(format_context->iformat->name, "webm") ||
1169 strstr(format_context->iformat->name, "matroska")) {
1170 // TODO(servolk): FFmpeg doesn't set stream->id correctly for webm files.
1171 // Need to fix that and use it as track id. crbug.com/323183
1172 track_id = base::UintToString(media_tracks->tracks().size() + 1);
1173 track_label = streams_[i]->GetMetadata("title");
1174 }
1175
1161 // Note when we find our audio/video stream (we only want one of each) and 1176 // Note when we find our audio/video stream (we only want one of each) and
1162 // record src= playback UMA stats for the stream's decoder config. 1177 // record src= playback UMA stats for the stream's decoder config.
1163 if (codec_type == AVMEDIA_TYPE_AUDIO) { 1178 if (codec_type == AVMEDIA_TYPE_AUDIO) {
1164 CHECK(!audio_stream); 1179 CHECK(!audio_stream);
1165 audio_stream = stream; 1180 audio_stream = stream;
1166 audio_config = streams_[i]->audio_decoder_config(); 1181 audio_config = streams_[i]->audio_decoder_config();
1167 RecordAudioCodecStats(audio_config); 1182 RecordAudioCodecStats(audio_config);
1183
1184 media_tracks->AddAudioTrack(audio_config, track_id, "main", track_label,
1185 track_language);
1168 } else if (codec_type == AVMEDIA_TYPE_VIDEO) { 1186 } else if (codec_type == AVMEDIA_TYPE_VIDEO) {
1169 CHECK(!video_stream); 1187 CHECK(!video_stream);
1170 video_stream = stream; 1188 video_stream = stream;
1171 video_config = streams_[i]->video_decoder_config(); 1189 video_config = streams_[i]->video_decoder_config();
1172 RecordVideoCodecStats(video_config, stream->codec->color_range); 1190 RecordVideoCodecStats(video_config, stream->codec->color_range);
1191
1192 media_tracks->AddVideoTrack(video_config, track_id, "main", track_label,
1193 track_language);
1173 } 1194 }
1174 1195
1175 max_duration = std::max(max_duration, streams_[i]->duration()); 1196 max_duration = std::max(max_duration, streams_[i]->duration());
1176 1197
1177 const base::TimeDelta start_time = 1198 const base::TimeDelta start_time =
1178 ExtractStartTime(stream, start_time_estimates[i]); 1199 ExtractStartTime(stream, start_time_estimates[i]);
1179 const bool has_start_time = start_time != kNoTimestamp(); 1200 const bool has_start_time = start_time != kNoTimestamp();
1180 1201
1181 // Always prefer the video stream for seeking. If none exists, we'll swap 1202 // Always prefer the video stream for seeking. If none exists, we'll swap
1182 // the fallback stream with the preferred stream below. 1203 // the fallback stream with the preferred stream below.
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
1333 media_log_->SetBooleanProperty("video_is_encrypted", 1354 media_log_->SetBooleanProperty("video_is_encrypted",
1334 video_config.is_encrypted()); 1355 video_config.is_encrypted());
1335 } else { 1356 } else {
1336 media_log_->SetBooleanProperty("found_video_stream", false); 1357 media_log_->SetBooleanProperty("found_video_stream", false);
1337 } 1358 }
1338 1359
1339 media_log_->SetTimeProperty("max_duration", max_duration); 1360 media_log_->SetTimeProperty("max_duration", max_duration);
1340 media_log_->SetTimeProperty("start_time", start_time_); 1361 media_log_->SetTimeProperty("start_time", start_time_);
1341 media_log_->SetIntegerProperty("bitrate", bitrate_); 1362 media_log_->SetIntegerProperty("bitrate", bitrate_);
1342 1363
1364 media_tracks_updated_cb_.Run(std::move(media_tracks));
1365
1343 status_cb.Run(PIPELINE_OK); 1366 status_cb.Run(PIPELINE_OK);
1344 } 1367 }
1345 1368
1346 void FFmpegDemuxer::OnSeekFrameDone(const PipelineStatusCB& cb, int result) { 1369 void FFmpegDemuxer::OnSeekFrameDone(const PipelineStatusCB& cb, int result) {
1347 DCHECK(task_runner_->BelongsToCurrentThread()); 1370 DCHECK(task_runner_->BelongsToCurrentThread());
1348 CHECK(pending_seek_); 1371 CHECK(pending_seek_);
1349 pending_seek_ = false; 1372 pending_seek_ = false;
1350 1373
1351 if (!blocking_thread_.IsRunning()) { 1374 if (!blocking_thread_.IsRunning()) {
1352 MEDIA_LOG(ERROR, media_log_) << GetDisplayName() << ": bad state"; 1375 MEDIA_LOG(ERROR, media_log_) << GetDisplayName() << ": bad state";
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
1515 1538
1516 void FFmpegDemuxer::SetLiveness(DemuxerStream::Liveness liveness) { 1539 void FFmpegDemuxer::SetLiveness(DemuxerStream::Liveness liveness) {
1517 DCHECK(task_runner_->BelongsToCurrentThread()); 1540 DCHECK(task_runner_->BelongsToCurrentThread());
1518 for (const auto& stream : streams_) { // |stream| is a ref to a pointer. 1541 for (const auto& stream : streams_) { // |stream| is a ref to a pointer.
1519 if (stream) 1542 if (stream)
1520 stream->SetLiveness(liveness); 1543 stream->SetLiveness(liveness);
1521 } 1544 }
1522 } 1545 }
1523 1546
1524 } // namespace media 1547 } // namespace media
OLDNEW
« no previous file with comments | « media/BUILD.gn ('k') | media/filters/ffmpeg_demuxer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698