| 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 <algorithm> | 7 #include <algorithm> |
| 8 #include <string> | 8 #include <string> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 151 DCHECK(!demuxer_stream_); | 151 DCHECK(!demuxer_stream_); |
| 152 | 152 |
| 153 if (!stream) { | 153 if (!stream) { |
| 154 status_cb.Run(PIPELINE_ERROR_DECODE); | 154 status_cb.Run(PIPELINE_ERROR_DECODE); |
| 155 return; | 155 return; |
| 156 } | 156 } |
| 157 | 157 |
| 158 demuxer_stream_ = stream; | 158 demuxer_stream_ = stream; |
| 159 statistics_cb_ = statistics_cb; | 159 statistics_cb_ = statistics_cb; |
| 160 | 160 |
| 161 const VideoDecoderConfig& config = stream->video_decoder_config(); | 161 if (!ConfigureDecoder()) { |
| 162 | |
| 163 // TODO(scherkus): this check should go in Pipeline prior to creating | |
| 164 // decoder objects. | |
| 165 if (!config.IsValidConfig()) { | |
| 166 DLOG(ERROR) << "Invalid video stream - " << config.AsHumanReadableString(); | |
| 167 status_cb.Run(PIPELINE_ERROR_DECODE); | |
| 168 return; | |
| 169 } | |
| 170 | |
| 171 // Initialize AVCodecContext structure. | |
| 172 codec_context_ = avcodec_alloc_context3(NULL); | |
| 173 VideoDecoderConfigToAVCodecContext(config, codec_context_); | |
| 174 | |
| 175 // Enable motion vector search (potentially slow), strong deblocking filter | |
| 176 // for damaged macroblocks, and set our error detection sensitivity. | |
| 177 codec_context_->error_concealment = FF_EC_GUESS_MVS | FF_EC_DEBLOCK; | |
| 178 codec_context_->err_recognition = AV_EF_CAREFUL; | |
| 179 codec_context_->thread_count = GetThreadCount(codec_context_->codec_id); | |
| 180 codec_context_->opaque = this; | |
| 181 codec_context_->flags |= CODEC_FLAG_EMU_EDGE; | |
| 182 codec_context_->get_buffer = GetVideoBufferImpl; | |
| 183 codec_context_->release_buffer = ReleaseVideoBufferImpl; | |
| 184 | |
| 185 AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id); | |
| 186 if (!codec) { | |
| 187 status_cb.Run(PIPELINE_ERROR_DECODE); | |
| 188 return; | |
| 189 } | |
| 190 | |
| 191 if (avcodec_open2(codec_context_, codec, NULL) < 0) { | |
| 192 status_cb.Run(PIPELINE_ERROR_DECODE); | 162 status_cb.Run(PIPELINE_ERROR_DECODE); |
| 193 return; | 163 return; |
| 194 } | 164 } |
| 195 | 165 |
| 196 // Success! | 166 // Success! |
| 197 state_ = kNormal; | 167 state_ = kNormal; |
| 198 av_frame_ = avcodec_alloc_frame(); | |
| 199 status_cb.Run(PIPELINE_OK); | 168 status_cb.Run(PIPELINE_OK); |
| 200 } | 169 } |
| 201 | 170 |
| 202 void FFmpegVideoDecoder::Read(const ReadCB& read_cb) { | 171 void FFmpegVideoDecoder::Read(const ReadCB& read_cb) { |
| 203 // Complete operation asynchronously on different stack of execution as per | 172 // Complete operation asynchronously on different stack of execution as per |
| 204 // the API contract of VideoDecoder::Read() | 173 // the API contract of VideoDecoder::Read() |
| 205 message_loop_->PostTask(FROM_HERE, base::Bind( | 174 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 206 &FFmpegVideoDecoder::DoRead, this, read_cb)); | 175 &FFmpegVideoDecoder::DoRead, this, read_cb)); |
| 207 } | 176 } |
| 208 | 177 |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 313 DoStop(); | 282 DoStop(); |
| 314 return; | 283 return; |
| 315 } | 284 } |
| 316 | 285 |
| 317 if (!reset_cb_.is_null()) { | 286 if (!reset_cb_.is_null()) { |
| 318 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); | 287 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); |
| 319 DoReset(); | 288 DoReset(); |
| 320 return; | 289 return; |
| 321 } | 290 } |
| 322 | 291 |
| 323 if (status != DemuxerStream::kOk) { | 292 if (status == DemuxerStream::kAborted) { |
| 324 Status decoder_status = | 293 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); |
| 325 (status == DemuxerStream::kAborted) ? kOk : kDecodeError; | |
| 326 base::ResetAndReturn(&read_cb_).Run(decoder_status, NULL); | |
| 327 return; | 294 return; |
| 328 } | 295 } |
| 329 | 296 |
| 297 if (status == DemuxerStream::kConfigChanged) { |
| 298 if (!ConfigureDecoder()) { |
| 299 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); |
| 300 return; |
| 301 } |
| 302 |
| 303 ReadFromDemuxerStream(); |
| 304 return; |
| 305 } |
| 306 |
| 330 DCHECK_EQ(status, DemuxerStream::kOk); | 307 DCHECK_EQ(status, DemuxerStream::kOk); |
| 331 | 308 |
| 332 if (buffer->GetDecryptConfig() && buffer->GetDataSize()) { | 309 if (buffer->GetDecryptConfig() && buffer->GetDataSize()) { |
| 333 decryptor_->Decrypt(buffer, | 310 decryptor_->Decrypt(buffer, |
| 334 base::Bind(&FFmpegVideoDecoder::BufferDecrypted, this)); | 311 base::Bind(&FFmpegVideoDecoder::BufferDecrypted, this)); |
| 335 return; | 312 return; |
| 336 } | 313 } |
| 337 | 314 |
| 338 DecodeBuffer(buffer); | 315 DecodeBuffer(buffer); |
| 339 } | 316 } |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 517 avcodec_close(codec_context_); | 494 avcodec_close(codec_context_); |
| 518 av_free(codec_context_); | 495 av_free(codec_context_); |
| 519 codec_context_ = NULL; | 496 codec_context_ = NULL; |
| 520 } | 497 } |
| 521 if (av_frame_) { | 498 if (av_frame_) { |
| 522 av_free(av_frame_); | 499 av_free(av_frame_); |
| 523 av_frame_ = NULL; | 500 av_frame_ = NULL; |
| 524 } | 501 } |
| 525 } | 502 } |
| 526 | 503 |
| 504 bool FFmpegVideoDecoder::ConfigureDecoder() { |
| 505 const VideoDecoderConfig& config = demuxer_stream_->video_decoder_config(); |
| 506 |
| 507 if (!config.IsValidConfig()) { |
| 508 DLOG(ERROR) << "Invalid video stream - " << config.AsHumanReadableString(); |
| 509 return false; |
| 510 } |
| 511 |
| 512 // Release existing decoder resources if necessary. |
| 513 ReleaseFFmpegResources(); |
| 514 |
| 515 // Initialize AVCodecContext structure. |
| 516 codec_context_ = avcodec_alloc_context3(NULL); |
| 517 VideoDecoderConfigToAVCodecContext(config, codec_context_); |
| 518 |
| 519 // Enable motion vector search (potentially slow), strong deblocking filter |
| 520 // for damaged macroblocks, and set our error detection sensitivity. |
| 521 codec_context_->error_concealment = FF_EC_GUESS_MVS | FF_EC_DEBLOCK; |
| 522 codec_context_->err_recognition = AV_EF_CAREFUL; |
| 523 codec_context_->thread_count = GetThreadCount(codec_context_->codec_id); |
| 524 codec_context_->opaque = this; |
| 525 codec_context_->flags |= CODEC_FLAG_EMU_EDGE; |
| 526 codec_context_->get_buffer = GetVideoBufferImpl; |
| 527 codec_context_->release_buffer = ReleaseVideoBufferImpl; |
| 528 |
| 529 AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id); |
| 530 if (!codec) |
| 531 return false; |
| 532 |
| 533 if (avcodec_open2(codec_context_, codec, NULL) < 0) |
| 534 return false; |
| 535 |
| 536 av_frame_ = avcodec_alloc_frame(); |
| 537 return true; |
| 538 } |
| 539 |
| 527 } // namespace media | 540 } // namespace media |
| OLD | NEW |