1 // Copyright 2013 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.
5 #include "media/base/media_file_checker.h"
10 #include "base/time/time.h"
11 #include "media/ffmpeg/ffmpeg_common.h"
12 #include "media/filters/blocking_url_protocol.h"
13 #include "media/filters/ffmpeg_glue.h"
14 #include "media/filters/file_data_source.h"
18 static const int64 kMaxCheckTimeInSeconds
= 5;
20 static void OnError(bool* called
) {
24 MediaFileChecker::MediaFileChecker(const base::PlatformFile
& file
)
26 file_closer_(&file_
) {
29 MediaFileChecker::~MediaFileChecker() {
32 bool MediaFileChecker::Start(base::TimeDelta check_time
) {
33 media::FileDataSource source
;
35 media::BlockingUrlProtocol
protocol(&source
, base::Bind(&OnError
, &read_ok
));
36 media::FFmpegGlue
glue(&protocol
);
37 source
.InitializeFromPlatformFile(file_
);
38 AVFormatContext
* format_context
= glue
.format_context();
40 if (!glue
.OpenContext())
43 if (avformat_find_stream_info(format_context
, NULL
) < 0)
46 // Remember the codec context for any decodable audio or video streams.
47 std::map
<int, AVCodecContext
*> stream_contexts
;
48 for (size_t i
= 0; i
< format_context
->nb_streams
; ++i
) {
49 AVCodecContext
* c
= format_context
->streams
[i
]->codec
;
50 if (c
->codec_type
== AVMEDIA_TYPE_AUDIO
||
51 c
->codec_type
== AVMEDIA_TYPE_VIDEO
) {
52 AVCodec
* codec
= avcodec_find_decoder(c
->codec_id
);
53 if (codec
&& avcodec_open2(c
, codec
, NULL
) >= 0)
54 stream_contexts
[i
] = c
;
58 if (stream_contexts
.size() == 0)
62 scoped_ptr_malloc
<AVFrame
, media::ScopedPtrAVFreeFrame
> frame(
63 avcodec_alloc_frame());
66 base::Time deadline
= base::Time::Now() +
68 base::TimeDelta::FromSeconds(kMaxCheckTimeInSeconds
));
70 result
= av_read_frame(glue
.format_context(), &packet
);
73 result
= av_dup_packet(&packet
);
77 std::map
<int, AVCodecContext
*>::const_iterator it
=
78 stream_contexts
.find(packet
.stream_index
);
79 if (it
== stream_contexts
.end()) {
80 av_free_packet(&packet
);
83 AVCodecContext
* av_context
= it
->second
;
85 int frame_decoded
= 0;
86 if (av_context
->codec_type
== AVMEDIA_TYPE_AUDIO
) {
87 // A shallow copy of packet so we can slide packet.data as frames are
88 // decoded; otherwise av_free_packet() will corrupt memory.
89 AVPacket temp_packet
= packet
;
91 avcodec_get_frame_defaults(frame
.get());
92 result
= avcodec_decode_audio4(av_context
, frame
.get(), &frame_decoded
,
96 temp_packet
.size
-= result
;
97 temp_packet
.data
+= result
;
98 } while (temp_packet
.size
> 0);
99 } else if (av_context
->codec_type
== AVMEDIA_TYPE_VIDEO
) {
100 avcodec_get_frame_defaults(frame
.get());
101 result
= avcodec_decode_video2(av_context
, frame
.get(), &frame_decoded
,
104 av_free_packet(&packet
);
105 } while (base::Time::Now() < deadline
&& read_ok
&& result
>= 0);
107 return read_ok
&& (result
== AVERROR_EOF
|| result
>= 0);