diff options
Diffstat (limited to 'fuzzer/aac_enc_fuzzer.cpp')
-rw-r--r-- | fuzzer/aac_enc_fuzzer.cpp | 479 |
1 files changed, 479 insertions, 0 deletions
diff --git a/fuzzer/aac_enc_fuzzer.cpp b/fuzzer/aac_enc_fuzzer.cpp new file mode 100644 index 0000000..5a35d70 --- /dev/null +++ b/fuzzer/aac_enc_fuzzer.cpp @@ -0,0 +1,479 @@ +/****************************************************************************** + * + * Copyright (C) 2020 The Android Open Source Project + * + * 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. + * + ***************************************************************************** + * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore + */ + +#include <string> +#include "aacenc_lib.h" +#include "src/aacenc.h" + +using namespace std; + +// IN_AUDIO_DATA, IN_ANCILLRY_DATA and IN_METADATA_SETUP +constexpr size_t kMaxBuffers = 3; + +constexpr size_t kMaxOutputBufferSize = 8192; + +constexpr uint32_t kMinBitRate = 8000; +constexpr uint32_t kMaxBitRate = 960000; + +constexpr int32_t kSampleRates[] = {8000, 11025, 12000, 16000, 22050, 24000, + 32000, 44100, 48000, 64000, 88200, 96000}; +constexpr size_t kSampleRatesSize = size(kSampleRates); + +constexpr CHANNEL_MODE kChannelModes[] = {MODE_1, + MODE_2, + MODE_1_2, + MODE_1_2_1, + MODE_1_2_2, + MODE_1_2_2_1, + MODE_1_2_2_2_1, + MODE_6_1, + MODE_7_1_BACK, + MODE_7_1_TOP_FRONT, + MODE_7_1_REAR_SURROUND, + MODE_7_1_FRONT_CENTER, + MODE_212}; +constexpr size_t kChannelModesSize = size(kChannelModes); + +constexpr TRANSPORT_TYPE kIdentifiers[] = { + TT_MP4_RAW, TT_MP4_ADIF, TT_MP4_ADTS, TT_MP4_LATM_MCP1, TT_MP4_LATM_MCP0, TT_MP4_LOAS, TT_DRM}; +constexpr size_t kIdentifiersSize = size(kIdentifiers); + +constexpr AUDIO_OBJECT_TYPE kAudioObjectTypes[] = {AOT_NONE, AOT_NULL_OBJECT, + AOT_AAC_MAIN, AOT_AAC_LC, + AOT_AAC_SSR, AOT_AAC_LTP, + AOT_SBR, AOT_AAC_SCAL, + AOT_TWIN_VQ, AOT_CELP, + AOT_HVXC, AOT_RSVD_10, + AOT_RSVD_11, AOT_TTSI, + AOT_MAIN_SYNTH, AOT_WAV_TAB_SYNTH, + AOT_GEN_MIDI, AOT_ALG_SYNTH_AUD_FX, + AOT_ER_AAC_LC, AOT_RSVD_18, + AOT_ER_AAC_LTP, AOT_ER_AAC_SCAL, + AOT_ER_TWIN_VQ, AOT_ER_BSAC, + AOT_ER_AAC_LD, AOT_ER_CELP, + AOT_ER_HVXC, AOT_ER_HILN, + AOT_ER_PARA, AOT_RSVD_28, + AOT_PS, AOT_MPEGS, + AOT_ESCAPE, AOT_MP3ONMP4_L1, + AOT_MP3ONMP4_L2, AOT_MP3ONMP4_L3, + AOT_RSVD_35, AOT_RSVD_36, + AOT_AAC_SLS, AOT_SLS, + AOT_ER_AAC_ELD, AOT_USAC, + AOT_SAOC, AOT_LD_MPEGS, + AOT_MP2_AAC_LC, AOT_MP2_SBR, + AOT_DRM_AAC, AOT_DRM_SBR, + AOT_DRM_MPEG_PS, AOT_DRM_SURROUND, + AOT_DRM_USAC}; + +constexpr size_t kAudioObjectTypesSize = size(kAudioObjectTypes); + +constexpr int32_t kSbrRatios[] = {-1, 0, 1, 2}; +constexpr size_t kSbrRatiosSize = size(kSbrRatios); + +constexpr int32_t kBitRateModes[] = { + AACENC_BR_MODE_INVALID, AACENC_BR_MODE_CBR, AACENC_BR_MODE_VBR_1, + AACENC_BR_MODE_VBR_2, AACENC_BR_MODE_VBR_3, AACENC_BR_MODE_VBR_4, + AACENC_BR_MODE_VBR_5, AACENC_BR_MODE_FF, AACENC_BR_MODE_SFR}; +constexpr size_t kBitRateModesSize = size(kBitRateModes); + +constexpr int32_t kGranuleLengths[] = {120, 128, 240, 256, 480, 512, 1024}; +constexpr size_t kGranuleLengthsSize = size(kGranuleLengths); + +constexpr int32_t kChannelOrder[] = {CH_ORDER_MPEG, CH_ORDER_WAV}; +constexpr size_t kChannelOrderSize = size(kChannelOrder); + +constexpr int32_t kSignalingModes[] = {-1, 0, 1, 2, 3}; +constexpr size_t kSignalingModesSize = size(kSignalingModes); + +constexpr int32_t kAudioMuxVer[] = {-1, 0, 1, 2}; +constexpr size_t kAudioMuxVerSize = size(kAudioMuxVer); + +constexpr int32_t kSbrModes[] = {-1, 0, 1, 2}; +constexpr size_t kSbrModesSize = size(kSbrModes); + +constexpr AACENC_METADATA_DRC_PROFILE kMetaDataDrcProfiles[] = { + AACENC_METADATA_DRC_NONE, AACENC_METADATA_DRC_FILMSTANDARD, + AACENC_METADATA_DRC_FILMLIGHT, AACENC_METADATA_DRC_MUSICSTANDARD, + AACENC_METADATA_DRC_MUSICLIGHT, AACENC_METADATA_DRC_SPEECH, + AACENC_METADATA_DRC_NOT_PRESENT}; +constexpr size_t kMetaDataDrcProfilesSize = size(kMetaDataDrcProfiles); + +enum { + IDX_SBR_MODE = 0, + IDX_AAC_AOT, + IDX_SAMPLE_RATE, + IDX_BIT_RATE_1, + IDX_BIT_RATE_2, + IDX_BIT_RATE_3, + IDX_CHANNEL, + IDX_IDENTIFIER, + IDX_SBR_RATIO, + IDX_METADATA_DRC_PROFILE, + IDX_METADATA_COMP_PROFILE, + IDX_METADATA_DRC_TARGET_REF_LEVEL, + IDX_METADATA_COMP_TARGET_REF_LEVEL, + IDX_METADATA_PROG_LEVEL_PRESENT, + IDX_METADATA_PROG_LEVEL, + IDX_METADATA_PCE_MIXDOWN_IDX_PRESENT, + IDX_METADATA_ETSI_DMXLVL_PRESENT, + IDX_METADATA_CENTER_MIX_LEVEL, + IDX_METADATA_SURROUND_MIX_LEVEL, + IDX_METADATA_DOLBY_SURROUND_MODE, + IDX_METADATA_DRC_PRESENTATION_MODE, + IDX_METADATA_EXT_ANC_DATA_ENABLE, + IDX_METADATA_EXT_DOWNMIX_LEVEL_ENABLE, + IDX_METADATA_EXT_DOWNMIX_LEVEL_A, + IDX_METADATA_EXT_DOWNMIX_LEVEL_B, + IDX_METADATA_DMX_GAIN_ENABLE, + IDX_METADATA_DMX_GAIN_5, + IDX_METADATA_DMX_GAIN_2, + IDX_METADATA_LFE_DMX_ENABLE, + IDX_METADATA_LFE_DMX_LEVEL, + IDX_IN_BUFFER_INDEX_1, + IDX_IN_BUFFER_INDEX_2, + IDX_IN_BUFFER_INDEX_3, + IDX_BIT_RATE_MODE, + IDX_GRANULE_LENGTH, + IDX_CHANNELORDER, + IDX_AFTERBURNER, + IDX_BANDWIDTH, + IDX_PEAK_BITRATE, + IDX_HEADER_PERIOD, + IDX_SIGNALING_MODE, + IDX_TPSUBFRAMES, + IDX_AUDIOMUXVER, + IDX_PROTECTION, + IDX_ANCILLARY_BITRATE, + IDX_METADATA_MODE, + IDX_LAST +}; + +template <typename type1, typename type2, typename type3> +auto generateNumberInRangeFromData(type1 data, type2 min, type3 max) -> decltype(max) { + return (data % (1 + max - min)) + min; +} + +class Codec { + public: + ~Codec() { deInitEncoder(); } + bool initEncoder(uint8_t **dataPtr, size_t *sizePtr); + void encodeFrames(const uint8_t *data, size_t size); + void deInitEncoder(); + + private: + template <typename type1, typename type2, typename type3> + void setAACParam(type1 data, const AACENC_PARAM aacParam, type2 min, type2 max, + const type3 *array = nullptr); + void setupMetaData(uint8_t *data); + + HANDLE_AACENCODER mEncoder = nullptr; + AACENC_MetaData mMetaData = {}; + uint32_t mInBufferIdx_1 = 0; + uint32_t mInBufferIdx_2 = 0; + uint32_t mInBufferIdx_3 = 0; +}; + +void Codec::setupMetaData(uint8_t *data) { + uint32_t drcProfileIndex = generateNumberInRangeFromData(data[IDX_METADATA_DRC_PROFILE], 0, + kMetaDataDrcProfilesSize - 1); + AACENC_METADATA_DRC_PROFILE drcProfile = kMetaDataDrcProfiles[drcProfileIndex]; + mMetaData.drc_profile = drcProfile; + + uint32_t compProfileIndex = generateNumberInRangeFromData(data[IDX_METADATA_COMP_PROFILE], 0, + kMetaDataDrcProfilesSize - 1); + AACENC_METADATA_DRC_PROFILE compProfile = kMetaDataDrcProfiles[compProfileIndex]; + mMetaData.comp_profile = compProfile; + + INT drcTargetRefLevel = + generateNumberInRangeFromData(data[IDX_METADATA_DRC_TARGET_REF_LEVEL], 0, UINT8_MAX); + mMetaData.drc_TargetRefLevel = drcTargetRefLevel; + + INT compTargetRefLevel = + generateNumberInRangeFromData(data[IDX_METADATA_COMP_TARGET_REF_LEVEL], 0, UINT8_MAX); + mMetaData.comp_TargetRefLevel = compTargetRefLevel; + + INT isProgRefLevelPresent = + generateNumberInRangeFromData(data[IDX_METADATA_PROG_LEVEL_PRESENT], 0, 1); + mMetaData.prog_ref_level_present = isProgRefLevelPresent; + + INT progRefLevel = generateNumberInRangeFromData(data[IDX_METADATA_PROG_LEVEL], 0, UINT8_MAX); + mMetaData.prog_ref_level = progRefLevel; + + UCHAR isPCEMixdownIdxPresent = + generateNumberInRangeFromData(data[IDX_METADATA_PCE_MIXDOWN_IDX_PRESENT], 0, 1); + mMetaData.PCE_mixdown_idx_present = isPCEMixdownIdxPresent; + + UCHAR isETSIDmxLvlPresent = + generateNumberInRangeFromData(data[IDX_METADATA_ETSI_DMXLVL_PRESENT], 0, 1); + mMetaData.ETSI_DmxLvl_present = isETSIDmxLvlPresent; + + SCHAR centerMixLevel = generateNumberInRangeFromData(data[IDX_METADATA_CENTER_MIX_LEVEL], 0, 7); + mMetaData.centerMixLevel = centerMixLevel; + + SCHAR surroundMixLevel = + generateNumberInRangeFromData(data[IDX_METADATA_SURROUND_MIX_LEVEL], 0, 7); + mMetaData.surroundMixLevel = surroundMixLevel; + + UCHAR dolbySurroundMode = + generateNumberInRangeFromData(data[IDX_METADATA_DOLBY_SURROUND_MODE], 0, 2); + mMetaData.dolbySurroundMode = dolbySurroundMode; + + UCHAR drcPresentationMode = + generateNumberInRangeFromData(data[IDX_METADATA_DRC_PRESENTATION_MODE], 0, 2); + mMetaData.drcPresentationMode = drcPresentationMode; + + UCHAR extAncDataEnable = + generateNumberInRangeFromData(data[IDX_METADATA_EXT_ANC_DATA_ENABLE], 0, 1); + mMetaData.ExtMetaData.extAncDataEnable = extAncDataEnable; + + UCHAR extDownmixLevelEnable = + generateNumberInRangeFromData(data[IDX_METADATA_EXT_DOWNMIX_LEVEL_ENABLE], 0, 1); + mMetaData.ExtMetaData.extDownmixLevelEnable = extDownmixLevelEnable; + + UCHAR extDownmixLevel_A = + generateNumberInRangeFromData(data[IDX_METADATA_EXT_DOWNMIX_LEVEL_A], 0, 7); + mMetaData.ExtMetaData.extDownmixLevel_A = extDownmixLevel_A; + + UCHAR extDownmixLevel_B = + generateNumberInRangeFromData(data[IDX_METADATA_EXT_DOWNMIX_LEVEL_B], 0, 7); + mMetaData.ExtMetaData.extDownmixLevel_B = extDownmixLevel_B; + + UCHAR dmxGainEnable = generateNumberInRangeFromData(data[IDX_METADATA_DMX_GAIN_ENABLE], 0, 1); + mMetaData.ExtMetaData.dmxGainEnable = dmxGainEnable; + + INT dmxGain5 = generateNumberInRangeFromData(data[IDX_METADATA_DMX_GAIN_5], 0, UINT8_MAX); + mMetaData.ExtMetaData.dmxGain5 = dmxGain5; + + INT dmxGain2 = generateNumberInRangeFromData(data[IDX_METADATA_DMX_GAIN_2], 0, UINT8_MAX); + mMetaData.ExtMetaData.dmxGain2 = dmxGain2; + + UCHAR lfeDmxEnable = generateNumberInRangeFromData(data[IDX_METADATA_LFE_DMX_ENABLE], 0, 1); + mMetaData.ExtMetaData.lfeDmxEnable = lfeDmxEnable; + + UCHAR lfeDmxLevel = generateNumberInRangeFromData(data[IDX_METADATA_LFE_DMX_LEVEL], 0, 15); + mMetaData.ExtMetaData.lfeDmxLevel = lfeDmxLevel; +} + +template <typename type1, typename type2, typename type3> +void Codec::setAACParam(type1 data, const AACENC_PARAM aacParam, type2 min, type2 max, + const type3 *array) { + auto value = 0; + if (array) { + uint32_t index = generateNumberInRangeFromData(data, min, max); + value = array[index]; + } else { + value = generateNumberInRangeFromData(data, min, max); + } + aacEncoder_SetParam(mEncoder, aacParam, value); + (void)aacEncoder_GetParam(mEncoder, aacParam); +} + +bool Codec::initEncoder(uint8_t **dataPtr, size_t *sizePtr) { + uint8_t *data = *dataPtr; + + if (AACENC_OK != aacEncOpen(&mEncoder, 0, 0)) { + return false; + } + + setAACParam<uint8_t, size_t, int32_t>(data[IDX_SBR_MODE], AACENC_SBR_MODE, 0, kSbrModesSize - 1, + kSbrModes); + + setAACParam<uint8_t, size_t, int32_t>(data[IDX_SBR_RATIO], AACENC_SBR_RATIO, 0, + kSbrRatiosSize - 1, kSbrRatios); + + setAACParam<uint8_t, size_t, AUDIO_OBJECT_TYPE>(data[IDX_AAC_AOT], AACENC_AOT, 0, + kAudioObjectTypesSize - 1, kAudioObjectTypes); + + setAACParam<uint8_t, size_t, int32_t>(data[IDX_SAMPLE_RATE], AACENC_SAMPLERATE, 0, + kSampleRatesSize - 1, kSampleRates); + + uint32_t tempValue = + (data[IDX_BIT_RATE_1] << 16) | (data[IDX_BIT_RATE_2] << 8) | data[IDX_BIT_RATE_3]; + setAACParam<uint8_t, uint32_t, uint32_t>(tempValue, AACENC_BITRATE, kMinBitRate, kMaxBitRate); + + setAACParam<uint8_t, size_t, CHANNEL_MODE>(data[IDX_CHANNEL], AACENC_CHANNELMODE, 0, + kChannelModesSize - 1, kChannelModes); + + setAACParam<uint8_t, size_t, TRANSPORT_TYPE>(data[IDX_IDENTIFIER], AACENC_TRANSMUX, 0, + kIdentifiersSize - 1, kIdentifiers); + + setAACParam<uint8_t, size_t, int32_t>(data[IDX_BIT_RATE_MODE], AACENC_BITRATEMODE, 0, + kBitRateModesSize - 1, kBitRateModes); + + setAACParam<uint8_t, size_t, int32_t>(data[IDX_GRANULE_LENGTH], AACENC_GRANULE_LENGTH, 0, + kGranuleLengthsSize - 1, kGranuleLengths); + + setAACParam<uint8_t, size_t, int32_t>(data[IDX_CHANNELORDER], AACENC_CHANNELORDER, 0, + kChannelOrderSize - 1, kChannelOrder); + + setAACParam<uint8_t, int32_t, int32_t>(data[IDX_AFTERBURNER], AACENC_AFTERBURNER, 0, 1); + + setAACParam<uint8_t, int32_t, int32_t>(data[IDX_BANDWIDTH], AACENC_BANDWIDTH, 0, 1); + + setAACParam<uint8_t, uint32_t, uint32_t>(data[IDX_PEAK_BITRATE], AACENC_PEAK_BITRATE, + kMinBitRate, kMinBitRate); + + setAACParam<uint8_t, uint32_t, uint32_t>(data[IDX_HEADER_PERIOD], AACENC_HEADER_PERIOD, 0, + UINT8_MAX); + + setAACParam<uint8_t, size_t, int32_t>(data[IDX_SIGNALING_MODE], AACENC_SIGNALING_MODE, 0, + kSignalingModesSize - 1, kSignalingModes); + + setAACParam<uint8_t, uint32_t, uint32_t>(data[IDX_TPSUBFRAMES], AACENC_TPSUBFRAMES, 0, + UINT8_MAX); + + setAACParam<uint8_t, size_t, int32_t>(data[IDX_AUDIOMUXVER], AACENC_AUDIOMUXVER, 0, + kAudioMuxVerSize - 1, kAudioMuxVer); + + setAACParam<uint8_t, uint32_t, uint32_t>(data[IDX_PROTECTION], AACENC_PROTECTION, 0, 1); + + setAACParam<uint8_t, uint32_t, uint32_t>(data[IDX_ANCILLARY_BITRATE], AACENC_ANCILLARY_BITRATE, + 0, kMaxBitRate); + + setAACParam<uint8_t, uint32_t, uint32_t>(data[IDX_METADATA_MODE], AACENC_METADATA_MODE, 0, 3); + + AACENC_InfoStruct encInfo; + aacEncInfo(mEncoder, &encInfo); + + mInBufferIdx_1 = generateNumberInRangeFromData(data[IDX_IN_BUFFER_INDEX_1], 0, kMaxBuffers - 1); + mInBufferIdx_2 = generateNumberInRangeFromData(data[IDX_IN_BUFFER_INDEX_2], 0, kMaxBuffers - 1); + mInBufferIdx_3 = generateNumberInRangeFromData(data[IDX_IN_BUFFER_INDEX_3], 0, kMaxBuffers - 1); + + setupMetaData(data); + + // Not re-using the data which was used for configuration for encoding + *dataPtr += IDX_LAST; + *sizePtr -= IDX_LAST; + + return true; +} + +static void deleteBuffers(uint8_t **buffers, size_t size) { + for (size_t n = 0; n < size; ++n) { + delete[] buffers[n]; + } + delete[] buffers; +} + +void Codec::encodeFrames(const uint8_t *data, size_t size) { + uint8_t *audioData = (uint8_t *)data; + uint8_t *ancData = (uint8_t *)data; + size_t audioSize = size; + size_t ancSize = size; + + while ((audioSize > 0) && (ancSize > 0)) { + AACENC_InArgs inargs; + memset(&inargs, 0, sizeof(inargs)); + inargs.numInSamples = audioSize / sizeof(int16_t); + inargs.numAncBytes = ancSize; + + void *buffers[] = {(void *)audioData, (void *)ancData, &mMetaData}; + INT bufferIds[] = {IN_AUDIO_DATA, IN_ANCILLRY_DATA, IN_METADATA_SETUP}; + INT bufferSizes[] = {static_cast<INT>(audioSize), static_cast<INT>(ancSize), + static_cast<INT>(sizeof(mMetaData))}; + INT bufferElSizes[] = {sizeof(int16_t), sizeof(UCHAR), sizeof(AACENC_MetaData)}; + + void *inBuffer[kMaxBuffers] = {}; + INT inBufferIds[kMaxBuffers] = {}; + INT inBufferSize[kMaxBuffers] = {}; + INT inBufferElSize[kMaxBuffers] = {}; + for (int32_t buffer = 0; buffer < kMaxBuffers; ++buffer) { + uint32_t Idxs[] = {mInBufferIdx_1, mInBufferIdx_2, mInBufferIdx_3}; + inBuffer[buffer] = buffers[Idxs[buffer]]; + inBufferIds[buffer] = bufferIds[Idxs[buffer]]; + inBufferSize[buffer] = bufferSizes[Idxs[buffer]]; + inBufferElSize[buffer] = bufferElSizes[Idxs[buffer]]; + } + + AACENC_BufDesc inBufDesc; + inBufDesc.numBufs = kMaxBuffers; + inBufDesc.bufs = (void **)&inBuffer; + inBufDesc.bufferIdentifiers = inBufferIds; + inBufDesc.bufSizes = inBufferSize; + inBufDesc.bufElSizes = inBufferElSize; + + uint8_t **outPtrRef = new uint8_t *[kMaxBuffers]; + for (int32_t buffer = 0; buffer < kMaxBuffers; ++buffer) { + outPtrRef[buffer] = new uint8_t[kMaxOutputBufferSize]; + } + + void *outBuffer[kMaxBuffers]; + INT outBufferIds[kMaxBuffers]; + INT outBufferSize[kMaxBuffers]; + INT outBufferElSize[kMaxBuffers]; + + for (int32_t buffer = 0; buffer < kMaxBuffers; ++buffer) { + outBuffer[buffer] = outPtrRef[buffer]; + outBufferIds[buffer] = OUT_BITSTREAM_DATA; + outBufferSize[buffer] = (INT)kMaxOutputBufferSize; + outBufferElSize[buffer] = sizeof(UCHAR); + } + + AACENC_BufDesc outBufDesc; + outBufDesc.numBufs = kMaxBuffers; + outBufDesc.bufs = (void **)&outBuffer; + outBufDesc.bufferIdentifiers = outBufferIds; + outBufDesc.bufSizes = outBufferSize; + outBufDesc.bufElSizes = outBufferElSize; + + AACENC_OutArgs outargs = {}; + aacEncEncode(mEncoder, &inBufDesc, &outBufDesc, &inargs, &outargs); + + if (outargs.numOutBytes == 0) { + if (audioSize > 0) { + ++audioData; + --audioSize; + } + if (ancSize > 0) { + ++ancData; + --ancSize; + } + } else { + size_t audioConsumed = outargs.numInSamples * sizeof(int16_t); + audioData += audioConsumed; + audioSize -= audioConsumed; + + size_t ancConsumed = outargs.numAncBytes; + ancData += ancConsumed; + ancSize -= ancConsumed; + } + deleteBuffers(outPtrRef, kMaxBuffers); + + // break out of loop if only metadata was sent in all the input buffers + // as sending it multiple times in a loop is redundant. + if ((mInBufferIdx_1 == kMaxBuffers - 1) && (mInBufferIdx_2 == kMaxBuffers - 1) && + (mInBufferIdx_3 == kMaxBuffers - 1)) { + break; + } + } +} + +void Codec::deInitEncoder() { aacEncClose(&mEncoder); } + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + if (size < IDX_LAST) { + return 0; + } + Codec encoder; + if (encoder.initEncoder(const_cast<uint8_t **>(&data), &size)) { + encoder.encodeFrames(data, size); + } + return 0; +} |