OLD | NEW |
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_video_decoder.h" | 5 #include "media/filters/ffmpeg_video_decoder.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 #include <stdint.h> | 8 #include <stdint.h> |
9 | 9 |
10 #include <algorithm> | 10 #include <algorithm> |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
204 void FFmpegVideoDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer, | 204 void FFmpegVideoDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer, |
205 const DecodeCB& decode_cb) { | 205 const DecodeCB& decode_cb) { |
206 DCHECK(thread_checker_.CalledOnValidThread()); | 206 DCHECK(thread_checker_.CalledOnValidThread()); |
207 DCHECK(buffer.get()); | 207 DCHECK(buffer.get()); |
208 DCHECK(!decode_cb.is_null()); | 208 DCHECK(!decode_cb.is_null()); |
209 CHECK_NE(state_, kUninitialized); | 209 CHECK_NE(state_, kUninitialized); |
210 | 210 |
211 DecodeCB decode_cb_bound = BindToCurrentLoop(decode_cb); | 211 DecodeCB decode_cb_bound = BindToCurrentLoop(decode_cb); |
212 | 212 |
213 if (state_ == kError) { | 213 if (state_ == kError) { |
214 decode_cb_bound.Run(kDecodeError); | 214 decode_cb_bound.Run(DecodeStatus::DECODE_ERROR); |
215 return; | 215 return; |
216 } | 216 } |
217 | 217 |
218 if (state_ == kDecodeFinished) { | 218 if (state_ == kDecodeFinished) { |
219 decode_cb_bound.Run(kOk); | 219 decode_cb_bound.Run(DecodeStatus::OK); |
220 return; | 220 return; |
221 } | 221 } |
222 | 222 |
223 DCHECK_EQ(state_, kNormal); | 223 DCHECK_EQ(state_, kNormal); |
224 | 224 |
225 // During decode, because reads are issued asynchronously, it is possible to | 225 // During decode, because reads are issued asynchronously, it is possible to |
226 // receive multiple end of stream buffers since each decode is acked. When the | 226 // receive multiple end of stream buffers since each decode is acked. When the |
227 // first end of stream buffer is read, FFmpeg may still have frames queued | 227 // first end of stream buffer is read, FFmpeg may still have frames queued |
228 // up in the decoder so we need to go through the decode loop until it stops | 228 // up in the decoder so we need to go through the decode loop until it stops |
229 // giving sensible data. After that, the decoder should output empty | 229 // giving sensible data. After that, the decoder should output empty |
(...skipping 11 matching lines...) Expand all Loading... |
241 // kNormal -> kError: | 241 // kNormal -> kError: |
242 // A decoding error occurs and decoding needs to stop. | 242 // A decoding error occurs and decoding needs to stop. |
243 // (any state) -> kNormal: | 243 // (any state) -> kNormal: |
244 // Any time Reset() is called. | 244 // Any time Reset() is called. |
245 | 245 |
246 bool has_produced_frame; | 246 bool has_produced_frame; |
247 do { | 247 do { |
248 has_produced_frame = false; | 248 has_produced_frame = false; |
249 if (!FFmpegDecode(buffer, &has_produced_frame)) { | 249 if (!FFmpegDecode(buffer, &has_produced_frame)) { |
250 state_ = kError; | 250 state_ = kError; |
251 decode_cb_bound.Run(kDecodeError); | 251 decode_cb_bound.Run(DecodeStatus::DECODE_ERROR); |
252 return; | 252 return; |
253 } | 253 } |
254 // Repeat to flush the decoder after receiving EOS buffer. | 254 // Repeat to flush the decoder after receiving EOS buffer. |
255 } while (buffer->end_of_stream() && has_produced_frame); | 255 } while (buffer->end_of_stream() && has_produced_frame); |
256 | 256 |
257 if (buffer->end_of_stream()) | 257 if (buffer->end_of_stream()) |
258 state_ = kDecodeFinished; | 258 state_ = kDecodeFinished; |
259 | 259 |
260 // VideoDecoderShim expects that |decode_cb| is called only after | 260 // VideoDecoderShim expects that |decode_cb| is called only after |
261 // |output_cb_|. | 261 // |output_cb_|. |
262 decode_cb_bound.Run(kOk); | 262 decode_cb_bound.Run(DecodeStatus::OK); |
263 } | 263 } |
264 | 264 |
265 void FFmpegVideoDecoder::Reset(const base::Closure& closure) { | 265 void FFmpegVideoDecoder::Reset(const base::Closure& closure) { |
266 DCHECK(thread_checker_.CalledOnValidThread()); | 266 DCHECK(thread_checker_.CalledOnValidThread()); |
267 | 267 |
268 avcodec_flush_buffers(codec_context_.get()); | 268 avcodec_flush_buffers(codec_context_.get()); |
269 state_ = kNormal; | 269 state_ = kNormal; |
270 // PostTask() to avoid calling |closure| inmediately. | 270 // PostTask() to avoid calling |closure| inmediately. |
271 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, closure); | 271 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, closure); |
272 } | 272 } |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
374 if (!codec || avcodec_open2(codec_context_.get(), codec, NULL) < 0) { | 374 if (!codec || avcodec_open2(codec_context_.get(), codec, NULL) < 0) { |
375 ReleaseFFmpegResources(); | 375 ReleaseFFmpegResources(); |
376 return false; | 376 return false; |
377 } | 377 } |
378 | 378 |
379 av_frame_.reset(av_frame_alloc()); | 379 av_frame_.reset(av_frame_alloc()); |
380 return true; | 380 return true; |
381 } | 381 } |
382 | 382 |
383 } // namespace media | 383 } // namespace media |
OLD | NEW |