我正在尝试使用android
ndk
来开发简单的decoder
/ player
应用。我使用android
sdk
创建了一个项目,然后我在我的项目目录中创建了一个名为jni的文件夹。
在jni目录中,我创建了一个omx.cpp
文件,我想在其中编写自己的类,从MediaSource
继承Android stagefright
。我还包含了stagefright
个头文件我的项目。我在我的libstagefright.so
文件中使用 dlopen
加载omx.cpp
。
我使用的代码如下:
using android::sp;
namespace android
{
class ImageSource : public MediaSource {
public:
ImageSource(int width, int height, int colorFormat)
: mWidth(width),
mHeight(height),
mColorFormat(colorFormat)
{
}
public:
int mWidth;
int mHeight;
int mColorFormat;
virtual status_t start(MetaData *params = NULL) {}
virtual status_t stop() {}
// Returns the format of the data output by this media source.
virtual sp<MetaData> getFormat() {}
virtual status_t read(
MediaBuffer **buffer, const MediaSource::ReadOptions *options) {
}
/*protected:
virtual ~ImageSource() {}*/
};
void Java_com_exampleomxvideodecoder_MainActivity(JNIEnv *env, jobject obj, jobject surface)
{
void *dlhandle;
dlhandle = dlopen("d:\libstagefright.so", RTLD_NOW);
if (dlhandle == NULL) {
printf("Service Not Found: %s\n", dlerror());
}
int width = 720;
int height = 480;
int colorFormat = 0;
sp<MediaSource> img_source = new ImageSource(width, height, colorFormat);
sp<MetaData> enc_meta = new MetaData;
// enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
// enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
enc_meta->setInt32(kKeyWidth, width);
enc_meta->setInt32(kKeyHeight, height);
enc_meta->setInt32(kKeySampleRate, kFramerate);
enc_meta->setInt32(kKeyBitRate, kVideoBitRate);
enc_meta->setInt32(kKeyStride, width);
enc_meta->setInt32(kKeySliceHeight, height);
enc_meta->setInt32(kKeyIFramesInterval, kIFramesIntervalSec);
enc_meta->setInt32(kKeyColorFormat, colorFormat);
sp<MediaSource> encoder =
OMXCodec::Create(
client.interface(), enc_meta, true, image_source);
sp<MPEG4Writer> writer = new MPEG4Writer("/sdcard/screenshot.mp4");
writer->addSource(encoder);
// you can add an audio source here if you want to encode audio as well
sp<MediaSource> audioEncoder =
OMXCodec::Create(client.interface(), encMetaAudio, true, audioSource);
writer->addSource(audioEncoder);
writer->setMaxFileDuration(kDurationUs);
CHECK_EQ(OK, writer->start());
while (!writer->reachedEOS()) {
fprintf(stderr, ".");
usleep(100000);
}
err = writer->stop();
}
}
我有以下怀疑:
1.在jni
函数中,如果我们创建一些类对象并使用它们来调用say MediaSource
类的函数,或者我们必须创建单独的.cpp和.h文件,这是可以的。如果我们如何使用单独的文件从jni函数调用/引用它。
2.这是制作我们自己的包装类的正确方法,它继承自MediaSource
类,或者还有其他方法。
基本上我想创建一个应用程序,它将.mp4
/ .avi
文件,demux
分开音频/视频,使用android stagefright
解码和渲染/播放它仅OpenMAX
。
如果为来源建议ffmpeg
,请demux
然后如何将其与android
st
agefright
框架集成。
此致
答案 0 :(得分:0)
要回答第一个问题,是,可以在同一个源文件中定义class
,并在下面的函数中对其进行实例化。我认为这样一个实现的最佳示例可能是DummySource
实用程序的recordVideo
,可以在cmds
目录中找到。
但是,您的文件应直接或间接包含MediaSource.h
文件,如前面的示例所示。
第二个问题更多的是实施选择或宗教信仰。对于某些开发人员来说,定义一个新类并继承自MediaSource
可能是您在示例中尝试过的正确方法。
有一个替代实现,您可以在其中创建源和类型转换为MediaSoure
强指针,如下例所示。
<sp><MediaSource> mVideoSource;
mVideoSource = new ImageSource(width, height, colorformat);
其中ImageSource
实施start
和read
方法。我觉得上面的recordVideo
示例是一个很好的参考。
关于最后一段,我会回答您的其他问题,但我觉得您的目标和代码之间存在根本的不匹配。目标是创建parser
或MediaExtractor
以及相应的decoder
,但上面的代码实例化ImageSource
,我认为它会提供YUV
个框架并创建正在传递encoder
以创建编码器时true
。
我还将在另一个帖子上添加关于NDK
可能性的进一步评论。