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

Side by Side Diff: media/mf/file_reader_util.cc

Issue 3044019: This tool demonstrates the use of the Media Foundation H.264 decoder as a sta... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 10 years, 4 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 | Annotate | Revision Log
« no previous file with comments | « media/mf/file_reader_util.h ('k') | media/mf/main.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 //
5 // Borrowed from media/tools/omx_test/file_reader_util.cc.
6 // Added some functionalities related to timestamps on packets.
7
8 #include "media/mf/file_reader_util.h"
9
10 #include <algorithm>
11
12 #include "base/scoped_comptr_win.h"
13 #include "base/logging.h"
14 #include "media/ffmpeg/ffmpeg_common.h"
15 #include "media/filters/bitstream_converter.h"
16
17 namespace media {
18
19 //////////////////////////////////////////////////////////////////////////////
20 // FFmpegFileReader
21 FFmpegFileReader::FFmpegFileReader(const std::string& filename)
22 : filename_(filename),
23 format_context_(NULL),
24 codec_context_(NULL),
25 target_stream_(-1),
26 converter_(NULL),
27 end_of_stream_(false) {
28 }
29
30 FFmpegFileReader::~FFmpegFileReader() {
31 if (format_context_)
32 av_close_input_file(format_context_);
33 }
34
35 bool FFmpegFileReader::Initialize() {
36 int result = av_open_input_file(&format_context_, filename_.c_str(),
37 NULL, 0, NULL);
38 if (result < 0) {
39 switch (result) {
40 case AVERROR_NOFMT:
41 LOG(ERROR) << "Error: File format not supported "
42 << filename_;
43 break;
44 default:
45 LOG(ERROR) << "Error: Could not open input for "
46 << filename_ << ": " << result;
47 break;
48 }
49 return false;
50 }
51 if (av_find_stream_info(format_context_) < 0) {
52 LOG(ERROR) << "can't use FFmpeg to parse stream info";
53 return false;
54 }
55
56 for (size_t i = 0; i < format_context_->nb_streams; ++i) {
57 codec_context_ = format_context_->streams[i]->codec;
58
59 // Find the video stream.
60 if (codec_context_->codec_type == CODEC_TYPE_VIDEO) {
61 target_stream_ = i;
62 break;
63 }
64 }
65 if (target_stream_ == -1) {
66 LOG(ERROR) << "no video in the stream";
67 return false;
68 }
69
70 // Initialize the bitstream filter if needed.
71 // TODO(hclam): find a better way to identify mp4 container.
72 if (codec_context_->codec_id == CODEC_ID_H264) {
73 converter_.reset(new media::FFmpegBitstreamConverter(
74 "h264_mp4toannexb", codec_context_));
75 } else if (codec_context_->codec_id == CODEC_ID_MPEG4) {
76 converter_.reset(new media::FFmpegBitstreamConverter(
77 "mpeg4video_es", codec_context_));
78 } else if (codec_context_->codec_id == CODEC_ID_WMV3) {
79 converter_.reset(new media::FFmpegBitstreamConverter(
80 "vc1_asftorcv", codec_context_));
81 } else if (codec_context_->codec_id == CODEC_ID_VC1) {
82 converter_.reset(new media::FFmpegBitstreamConverter(
83 "vc1_asftoannexg", codec_context_));
84 }
85 if (converter_.get() && !converter_->Initialize()) {
86 converter_.reset();
87 LOG(ERROR) << "failed to initialize h264_mp4toannexb filter";
88 return false;
89 }
90 return true;
91 }
92
93 void FFmpegFileReader::Read(uint8** output, int* size) {
94 Read(output, size, NULL, NULL);
95 }
96
97 void FFmpegFileReader::Read(uint8** output, int* size, int64* timestamp,
98 int64* duration) {
99 if (!format_context_ || !codec_context_ || target_stream_ == -1) {
100 *size = 0;
101 *output = NULL;
102 return;
103 }
104 AVPacket packet;
105 bool found = false;
106 while (!found) {
107 int result = av_read_frame(format_context_, &packet);
108 if (result < 0) {
109 *output = NULL;
110 *size = 0;
111 end_of_stream_ = true;
112 return;
113 }
114 if (packet.stream_index == target_stream_) {
115 if (converter_.get() && !converter_->ConvertPacket(&packet)) {
116 LOG(ERROR) << "failed to convert AVPacket";
117 }
118 *output = new uint8[packet.size];
119 if (*output == NULL) {
120 LOG(ERROR) << "Failed to allocate buffer for annex b stream";
121 *size = 0;
122 return;
123 }
124 *size = packet.size;
125 memcpy(*output, packet.data, packet.size);
126 if (duration) {
127 if (packet.duration == 0) {
128 LOG(WARNING) << "Packet duration not known";
129 }
130 // This is in AVCodecContext::time_base units
131 *duration = ConvertFFmpegTimeBaseTo100Ns(packet.duration);
132 }
133 if (timestamp) {
134 if (packet.pts == AV_NOPTS_VALUE) {
135 LOG(ERROR) << "Packet presentation time not known";
136 *timestamp = 0L;
137 } else {
138 // This is in AVCodecContext::time_base units
139 *timestamp = ConvertFFmpegTimeBaseTo100Ns(packet.pts);
140 }
141 }
142 found = true;
143 }
144 av_free_packet(&packet);
145 }
146 }
147
148 bool FFmpegFileReader::GetFrameRate(int* num, int *denom) const {
149 if (!codec_context_)
150 return false;
151
152 // time_base = 1 / frame_rate
153 *denom = codec_context_->time_base.num;
154 *num = codec_context_->time_base.den;
155 if (denom == 0) {
156 *num = 0;
157 return false;
158 }
159 return true;
160 }
161
162 bool FFmpegFileReader::GetWidth(int* width) const {
163 if (!codec_context_)
164 return false;
165 *width = codec_context_->width;
166 return true;
167 }
168
169 bool FFmpegFileReader::GetHeight(int* height) const {
170 if (!codec_context_)
171 return false;
172 *height = codec_context_->height;
173 return true;
174 }
175
176 bool FFmpegFileReader::GetAspectRatio(int* num, int* denom) const {
177 if (!codec_context_)
178 return false;
179 AVRational aspect_ratio = codec_context_->sample_aspect_ratio;
180 if (aspect_ratio.num == 0 || aspect_ratio.den == 0)
181 return false;
182 *num = aspect_ratio.num;
183 *denom = aspect_ratio.den;
184 return true;
185 }
186
187 int64 FFmpegFileReader::ConvertFFmpegTimeBaseTo100Ns(
188 int64 time_base_unit) const {
189 // FFmpeg units after time base conversion seems to be actually given in
190 // milliseconds (instead of seconds...) so we need to multiply it by a factor
191 // of 10,000 to convert it into units compatible with MF.
192 CHECK(codec_context_) << "Codec context needs to be initialized";
193 return time_base_unit * 10000 * codec_context_->time_base.num /
194 codec_context_->time_base.den;
195 }
196
197 } // namespace media
OLDNEW
« no previous file with comments | « media/mf/file_reader_util.h ('k') | media/mf/main.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698