OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. Use of this | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. Use of this |
2 // source code is governed by a BSD-style license that can be found in the | 2 // source code is governed by a BSD-style license that can be found in the |
3 // LICENSE file. | 3 // LICENSE file. |
4 | 4 |
5 #include "media/base/video_frame_impl.h" | 5 #include "media/base/video_frame_impl.h" |
6 #include "media/filters/ffmpeg_common.h" | 6 #include "media/filters/ffmpeg_common.h" |
7 #include "media/filters/ffmpeg_demuxer.h" | 7 #include "media/filters/ffmpeg_demuxer.h" |
8 #include "media/filters/ffmpeg_video_decoder.h" | 8 #include "media/filters/ffmpeg_video_decoder.h" |
9 | 9 |
10 namespace media { | 10 namespace media { |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
80 void FFmpegVideoDecoder::OnDecode(Buffer* buffer) { | 80 void FFmpegVideoDecoder::OnDecode(Buffer* buffer) { |
81 // Check for end of stream. | 81 // Check for end of stream. |
82 // TODO(scherkus): check for end of stream. | 82 // TODO(scherkus): check for end of stream. |
83 | 83 |
84 // Check for discontinuous buffer. If we receive a discontinuous buffer here, | 84 // Check for discontinuous buffer. If we receive a discontinuous buffer here, |
85 // flush the internal buffer of FFmpeg. | 85 // flush the internal buffer of FFmpeg. |
86 if (buffer->IsDiscontinuous()) { | 86 if (buffer->IsDiscontinuous()) { |
87 avcodec_flush_buffers(codec_context_); | 87 avcodec_flush_buffers(codec_context_); |
88 } | 88 } |
89 | 89 |
90 // Queue the incoming timestamp. | |
91 TimeTuple times; | |
92 times.timestamp = buffer->GetTimestamp(); | |
93 times.duration = buffer->GetDuration(); | |
94 time_queue_.push(times); | |
95 | |
96 // Create a packet for input data. | 90 // Create a packet for input data. |
97 // Due to FFmpeg API changes we no longer have const read-only pointers. | 91 // Due to FFmpeg API changes we no longer have const read-only pointers. |
98 AVPacket packet; | 92 AVPacket packet; |
99 av_init_packet(&packet); | 93 av_init_packet(&packet); |
100 packet.data = const_cast<uint8*>(buffer->GetData()); | 94 packet.data = const_cast<uint8*>(buffer->GetData()); |
101 packet.size = buffer->GetDataSize(); | 95 packet.size = buffer->GetDataSize(); |
102 | 96 |
103 // We don't allocate AVFrame on the stack since different versions of FFmpeg | 97 // We don't allocate AVFrame on the stack since different versions of FFmpeg |
104 // may change the size of AVFrame, causing stack corruption. The solution is | 98 // may change the size of AVFrame, causing stack corruption. The solution is |
105 // to let FFmpeg allocate the structure via avcodec_alloc_frame(). | 99 // to let FFmpeg allocate the structure via avcodec_alloc_frame(). |
106 int decoded = 0; | 100 int decoded = 0; |
107 scoped_ptr_malloc<AVFrame, ScopedPtrAVFree> yuv_frame(avcodec_alloc_frame()); | 101 scoped_ptr_malloc<AVFrame, ScopedPtrAVFree> yuv_frame(avcodec_alloc_frame()); |
108 int result = avcodec_decode_video2(codec_context_, yuv_frame.get(), &decoded, | 102 int result = avcodec_decode_video2(codec_context_, yuv_frame.get(), &decoded, |
109 &packet); | 103 &packet); |
110 | 104 |
111 // Log the problem if we can't decode a video frame. | 105 // Log the problem if we can't decode a video frame. |
112 if (result < 0) { | 106 if (result < 0) { |
113 LOG(INFO) << "Error decoding a video frame with timestamp: " | 107 LOG(INFO) << "Error decoding a video frame with timestamp: " |
114 << buffer->GetTimestamp().InMicroseconds() << " us" | 108 << buffer->GetTimestamp().InMicroseconds() << " us" |
115 << " , duration: " | 109 << " , duration: " |
116 << buffer->GetDuration().InMicroseconds() << " us" | 110 << buffer->GetDuration().InMicroseconds() << " us" |
117 << " , packet size: " | 111 << " , packet size: " |
118 << buffer->GetDataSize() << " bytes"; | 112 << buffer->GetDataSize() << " bytes"; |
119 } | 113 } |
120 | 114 |
121 // Check for a decoded frame instead of checking the return value of | 115 // Check for a decoded frame instead of checking the return value of |
122 // avcodec_decode_video(). We don't need to stop the pipeline on | 116 // avcodec_decode_video(). We don't need to stop the pipeline on |
123 // decode errors. | 117 // decode errors. |
124 if (!decoded) | 118 if (decoded == 0) { |
| 119 // Three conditions to meet to declare end of stream for this decoder: |
| 120 // 1. FFmpeg didn't read anything. |
| 121 // 2. FFmpeg didn't output anything. |
| 122 // 3. An end of stream buffer is received. |
| 123 if (result == 0 && buffer->IsEndOfStream()) { |
| 124 // Create an empty video frame and queue it. |
| 125 scoped_refptr<VideoFrame> video_frame; |
| 126 VideoFrameImpl::CreateEmptyFrame(&video_frame); |
| 127 EnqueueResult(video_frame); |
| 128 } |
125 return; | 129 return; |
| 130 } |
| 131 |
| 132 // Queue the incoming timestamp only if we can decode the frame successfully. |
| 133 TimeTuple times; |
| 134 times.timestamp = buffer->GetTimestamp(); |
| 135 times.duration = buffer->GetDuration(); |
| 136 time_queue_.push(times); |
126 | 137 |
127 // J (Motion JPEG) versions of YUV are full range 0..255. | 138 // J (Motion JPEG) versions of YUV are full range 0..255. |
128 // Regular (MPEG) YUV is 16..240. | 139 // Regular (MPEG) YUV is 16..240. |
129 // For now we will ignore the distinction and treat them the same. | 140 // For now we will ignore the distinction and treat them the same. |
130 | 141 |
131 VideoSurface::Format surface_format; | 142 VideoSurface::Format surface_format; |
132 switch (codec_context_->pix_fmt) { | 143 switch (codec_context_->pix_fmt) { |
133 case PIX_FMT_YUV420P: | 144 case PIX_FMT_YUV420P: |
134 case PIX_FMT_YUVJ420P: | 145 case PIX_FMT_YUVJ420P: |
135 surface_format = VideoSurface::YV12; | 146 surface_format = VideoSurface::YV12; |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
197 } | 208 } |
198 DCHECK(bytes_per_line <= source_stride && bytes_per_line <= dest_stride); | 209 DCHECK(bytes_per_line <= source_stride && bytes_per_line <= dest_stride); |
199 for (size_t i = 0; i < copy_lines; ++i) { | 210 for (size_t i = 0; i < copy_lines; ++i) { |
200 memcpy(dest, source, bytes_per_line); | 211 memcpy(dest, source, bytes_per_line); |
201 source += source_stride; | 212 source += source_stride; |
202 dest += dest_stride; | 213 dest += dest_stride; |
203 } | 214 } |
204 } | 215 } |
205 | 216 |
206 } // namespace | 217 } // namespace |
OLD | NEW |