Commit 66b85de2 authored by Linshizhi's avatar Linshizhi

Add wasm

parent baaeb9f7
/**
* Replace Moudle['quit'] to avoid process.exit();
*
* @ref: https://github.com/Kagami/ffmpeg.js/blob/v4.2.9003/build/pre.js#L48
*/
Module['quit'] = function(status) {
if (Module["onExit"]) Module["onExit"](status);
throw new ExitStatus(status);
}
Module['exit'] = exit;
Module["lengthBytesUTF8"] = lengthBytesUTF8;
Module["stringToUTF8"] = stringToUTF8;
/**
* Disable all console output, might need to enable it
* for debugging
*/
out = err = function() {}
#include <stdio.h>
#include <stdint.h>
#include <malloc.h>
#include "wasm.h"
extern "C" {
#include <libavcodec/avcodec.h>
#include <libswscale/swscale.h>
}
int width_ = 0;
int height_ = 0;
int framerate_ = 0;
AVFrame *frame;
AVPacket *packet;
AVCodecContext *cc;
struct SwsContext* swsCtx = NULL;
EM_PORT_API(uint8_t) encodeInit(int width, int height, int fps) {
width_ = width;
height_ = height;
framerate_ = fps;
const AVCodec *encoder = avcodec_find_encoder_by_name("libx264");
if (encoder == NULL) {
fprintf(stderr, "Unable to find H.264 decoder\n");
return 1;
}
cc = avcodec_alloc_context3(encoder);
if (cc == NULL) {
fprintf(stderr, "Unable to alloc codec context\n");
return 2;
}
// Setup encode parameters
cc->width = width;
cc->height = height;
cc->pix_fmt = AV_PIX_FMT_YUV420P;
cc->time_base = (AVRational){1, 90000};
if (avcodec_open2(cc, encoder, NULL) < 0) {
fprintf(stderr, "Unable to open codec context\n");
return 3;
}
packet = av_packet_alloc();
if (packet == NULL) {
fprintf(stderr, "Could not allocate packet\n");
}
frame = av_frame_alloc();
frame->format = cc->pix_fmt;
frame->width = cc->width;
frame->height = cc->height;
int ret = av_frame_get_buffer(frame, 0);
if (ret < 0) {
fprintf(stderr, "Could not allocate the video frame data\n");
return 4;
}
swsCtx = sws_getCachedContext(swsCtx, width, height, AV_PIX_FMT_RGBA,
width, height, AV_PIX_FMT_YUV420P,
SWS_BICUBIC,
NULL, NULL, NULL);
return 0;
}
EM_PORT_API(uint8_t*) encode(uint8_t *data, uint32_t *size) {
int ret = 0;
uint8_t *mem;
if (av_frame_make_writable(frame) < 0) {
fprintf(stderr, "Fail to make frame writable\n");
}
AVFrame *rgbaFrame = av_frame_alloc();
rgbaFrame->format =AV_PIX_FMT_RGBA;
rgbaFrame->height = cc->height;
rgbaFrame->width = cc->width;
avpicture_fill((AVPicture*)rgbaFrame, data, AV_PIX_FMT_RGBA, width_, height_);
//转换的YUV数据存放在frame
int outSliceH = sws_scale(swsCtx, (const uint8_t* const*)rgbaFrame->data, rgbaFrame->linesize, 0, height_,
frame->data, frame->linesize);
if (outSliceH <= 0) {
printf("outSliceH <= 0 \n");
return NULL;
}
frame->pts = AV_NOPTS_VALUE;
frame->pict_type = AV_PICTURE_TYPE_I;
// Encode
ret = avcodec_send_frame(cc, frame);
if (ret < 0) {
fprintf(stderr, "Fail to encoding\n");
}
while (true) {
ret = avcodec_receive_packet(cc, packet);
if (ret) break;
// For video frame avcodec_receive_packet should return
// only once.
mem = (uint8_t*)malloc(packet->size);
memcpy(mem, packet->data, packet->size);
}
av_packet_unref(packet);
av_frame_unref(frame);
*size = packet->size;
return mem;
}
// Trivial main
int main(int argc, char *argv[]) {}
#ifndef EM_PORT_API
#if defined(__EMSCRIPTEN__)
#include <emscripten.h>
#if defined(__cplusplus)
#define EM_PORT_API(rettype) extern "C" rettype EMSCRIPTEN_KEEPALIVE
#else
#define EM_PORT_API(rettype) rettype EMSCRIPTEN_KEEPALIVE
#endif
#else
#if defined(__cplusplus)
#define EM_PORT_API(rettype) extern "C" rettype
#else
#define EM_PORT_API(rettype) rettype
#endif
#endif
#endif
#!/bin/bash
#set -eo pipefail
WORKPATH=$(cd $(dirname $0); pwd)
DEMO_PATH=$WORKPATH/src
echo "WORKPATH"=$WORKPATH
rm -rf ${DEMO_PATH}/mp4encoder.js ${DEMO_PATH}/mp4encoder.wasm
FFMPEG_ST=yes
EMSDK=/emsdk
THIRD_DIR=${WORKPATH}/lib/third/build
WASM_DIR=${WORKPATH}/src/wasm
DEBUG="-O3"
#DEBUG="-O1 -g -fno-inline -gseparate-dwarf=/code/demo2/temp.debug.wasm -s SEPARATE_DWARF_URL=http://localhost:5000/temp.debug.wasm"
#--closure 压缩胶水代码,有可能会造成变量重复定义。生产发布可设为1
OPTIM_FLAGS="$DEBUG --closure 0"
if [[ "$FFMPEG_ST" != "yes" ]]; then
EXTRA_FLAGS=(
-pthread
-s USE_PTHREADS=1 # enable pthreads support
-s PROXY_TO_PTHREAD=1 # detach main() from browser/UI main thread
-o ${DEMO_PATH}/mp4encoder.js
)
else
EXTRA_FLAGS=(
-o ${DEMO_PATH}/mp4encoder.js
)
fi
FLAGS=(
-I$WORKPATH/lib/ffmpeg-emcc/include -L$WORKPATH/lib/ffmpeg-emcc/lib -I$THIRD_DIR/include -L$THIRD_DIR/lib
-Wno-deprecated-declarations -Wno-pointer-sign -Wno-implicit-int-float-conversion -Wno-switch -Wno-parentheses -Qunused-arguments
-lavdevice -lavfilter -lavformat -lavcodec -lswresample -lswscale -lavutil -lpostproc
-lm -lharfbuzz -lfribidi -lass -lx264 -lx265 -lvpx -lwavpack -lmp3lame -lfdk-aac -lvorbis -lvorbisenc -lvorbisfile -logg -ltheora -ltheoraenc -ltheoradec -lz -lfreetype -lopus -lwebp
$WASM_DIR/interfaces.cc $WASM_DIR/utils.cc
-s FORCE_FILESYSTEM=1
-s ENVIRONMENT='web'
-s WASM=1
#-s USE_SDL=0 # use SDL2
-s INVOKE_RUN=0 # not to run the main() in the beginning
-s EXIT_RUNTIME=1 # exit runtime after execution
-s MODULARIZE=1 # 延迟加载 use modularized version to be more flexible
-s EXPORT_NAME="createMP4Encoder" # assign export name for browser
-s EXPORTED_FUNCTIONS="[_main,_malloc,_free]" # export main and proxy_main funcs
-s EXPORTED_RUNTIME_METHODS="[FS, cwrap, ccall, setValue, writeAsciiToMemory, getValue]" # export preamble funcs
-s INITIAL_MEMORY=268435456 # 64 KB * 1024 * 16 * 2047 = 2146435072 bytes ~= 2 GB, 268435456 =256M, 134,217,728 =128M
-s ALLOW_MEMORY_GROWTH=1
-s ASSERTIONS=1
--pre-js $WORKPATH/pre.js
--post-js $WORKPATH/post.js
$OPTIM_FLAGS
${EXTRA_FLAGS[@]}
)
emcc "${FLAGS[@]}"
mv ${DEMO_PATH}/mp4encoder.wasm tmp/mp4encoder.wasm
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment