4javier 4javier - 2 months ago 14
C++ Question

C++ implementation of abstract method not satisfied

In an Android project I have a quite messy inheritance situation that I can't fully understand.
This is the error I get compiling:

vendor/mediatek/proprietary/external/audioATCmdHandlerServer/AudioCmdHandler.cpp:4458:51: error: cannot allocate an object of abstract type 'android::MediaRecorder'
m_MediaRecorderClient = new MediaRecorder();
^
In file included from vendor/mediatek/proprietary/external/audioATCmdHandlerServer/AudioCmdHandler.h:101:0,
from vendor/mediatek/proprietary/external/audioATCmdHandlerServer/AudioCmdHandler.cpp:199:
frameworks/av/include/media/mediarecorder.h:245:7: note: because the following virtual functions are pure within 'android::MediaRecorder':
class MediaRecorder : public BnMediaRecorderClient,
^
In file included from frameworks/av/include/media/mediarecorder.h:30:0,
from vendor/mediatek/proprietary/external/audioATCmdHandlerServer/AudioCmdHandler.h:101,
from vendor/mediatek/proprietary/external/audioATCmdHandlerServer/AudioCmdHandler.cpp:199:
frameworks/av/include/media/IMediaRecorderClient.h:32:18: note: virtual void android::IMediaRecorderClient::readAudio()
virtual void readAudio() = 0;


This is the class MediaRecorder from mediarecorder.h

............
.......
#include <media/IMediaRecorderClient.h>
.......
...........

class MediaRecorder : public BnMediaRecorderClient,
public virtual IMediaDeathNotifier
{
public:
MediaRecorder();
~MediaRecorder();

void died();
status_t initCheck();
status_t setCamera(const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy);
status_t setPreviewSurface(const sp<IGraphicBufferProducer>& surface);
status_t setVideoSource(int vs);
status_t setAudioSource(int as);
status_t setOutputFormat(int of);
status_t setVideoEncoder(int ve);
status_t setAudioEncoder(int ae);
status_t setOutputFile(const char* path);
status_t setOutputFile(int fd, int64_t offset, int64_t length);
status_t setVideoSize(int width, int height);
status_t setVideoFrameRate(int frames_per_second);
status_t setParameters(const String8& params);
status_t setListener(const sp<MediaRecorderListener>& listener);
status_t setClientName(const String16& clientName);
status_t prepare();
status_t getMaxAmplitude(int* max);
status_t start();
status_t stop();
status_t reset();
status_t init();
status_t close();
status_t release();
void notify(int msg, int ext1, int ext2);
sp<IGraphicBufferProducer> querySurfaceMediaSourceFromMediaServer();

#ifdef MTK_AOSP_ENHANCEMENT
status_t setParametersExtra(const String8& params);
#endif

private:
void doCleanUp();
status_t doReset();

sp<IMediaRecorder> mMediaRecorder;
sp<MediaRecorderListener> mListener;

// Reference to IGraphicBufferProducer
// for encoding GL Frames. That is useful only when the
// video source is set to VIDEO_SOURCE_GRALLOC_BUFFER
sp<IGraphicBufferProducer> mSurfaceMediaSource;

media_recorder_states mCurrentState;
bool mIsAudioSourceSet;
bool mIsVideoSourceSet;
bool mIsAudioEncoderSet;
bool mIsVideoEncoderSet;
bool mIsOutputFileSet;
Mutex mLock;
Mutex mNotifyLock;
};


This is IMediaRecorderClient.h

#include <utils/RefBase.h>
#include <binder/IInterface.h>
#include <binder/Parcel.h>

namespace android {

class IMediaRecorderClient: public IInterface
{
public:
DECLARE_META_INTERFACE(MediaRecorderClient);

virtual void notify(int msg, int ext1, int ext2) = 0;
virtual void readAudio() = 0;
};

// ----------------------------------------------------------------------------

class BnMediaRecorderClient: public BnInterface<IMediaRecorderClient>
{
public:
virtual status_t onTransact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
};

};


And this is an extract from IMediaRecorderClient.cpp, that seems to me implementing the abstract method virtual void readAudio()

#include <utils/RefBase.h>
#include <binder/IInterface.h>
#include <binder/Parcel.h>

#include <media/IMediaRecorderClient.h>

namespace android {

enum {
NOTIFY = IBinder::FIRST_CALL_TRANSACTION,
READ_AUDIO,
};

class BpMediaRecorderClient: public BpInterface<IMediaRecorderClient>
{
public:
BpMediaRecorderClient(const sp<IBinder>& impl)
: BpInterface<IMediaRecorderClient>(impl)
{
}

virtual void notify(int msg, int ext1, int ext2)
{
Parcel data, reply;
data.writeInterfaceToken(IMediaRecorderClient::getInterfaceDescriptor());
data.writeInt32(msg);
data.writeInt32(ext1);
data.writeInt32(ext2);
remote()->transact(NOTIFY, data, &reply, IBinder::FLAG_ONEWAY);
}

virtual void readAudio()
{
Parcel data, reply;
data.writeInterfaceToken(IMediaRecorderClient::getInterfaceDescriptor());
remote()->transact(READ_AUDIO, data, &reply, IBinder::FLAG_ONEWAY);
}
};


Where am I wrong?

Answer

The compiler is telling you that in the following statement of AudioCmdHandler.cpp:

    m_MediaRecorderClient = new MediaRecorder();

there is an attempt to instantiate the class MediaRecorder which is an abstract class. An abstract class means that it has at least one virtual function which is not defined at all, and in your case it is readAudio().

How come ?

The class definition of MediaRecorder that you've shown, doesn't provide readAudio(). But the class inherits from BnMediaRecorderClient. This one doesn't provide readAudio() either and inherits from a template BnInterface<IMediaRecorderClient>.

I don't know how exactly the template class BnInterface<...> is defined, but I guess it is a CRTP that extends the interface provided as argument, so that in the end, MediaRecorder will indirectly inherit from IMediaRecorderClient.

And this one defines this pure virtual function:

virtual void readAudio() = 0;

How to solve it ?

You must provide provide and implement this function in MediaRecorder in order to be able to instantiate objects of this class.