* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ohos.ace.plugin.avmetadatahelperplugin;
import android.content.Context;
import android.media.MediaDataSource;
import android.media.MediaMetadataRetriever;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import ohos.ace.adapter.ALog;
* AVMetadataHelperPlugin
*
* @since 1
*/
public class AVMetadataHelperPlugin {
* nativeInit is used to initialize the native library.
*/
private static final String LOG_TAG = "AVMetadataHelperPlugin";
* HELPER_STATE_ERROR is used to indicate the state of the helper is error.
*/
public static final int HELPER_STATE_ERROR = 0;
* HELPER_IDLE is used to indicate the state of the helper is idle.
*/
public static final int HELPER_IDLE = 1;
* HELPER_PREPARING is used to indicate the state of the helper is preparing.
*/
public static final int HELPER_PREPARED = 2;
* HELPER_CALL_DONE is used to indicate the call is done.
*/
public static final int HELPER_CALL_DONE = 3;
* HELPER_RELEASED is used to indicate the state of the helper is released.
*/
public static final int HELPER_RELEASED = 4;
private Map<Long, MediaMetadataRetriever> metadataRetrieverMap = new HashMap<>();
private Map<Long, MediaDataSourceImpl> dataSourceMap = new HashMap<>();
* AVMetadataHelperPlugin
*
* @param context context of the application
*/
public AVMetadataHelperPlugin(Context context) {
if (context == null) {
ALog.e(LOG_TAG, "context is null");
return;
}
nativeInit();
}
* MediaDataSourceImpl
*
* The class is used for getting the data source.
* @since 1
*/
public class MediaDataSourceImpl extends MediaDataSource {
private long key;
public MediaDataSourceImpl(long id) {
key = id;
}
@Override
public long getSize() {
return -1;
}
@Override
public int readAt(long position, byte[] buffer, int offset, int size) {
return nativeReadAt(key, position, buffer, offset, size);
}
@Override
public void close() {
}
};
private class CallbackThread extends Thread {
private long id;
private int state;
@Override
public void run() {
nativeOnStateChanged(id, state);
}
public void setParams(long key, int info) {
id = key;
state = info;
}
}
* creates a MediaMetadataRetriever object.
*
* @param key The key of the MediaMetadataRetriever.
*/
public void createMetadataRetriever(long key) {
MediaMetadataRetriever metadataRetriever = metadataRetrieverMap.get(key);
if (metadataRetriever != null) {
ALog.e(LOG_TAG, "createMetadataRetriever metadataRetriever exist.");
return;
}
metadataRetriever = new MediaMetadataRetriever();
metadataRetrieverMap.put(key, metadataRetriever);
notifyInfo(key, HELPER_IDLE);
}
private void notifyInfo(long key, int info) {
CallbackThread td = new CallbackThread();
td.setParams(key, info);
td.start();
}
* releases a MediaMetadataRetriever object.
*
* @param key The key of the MediaMetadataRetriever.
*/
public void releaseMetadataRetriever(long key) {
metadataRetrieverMap.remove(key);
}
* Sets the data source (FileDescriptor) to use.
*
* @param key The key of the MediaMetadataRetriever.
* @param url the url for the file you want to play.
* @param offset the offset into the file where the data to be played starts, in bytes. It must be non-negative
* @param size the length in bytes of the data to be played. The negative value is invalid.
*/
public void setDataSource(long key, String url, long offset, long size) {
MediaMetadataRetriever metadataRetriever = metadataRetrieverMap.get(key);
if (metadataRetriever == null) {
ALog.e("LOG_TAG", "MediaMetadataRetriever is not created, setDataSource(fd).");
return;
}
try {
if (size <= 0) {
File file = new File(url);
size = file.length();
}
FileInputStream fs = new FileInputStream(url);
metadataRetriever.setDataSource(fs.getFD(), offset, size);
notifyInfo(key, HELPER_PREPARED);
} catch (IOException ex) {
ALog.e(LOG_TAG, "setDataSource IOException:" + ex.getMessage());
}
}
* Sets the data source (file pathname) to use.
*
* @param key The key of the MediaMetadataRetriever.
*/
public void setDataSource(long key) {
MediaMetadataRetriever metadataRetriever = metadataRetrieverMap.get(key);
if (metadataRetriever == null) {
ALog.e("LOG_TAG", "MediaMetadataRetriever is not created, setDataSource(dataSource).");
return;
}
MediaDataSourceImpl dataSource = new MediaDataSourceImpl(key);
dataSourceMap.put(key, dataSource);
metadataRetriever.setDataSource(dataSource);
notifyInfo(key, HELPER_PREPARED);
}
* Retrieves the meta data value associated with the keyCode.
*
* @param key The key of the MediaMetadataRetriever.
* @param keyCode The key of metadata.
*/
public String extractMetadata(long key, int keyCode) {
MediaMetadataRetriever metadataRetriever = metadataRetrieverMap.get(key);
if (metadataRetriever == null) {
ALog.e("LOG_TAG", "MediaMetadataRetriever is not created, extractMetadata.");
return "";
}
String ret = metadataRetriever.extractMetadata(keyCode);
return ret == null ? "" : ret;
}
* Retrieves the optional graphic or album/cover art associated associated with the data source.
*
* @param key The key of the MediaMetadataRetriever.
*/
public void extractMetadataDone(long key) {
notifyInfo(key, HELPER_CALL_DONE);
}
* Retrieves the optional graphic or album/cover art associated associated with the data source.
*
* @param key The key of the MediaMetadataRetriever.
* @return The size of the embedded picture.
*/
public int getEmbeddedPictureSize(long key) {
MediaMetadataRetriever metadataRetriever = metadataRetrieverMap.get(key);
if (metadataRetriever == null) {
ALog.e("LOG_TAG", "MediaMetadataRetriever is not created, getEmbeddedPicture.");
return -1;
}
byte[] pic = metadataRetriever.getEmbeddedPicture();
if (pic == null) {
notifyInfo(key, HELPER_CALL_DONE);
return -1;
} else {
return pic.length;
}
}
* Finds the optional graphic or album/cover art associated associated with the data source..
*
* @param key The key of the MediaMetadataRetriever.
*/
public byte[] getEmbeddedPicture(long key) {
MediaMetadataRetriever metadataRetriever = metadataRetrieverMap.get(key);
if (metadataRetriever == null) {
ALog.e("LOG_TAG", "MediaMetadataRetriever is not created, getEmbeddedPicture.");
return null;
}
notifyInfo(key, HELPER_CALL_DONE);
return metadataRetriever.getEmbeddedPicture();
}
* releases a MediaMetadataRetriever object.
*
* @param key The key of the MediaMetadataRetriever.
*/
public void release(long key) {
MediaMetadataRetriever metadataRetriever = metadataRetrieverMap.get(key);
if (metadataRetriever == null) {
ALog.e("LOG_TAG", "MediaMetadataRetriever is not created, release.");
return;
}
metadataRetriever.release();
notifyInfo(key, HELPER_RELEASED);
}
* Init AVMetadataHelperPlugin jni.
*
*/
protected native void nativeInit();
* Read the media data source.
*
* @param key The key of the MediaMetadataRetriever.
* @param position The position in the data source to read from.
* @param buffer The buffer to read the data into.
* @param offset The offset within buffer to read the data into.
* @param size The number of bytes to read.
* @return int The number of bytes read, or -1 if end of stream is reached.
*/
protected native int nativeReadAt(long key, long position, byte[] buffer, int offset, int size);
* Notify the state of MediaMetadataRetriever changed.
*
* @param key The key of the MediaMetadataRetriever.
* @param state The state of the MediaMetadataRetriever.
* @return void.
*/
protected native void nativeOnStateChanged(long key, int state);
}