#include "PL_AndroidMediaCodecDecoder.h" #include "MaterialBuffer.h" #include "logger.h" struct PL_AMCD_Internal { uint8_t buffer[1920*1080*4];//#todo from config size_t buffSize; size_t buffSizeMax; MB_Frame lastFrame; PL_AndroidMediaCodecDecoder_Config config; bool payError; AMediaCodec* codec; PL_AMCD_Internal() : buffSize(0), buffSizeMax(sizeof(buffer)), lastFrame(), config(), payError(true), codec(nullptr) { } ~PL_AMCD_Internal() { } void reset() { buffSize = 0; payError = true; MB_Frame _lastFrame; lastFrame = _lastFrame; PL_AndroidMediaCodecDecoder_Config _config; config = _config; codec = nullptr; } }; PipeLineElem* create_PL_AndroidMediaCodecDecoder() { return new PL_AndroidMediaCodecDecoder; } PL_AndroidMediaCodecDecoder::PL_AndroidMediaCodecDecoder() : internal(new PL_AMCD_Internal) { } PL_AndroidMediaCodecDecoder::~PL_AndroidMediaCodecDecoder() { delete (PL_AMCD_Internal*)internal; internal= nullptr; } bool PL_AndroidMediaCodecDecoder::init(void* args) { PL_AMCD_Internal* in = (PL_AMCD_Internal*)internal; in->reset(); PL_AndroidMediaCodecDecoder_Config* config = (PL_AndroidMediaCodecDecoder_Config*)args; in->config = *config; AMediaFormat* format = AMediaFormat_new(); AMediaFormat_setString(format, AMEDIAFORMAT_KEY_MIME, config.ak_mime.c_str()); AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_HEIGHT, config.ak_height); AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_WIDTH, config.ak_width); // should like: // mime: string(video/avc), durationUs: int64(10000000), width: int32(480), height: int32(360), max-input-size: int32(55067), csd-0: data, csd-1: data} LOG_INFO << "AMediaFormat_toString: " << AMediaFormat_toString(format) << LOG_ENDL; in->codec = AMediaCodec_createDecoderByType(config.ak_mime.c_str()); if (AMediaCodec_configure(in->codec, format, data.window, NULL, 0) != AMEDIA_OK) LOG_ERROR << "AMediaCodec_configure error" << LOG_ENDL; if (AMediaCodec_start(in->codec) != AMEDIA_OK) LOG_ERROR << "AMediaCodec_start error" << LOG_ENDL; AMediaFormat_delete(format); return true; } void PL_AndroidMediaCodecDecoder::finit() { PL_AMCD_Internal* in = (PL_AMCD_Internal*)internal; //todo release codec } bool PL_AndroidMediaCodecDecoder::pay(const PipeMaterial& pm) { PL_AMCD_Internal* in = (PL_AMCD_Internal*)internal; if (pm.type != PipeMaterial::PMT_FRAME) { LOG_ERROR << "Only support PMT_FRAME" << std::endl; return false; } if (pm.buffer == nullptr) return false; MB_Frame* frame = (MB_Frame*)pm.buffer; if (frame->type != MB_Frame::MBFT_H264_NALU) { LOG_ERROR << "Only support MBFT_H264_NALU" << std::endl; return false; } ssize_t bufidx = AMediaCodec_dequeueInputBuffer(in->codec, 2000); static int framecount = 0; LOGP(DEBUG, "input buffer bufidx=%zd, framecount=%d", bufidx, framecount++); if (bufidx >= 0) { size_t bufsize; uint8_t* buf = AMediaCodec_getInputBuffer(in->codec, bufidx, &bufsize); size_t sampleSize = std::min(bufsize, frame->buffSize); memcpy(buf, buffer, sampleSize); //auto sampleSize = AMediaExtractor_readSampleData(d->ex, buf, bufsize); //if (sampleSize < 0) { // sampleSize = 0; // d->sawInputEOS = true; // LOGV("EOS"); //} //auto presentationTimeUs = AMediaExtractor_getSampleTime(d->ex); uint64_t presentationTimeUs = presentationTime.tv_sec * 1000 * 1000 + presentationTime.tv_usec; //microseconds media_status_t ms = AMediaCodec_queueInputBuffer(data.codec, bufidx, 0, sampleSize, presentationTimeUs, 0); //LOGV("media_status_t=%d", ms); //AMediaExtractor_advance(d->ex); } // // AVFrame* pAVFrame = (AVFrame*)frame->buffer; // if (pAVFrame == nullptr) // return false; // // const int height = pAVFrame->height; // const int width = pAVFrame->width; // ////int I420ToBGRA(const uint8* src_y, int src_stride_y, //// const uint8* src_u, int src_stride_u, //// const uint8* src_v, int src_stride_v, //// uint8* dst_argb, int dst_stride_argb, //// int width, int height); // // libyuv::I420ToBGRA(pAVFrame->data[0], width, // pAVFrame->data[1], SUBSAMPLE(width, 2), // pAVFrame->data[2], SUBSAMPLE(width, 2), // in->buffer, 4 * width, // width, height); // // in->buffSize = in->buffSizeMax; // //in->buffer readly // // in->lastFrame.type = MB_Frame::MBFT_BGRA; // in->lastFrame.buffer = in->buffer; // in->lastFrame.buffSize = in->buffSize; // in->lastFrame.width = width; // in->lastFrame.height = height; // in->lastFrame.pts = frame->pts; // // //#test // //static size_t f=0; // //char fname[50]; // //sprintf(fname, "%u.bgra", ++f); // //FILE * pFile = fopen (fname,"wb"); // //fwrite (in->buffer , sizeof(char), in->buffSize, pFile); // //fclose(pFile); // return true; } bool PL_AndroidMediaCodecDecoder::gain(PipeMaterial& pm) { PL_AMCD_Internal* in = (PL_AMCD_Internal*)internal; pm.type = PipeMaterial::PMT_FRAME; pm.buffer = &(in->lastFrame); pm.buffSize = 0; pm.former = this; return true; }