Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <../../../../FPExternalClasses/Classes/FFmpeg/ffmpegvideoplay.h>
- #include "cocostudio/CocoStudio.h"
- #include "ui/CocosGUI.h"
- #include "../../../../FPExternalClasses/Classes/videoplay.h"
- #include <mutex>
- #include "iostream"
- #include <cocos2d.h>
- #include "../../../../FPExternalClasses/Classes/global.h"
- #include "../../../../FPExternalClasses/Classes/globalevents.h"
- #include "../../../../FPExternalClasses/Classes/videomanager.h";
- #include <mutex>
- unsigned int video::totalVideoPlayers = 0;
- bool isAlt = false;
- video::video(std::string path, cocos2d::Sprite* origin) {
- totalVideoPlayers++;
- this->infilename = path;
- if (origin) {
- holdersprite = origin; //save the guy
- transfer = true;
- org_rotation = origin->getRotation();
- org_scaleX = origin->getScaleX();
- org_scaleY = origin->getScaleY();
- org_anchor = origin->getAnchorPoint();
- org_pos = origin->getPosition();
- org_size = origin->getContentSize();
- org_opacity = origin->getOpacity();
- wasVisible = origin->isVisible();
- org_blend = origin->getBlendFunc();
- org_zorder = origin->getZOrder();
- }
- this->video_init();
- }
- video::~video() {
- freeData();
- }
- void video::video_init() {
- //get mat?
- //or draw vertices?
- //try first standard way?
- //draw vertices?
- // build and compile our shader zprogram
- // ------------------------------------
- /// ourShader = new Shader("4.2.texture.vs", "4.2.texture.fs");
- // load and create a texture
- // -------------------------
- // texture 1
- // ---------
- glGenTextures(1, &texture1);
- glBindTexture(GL_TEXTURE_2D, texture1);
- // set the texture wrapping parameters
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); // set texture wrapping to GL_REPEAT (default wrapping method)
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
- // set texture filtering parameters
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); //GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); //GL_LINEAR);
- // load image, create texture and generate mipmaps
- // tell opengl for each sampler to which texture unit it belongs to (only has to be done once)
- // -------------------------------------------------------------------------------------------
- /// ourShader->use(); // don't forget to activate/use the shader before setting uniforms!
- // either set it manually like so:
- /// glUniform1i(glGetUniformLocation(ourShader->ID, "texture1"), 0);
- // or set it via the texture class
- //we already have DECLARED contexts
- //we need to fill them up boi
- #pragma warning(disable : 4996)
- av_register_all(); //will register only the ones we need next time around
- avformat_open_input(&format_contex, infilename.c_str(), NULL, NULL);
- avformat_find_stream_info(format_contex, NULL);
- // get video stream index
- for (int i = 0; i < format_contex->nb_streams; i++) {
- //FIND STREAM THAT IS VIDEO TYPE!
- if (format_contex->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { //kinda pointless step
- VideoStreamIndex = i;
- break;
- }
- }
- // av_dump_format(format_contex, VideoStreamIndex, infilename, false);
- codec_contex = avcodec_alloc_context3(NULL);
- avcodec_parameters_to_context(codec_contex, format_contex->streams[VideoStreamIndex]->codecpar);
- Codec = avcodec_find_decoder(codec_contex->codec_id);
- avcodec_open2(codec_contex, Codec, NULL);
- ///pkt = av_packet_alloc();
- ///av_init_packet(pkt);
- ///oframe = av_frame_alloc();
- //fin = fopen(infilename, "rb");
- this->width = codec_contex->width;
- this->height = codec_contex->height;
- if (this->height == 0 || this->width == 0) {
- //SOMETHING WENT WRONG
- int breakpoint = 12;
- }
- //allocate buffer
- //buffer = (uint8_t*)calloc(3 * width * height, sizeof(uint8_t));
- //That's all i think!
- //now just get dem frames
- /// glAttachShader(ourShader->ID, GL_VERTEX_SHADER);
- /// glAttachShader(ourShader->ID, GL_FRAGMENT_SHADER);
- //global::global_pending_futures.push_back(std::async(std::launch::async, [] {
- //global::global_pending_futures.push_back(std::async(std::launch::async, [this] {
- // this->decodeLoop();
- //}));
- //auto GlobalSize = Director::getInstance()->getWinSize();
- cocos2d::Size contentSize = cocos2d::Size(width, height);
- if (transfer) {
- this->setContentSize(org_size);
- contentSize = org_size;//cocos2d::Size(width, height);
- this->setAnchorPoint(org_anchor);
- this->setPosition(org_pos);
- this->setScaleX(org_scaleX);
- this->setScaleY(org_scaleY);
- this->setRotation(org_rotation);
- this->setOpacity(org_opacity);
- this->setVisible(wasVisible);
- }
- buf1.frame = av_frame_alloc();
- buf2.frame = av_frame_alloc();
- //buf3.frame = av_frame_alloc();
- buf1.pdata = (uint8_t*)malloc(3 * (width*height));
- buf2.pdata = (uint8_t*)malloc(3 * (width*height));
- //buf3.pdata = (uint8_t*)malloc(3 * (width*height));
- buf1.pkt = av_packet_alloc();
- buf2.pkt = av_packet_alloc();
- //buf3.pkt = av_packet_alloc();
- buf1.name = "buffer 1";
- buf2.name = "buffer 2";
- //buf3.name = "buffer 3";
- glGenBuffers(2, pboids);
- buf1.pboid = pboids[0];
- buf2.pboid = pboids[1];
- size_t size = 3 * (width*height);
- glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buf1.pboid);
- glBufferData(GL_PIXEL_UNPACK_BUFFER, size, NULL, GL_DYNAMIC_DRAW);
- glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buf2.pboid);
- glBufferData(GL_PIXEL_UNPACK_BUFFER, size, NULL, GL_DYNAMIC_DRAW);
- GLenum err;
- while ((err = glGetError()) != GL_NO_ERROR)
- {
- //Process/log the error.
- }
- glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
- decodeLoop();
- ///unsigned char *
- video::frameData* dataEna = getData();///vid.getCurrentRBGConvertedFrame();
- Texture2D *texture = new Texture2D();
- if (dataEna) {
- if (dataEna->pdata) {
- texture->initWithData(dataEna->pdata, sizeof(dataEna->pdata),
- cocos2d::Texture2D::PixelFormat::RGB888, width, height, contentSize);
- }
- }
- else {
- global::AppendToLog("ERROR! Couldn't create video!", true);
- return;
- }
- _texture = texture;
- //texture->_ID
- initWithTexture(texture);
- this->freeData();
- if (transfer) {
- this->setContentSize(org_size);
- contentSize = org_size;//cocos2d::Size(width, height);
- this->setAnchorPoint(org_anchor);
- this->setPosition(org_pos);
- this->setScaleX(org_scaleX);
- this->setScaleY(org_scaleY);
- this->setRotation(org_rotation);
- this->setOpacity(org_opacity);
- this->setVisible(wasVisible);
- this->_blendFunc = org_blend;
- this->setZOrder(org_zorder);
- }
- ///buffer = (uint8_t*)malloc(3 * (width*height));///(width*height));
- ///std::thread t2([this] {
- global::global_pending_futures.push_back(std::async(std::launch::async, [=] {
- while (true) {
- if (isPlaying) {
- this->decodeLoop();
- ///std::this_thread::sleep_for(std::chrono::milliseconds(3));
- }
- else {
- std::this_thread::sleep_for(std::chrono::milliseconds(3));
- }
- }
- /// });
- }));
- }
- void video::decodeLoop() { //this should loop in a separate thread
- frameData* buff = nullptr;
- if (buf1.needsRefill) {
- /// buf1.bufferLock.lock();
- buff = &buf1;
- buf1.needsRefill = false;
- firstBuff = true;
- }
- else if (buf2.needsRefill) {
- ///buf2.bufferLock.lock();
- buff = &buf2;
- buf2.needsRefill = false;
- firstBuff = false;
- }
- if (buff == nullptr) {
- std::this_thread::sleep_for(std::chrono::milliseconds(1));
- return;//error? //wait?
- }
- //pack pixel buffer?
- if (getNextFrame(buff)) {
- getCurrentRBGConvertedFrame(buff);
- }
- else {
- loopedTimes++;
- if (loopedTimes >= repeatTimes) {
- stop();
- }
- else {
- restartVideoPlay(&buf1);//restart both
- restartVideoPlay(&buf2);
- if (getNextFrame(buff)) {
- getCurrentRBGConvertedFrame(buff);
- }
- }
- }
- ///glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buff->pboid);
- ///glBufferData(GL_PIXEL_UNPACK_BUFFER, 3 * (width*height), buff->pdata, GL_DYNAMIC_DRAW);
- /// buff->bufferLock.unlock();
- return;
- }
- void video::actualDraw() { //meant for cocos implementation
- ///return;
- if (this->isVisible()) {
- if (this->getOpacity() > 0) {
- //since we do flip flop method, we can check for loops here
- if (isPlaying) {
- if (loopedTimes >= repeatTimes) { //ignore -1 because comparing unsgined to singed
- this->stop();
- }
- }
- if (isPlaying) {
- this->setVisible(true);
- ///pxDataMtx.lock();
- if (!display) { //skip frame
- ///this->getNextFrame();
- display = true;
- }
- else if (display) {
- display = false;
- auto buff = this->getData();
- width = this->getWidth();
- height = this->getHeight();
- if (buff) {
- ///buff->bufferLock.lock();
- if (buff->pdata) {
- glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buff->pboid);
- glBufferData(GL_PIXEL_UNPACK_BUFFER, 3 * (width*height), buff->pdata, GL_DYNAMIC_DRAW);
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, 0);///buff->pdata);
- //glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
- //glGenerateMipmap(GL_TEXTURE_2D);
- glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
- }
- buff->needsRefill = true;
- ///buff->bufferLock.unlock();
- }
- //std::this_thread::sleep_for(std::chrono::milliseconds(14));
- ///this->freeData();
- // bind textures on corresponding texture units
- //glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, texture1);
- }
- //glActiveTexture(GL_TEXTURE1);
- //glBindTexture(GL_TEXTURE_2D, texture2);
- // render container
- //ourShader.use();
- // glDetachShader(ourShader->ID, GL_VERTEX_SHADER);
- // glDetachShader(ourShader->ID, GL_FRAGMENT_SHADER);
- ///pxDataMtx.unlock();
- }
- else { this->setVisible(false); }
- }
- }
- }
- void video::draw(cocos2d::Renderer* renderer, const cocos2d::Mat4& transform, uint32_t flags){
- if(!_customCommand){
- _customCommand = new cocos2d::CustomCommand();
- }
- Sprite::draw(renderer, transform, flags);
- _customCommand->init(_globalZOrder);
- _customCommand->func = CC_CALLBACK_0(video::actualDraw, this);
- cocos2d::Director::getInstance()->getRenderer()->addCommand(_customCommand);
- }
- unsigned char* video::getNextFrame(frameData* fd) {
- //if (isAlt) { isAlt = false; return NULL; }
- //else { isAlt = true; }
- //outputs pixel data but also updates oframe so we can fill cframe
- framecount++;
- //std::cout << std::to_string(framecount) << std::endl;
- // read an encoded packet from file
- int ret = av_read_frame(format_contex, fd->pkt);
- if (ret < 0)
- {
- //if cannot read frame, seek to start
- if (repeat) {
- av_packet_unref(fd->pkt);
- return nullptr;
- //ret = av_read_frame(format_contex, pkt); //we already do that in restart()
- }
- else {
- //av_log(NULL, AV_LOG_ERROR, "cannot read frame");
- av_packet_unref(fd->pkt);
- return nullptr;
- }
- }
- // if packet data is video data then send it to decoder
- if (fd->pkt->stream_index == VideoStreamIndex) {
- //decode
- fd->frame = decode(codec_contex, fd->frame, fd->pkt);
- }
- // release packet buffers to be allocated again
- av_packet_unref(fd->pkt);
- //std::this_thread::sleep_for(std::chrono::milliseconds(2));
- return (unsigned char*)fd->frame->data[0];
- //flush decoder
- //decode(codec_ctx, frame, NULL);
- }
- //only internally resets video, doesn't output frame!
- void video::restartVideoPlay(video::frameData* buff) {
- ///return;
- av_seek_frame(format_contex, buff->pkt->stream_index, 0, AVSEEK_FLAG_BACKWARD);
- ///av_read_frame(format_contex, buff->pkt);
- framecount = 0;
- codec_contex->frame_number = 0;
- ///loopedTimes++;
- }
- AVFrame* video::decode(AVCodecContext* cc, AVFrame* frame, AVPacket* pack) {
- int ret;
- //send packet to decoder
- ret = avcodec_send_packet(cc, pack);
- if (ret < 0) {
- //fprintf(stderr, "Error sending a packet for decoding\n");
- //exit(1);
- }
- while (ret >= 0) {
- // receive frame from decoder
- // we may receive multiple frames or we may consume all data from decoder, then return to main loop
- ret = avcodec_receive_frame(cc, frame);
- if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
- av_packet_unref(pack);
- return frame;
- }
- else if (ret < 0) {
- // something wrong, quit program
- fprintf(stderr, "Error during decoding\n");
- exit(1);
- }
- //printf("outputing frame %3d\n", cc->frame_number);
- fflush(stdout);
- av_packet_unref(pack);
- return frame;
- }
- }
- /*
- void YUVImage::yuv2rgb(uint8_t yValue, uint8_t uValue, uint8_t vValue,
- uint8_t *r, uint8_t *g, uint8_t *b) const {
- int rTmp = yValue + (1.370705 * (vValue-128));
- int gTmp = yValue - (0.698001 * (vValue-128)) - (0.337633 * (uValue-128));
- int bTmp = yValue + (1.732446 * (uValue-128));
- *r = clamp(rTmp, 0, 255);
- *g = clamp(gTmp, 0, 255);
- *b = clamp(bTmp, 0, 255);
- }
- */
- unsigned char* video::getCurrentRBGConvertedFrame(frameData* fd) {
- SwsContext *sws_ctx = sws_getContext(width, height,
- codec_contex->pix_fmt, width, height,
- AV_PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL //BICUBIC is nicer color?
- );
- uint8_t *rgb24[1];
- //buffer should only be allocated ONCE
- ///buffer = (uint8_t*)malloc(3 * (width*height));//(uint8_t*)calloc(3 * width * height, sizeof(uint8_t));
- //memset(buffer, NULL, sizeof(buffer));
- //buffer = prgb24;
- rgb24[0] = { fd->pdata };
- int rgb24_stride[1] = { 3 * width }; //same as linesize supposedly
- sws_scale(sws_ctx, fd->frame->data, fd->frame->linesize, 0, height, rgb24, rgb24_stride);
- sws_freeContext(sws_ctx);
- return fd->pdata;
- }
- void video::freeData() {
- return;
- if (codec_contex) {
- //avcodec_free_context(&codec_contex);levi
- }
- //return;
- if (buffer) {
- ///free(buffer);
- ///buffer = NULL;
- }
- if (oframe) {
- //av_frame_free(&oframe);
- av_frame_unref(oframe);
- //av_frame_free(&oframe);
- }
- if (cframe) {
- //av_frame_free(&cframe);
- av_frame_unref(cframe);
- }
- if (pkt) {
- av_packet_unref(pkt);
- //av_free_packet(pkt);
- }
- }
- void video::stop() { //will make actual stop
- isPlaying = false;
- restartVideoPlay(&buf1);
- restartVideoPlay(&buf2);
- freeData();
- this->setVisible(false);
- this->holdersprite->setVisible(false);
- if (hideWithEvent != "") {
- cocos2d::Director::getInstance()->getScheduler()->performFunctionInCocosThread([this] {
- globalevents::fireCustomEvent(hideWithEvent);
- });
- }
- }
- void video::play() {
- if (isPlaying) { return; }
- isPlaying = true;
- if (showWithEvent != "") {
- cocos2d::Director::getInstance()->getScheduler()->performFunctionInCocosThread([this] {
- globalevents::fireCustomEvent(showWithEvent);
- });
- }
- //opengl data here
- //no opengl data here!
- this->setVisible(true);
- this->holdersprite->setVisible(false);
- }
- void video::pause() {
- isPlaying = false;
- }
- void video::setRepeats(int reps) {
- if (reps == 999) {
- repeatTimes = -1; //forever
- }
- else if (reps == 0) {
- repeatTimes = 1;
- }
- else {
- repeatTimes = reps;
- }
- }
- ///unsigned char*
- video::frameData* video::getData() {
- if (firstBuff) {
- if (buf1.needsRefill == false) {
- ///firstBuff = false;
- return &buf1;///.pdata;
- }
- }
- else { //if false
- if (buf2.needsRefill == false) {
- ///firstBuff = true;
- return &buf2;///.pdata;
- }
- }
- return nullptr;
- }
- #ifdef SAMPLENOTDEFINED
- Step 1. RGB - YUV conversion.----------------------------
- // Create YUV buffer
- m_bufferSize = avpicture_get_size(PIX_FMT_YUV420P, width, height);
- avPictureInfo_ = avcodec_alloc_frame();
- m_buffer = (uint8_t *)av_malloc(m_bufferSize);
- avpicture_fill((AVPicture*)avPictureInfo_, m_buffer, PIX_FMT_YUV420P,
- width, height);
- // Then fill it with RGB data
- struct SwsContext *img_convert_ctx = sws_getContext(m_width, m_height,
- PIX_FMT_RGB24,
- m_width,
- m_height, PIX_FMT_YUV420P, SWS_BICUBIC,
- NULL, NULL, NULL);
- if (img_convert_ctx == NULL) {
- return NULL;
- }
- uint8_t * srcData[4] = { m_buffer, 0, 0, 0 };
- int srcLineSize[4] = { m_width * 3 * sizeof(uint8_t), 0, 0, 0 };
- sws_scale(img_convert_ctx, srcData, srcLineSize, 0,
- m_height, yuvImage->avPictureInfo_->data,
- yuvImage->avPictureInfo_->linesize);
- free(img_convert_ctx);
- #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement