OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2009 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 #include "base/string_util.h" |
| 6 #include "media/base/filters.h" |
| 7 #include "media/filters/ffmpeg_common.h" |
| 8 #include "media/filters/ffmpeg_glue.h" |
| 9 |
| 10 namespace { |
| 11 |
| 12 // FFmpeg protocol interface. |
| 13 int OpenContext(URLContext* h, const char* filename, int flags) { |
| 14 scoped_refptr<media::DataSource> data_source; |
| 15 media::FFmpegGlue::get()->GetDataSource(filename, &data_source); |
| 16 if (!data_source) |
| 17 return AVERROR_IO; |
| 18 |
| 19 data_source->AddRef(); |
| 20 h->priv_data = data_source; |
| 21 h->flags = URL_RDONLY; |
| 22 // TODO(scherkus): data source should be able to tell us if we're streaming. |
| 23 h->is_streamed = FALSE; |
| 24 return 0; |
| 25 } |
| 26 |
| 27 int ReadContext(URLContext* h, unsigned char* buf, int size) { |
| 28 media::DataSource* data_source = |
| 29 reinterpret_cast<media::DataSource*>(h->priv_data); |
| 30 int result = data_source->Read(buf, size); |
| 31 if (result < 0) |
| 32 result = AVERROR_IO; |
| 33 return result; |
| 34 } |
| 35 |
| 36 int WriteContext(URLContext* h, unsigned char* buf, int size) { |
| 37 // We don't support writing. |
| 38 return AVERROR_IO; |
| 39 } |
| 40 |
| 41 offset_t SeekContext(URLContext* h, offset_t offset, int whence) { |
| 42 media::DataSource* data_source = |
| 43 reinterpret_cast<media::DataSource*>(h->priv_data); |
| 44 offset_t new_offset = AVERROR_IO; |
| 45 switch (whence) { |
| 46 case SEEK_SET: |
| 47 if (data_source->SetPosition(offset)) |
| 48 data_source->GetPosition(&new_offset); |
| 49 break; |
| 50 |
| 51 case SEEK_CUR: |
| 52 int64 pos; |
| 53 if (!data_source->GetPosition(&pos)) |
| 54 break; |
| 55 if (data_source->SetPosition(pos + offset)) |
| 56 data_source->GetPosition(&new_offset); |
| 57 break; |
| 58 |
| 59 case SEEK_END: |
| 60 int64 size; |
| 61 if (!data_source->GetSize(&size)) |
| 62 break; |
| 63 if (data_source->SetPosition(size + offset)) |
| 64 data_source->GetPosition(&new_offset); |
| 65 break; |
| 66 |
| 67 case AVSEEK_SIZE: |
| 68 data_source->GetSize(&new_offset); |
| 69 break; |
| 70 |
| 71 default: |
| 72 NOTREACHED(); |
| 73 } |
| 74 if (new_offset < 0) |
| 75 new_offset = AVERROR_IO; |
| 76 return new_offset; |
| 77 } |
| 78 |
| 79 int CloseContext(URLContext* h) { |
| 80 media::DataSource* data_source = |
| 81 reinterpret_cast<media::DataSource*>(h->priv_data); |
| 82 data_source->Release(); |
| 83 h->priv_data = NULL; |
| 84 return 0; |
| 85 } |
| 86 |
| 87 } // namespace |
| 88 |
| 89 //------------------------------------------------------------------------------ |
| 90 |
| 91 namespace media { |
| 92 |
| 93 // Use the HTTP protocol to avoid any file path separator issues. |
| 94 static const char kProtocol[] = "http"; |
| 95 |
| 96 // Fill out our FFmpeg protocol definition. |
| 97 static URLProtocol kFFmpegProtocol = { |
| 98 kProtocol, |
| 99 &OpenContext, |
| 100 &ReadContext, |
| 101 &WriteContext, |
| 102 &SeekContext, |
| 103 &CloseContext, |
| 104 }; |
| 105 |
| 106 FFmpegGlue::FFmpegGlue() { |
| 107 // Register our protocol glue code with FFmpeg. |
| 108 avcodec_init(); |
| 109 register_protocol(&kFFmpegProtocol); |
| 110 |
| 111 // Now register the rest of FFmpeg. |
| 112 av_register_all(); |
| 113 } |
| 114 |
| 115 FFmpegGlue::~FFmpegGlue() { |
| 116 DataSourceMap::iterator iter = data_sources_.begin(); |
| 117 while (iter != data_sources_.end()) { |
| 118 DataSource* data_source = iter->second; |
| 119 iter = data_sources_.erase(iter); |
| 120 } |
| 121 } |
| 122 |
| 123 std::string FFmpegGlue::AddDataSource(DataSource* data_source) { |
| 124 AutoLock auto_lock(lock_); |
| 125 std::string key = GetDataSourceKey(data_source); |
| 126 if (data_sources_.find(key) == data_sources_.end()) { |
| 127 data_sources_[key] = data_source; |
| 128 } |
| 129 return key; |
| 130 } |
| 131 |
| 132 void FFmpegGlue::RemoveDataSource(DataSource* data_source) { |
| 133 AutoLock auto_lock(lock_); |
| 134 DataSourceMap::iterator iter = data_sources_.begin(); |
| 135 while (iter != data_sources_.end()) { |
| 136 if (iter->second == data_source) { |
| 137 iter = data_sources_.erase(iter); |
| 138 } else { |
| 139 ++iter; |
| 140 } |
| 141 } |
| 142 } |
| 143 |
| 144 void FFmpegGlue::GetDataSource(const std::string& key, |
| 145 scoped_refptr<DataSource>* data_source) { |
| 146 AutoLock auto_lock(lock_); |
| 147 DataSourceMap::iterator iter = data_sources_.find(key); |
| 148 if (iter == data_sources_.end()) { |
| 149 *data_source = NULL; |
| 150 return; |
| 151 } |
| 152 *data_source = iter->second; |
| 153 } |
| 154 |
| 155 std::string FFmpegGlue::GetDataSourceKey(DataSource* data_source) { |
| 156 // Use the DataSource's memory address to generate the unique string. This |
| 157 // also has the nice property that adding the same DataSource reference will |
| 158 // not generate duplicate entries. |
| 159 return StringPrintf("%s://0x%lx", kProtocol, static_cast<void*>(data_source)); |
| 160 } |
| 161 |
| 162 } // namespace media |
OLD | NEW |