2021年2月2日星期二

How can I display the video on sdl converted to emscripten?

I am trying to view video in a browser using ffmpeg's decoder.

So, I made the decoder into a js file using emscripten.

By the way, the decoder seems to work, but only the last scene is displayed.

How can a video come out from start to finish?

Here is my code

  #include <stdio.h>  #include <stdlib.h>  #include <string.h>    #include <libavcodec/avcodec.h>    #include <SDL2/SDL.h>    #define INBUF_SIZE 128    static void decode(AVCodecContext *dec_ctx, AVFrame *frame, AVPacket *pkt,                     const char *filename,                     SDL_Window * screen, SDL_Renderer * renderer, SDL_Texture * texture)  {      char buf[1024];      int ret;        ret = avcodec_send_packet(dec_ctx, pkt);      if (ret < 0) {          fprintf(stderr, "Error sending a packet for decoding\n");          exit(1);      }        while (ret >= 0) {          ret = avcodec_receive_frame(dec_ctx, frame);          if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)              return;          else if (ret < 0) {              fprintf(stderr, "Error during decoding\n");              exit(1);          }            printf("saving frame %3d\n", dec_ctx->frame_number);          fflush(stdout);            SDL_Rect rect;          rect.x = 0;          rect.y = 0;          rect.w = dec_ctx->width;          rect.h = dec_ctx->height;            SDL_UpdateYUVTexture(              texture,            // the texture to update              &rect,              // a pointer to the rectangle of pixels to update, or NULL to update the entire texture              frame->data[0],      // the raw pixel data for the Y plane              frame->linesize[0],  // the number of bytes between rows of pixel data for the Y plane              frame->data[1],      // the raw pixel data for the U plane              frame->linesize[1],  // the number of bytes between rows of pixel data for the U plane              frame->data[2],      // the raw pixel data for the V plane              frame->linesize[2]   // the number of bytes between rows of pixel data for the V plane          );            SDL_RenderClear(renderer);            SDL_RenderCopy(              renderer,   // the rendering context              texture,    // the source texture              NULL,       // the source SDL_Rect structure or NULL for the entire texture              NULL        // the destination SDL_Rect structure or NULL for the entire rendering                          // target; the texture will be stretched to fill the given rectangle          );            SDL_RenderPresent(renderer);          SDL_UpdateWindowSurface(screen);      }  }    int main(int argc, char **argv)  {      const char *filename, *outfilename;      const AVCodec *codec;      AVCodecParserContext *parser;      AVCodecContext *c= NULL;      FILE *f;      AVFrame *frame;      uint8_t inbuf[INBUF_SIZE + AV_INPUT_BUFFER_PADDING_SIZE];      uint8_t *data;      size_t   data_size;      int ret;      AVPacket *pkt;        if (argc <= 2) {          fprintf(stderr, "Usage: %s <input file> <output file>\n"                  "And check your input file is encoded by mpeg1video please.\n", argv[0]);          exit(0);      }      filename    = argv[1];      outfilename = argv[2];        pkt = av_packet_alloc();      if (!pkt)          exit(1);        /* set end of buffer to 0 (this ensures that no overreading happens for damaged MPEG streams) */      memset(inbuf + INBUF_SIZE, 0, AV_INPUT_BUFFER_PADDING_SIZE);        ret = SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER);   // [1]      if (ret != 0)      {          // error while initializing SDL          printf("Could not initialize SDL - %s\n.", SDL_GetError());            // exit with error          // return -1;      }        /* find the MPEG-1 video decoder */      codec = avcodec_find_decoder(AV_CODEC_ID_H265);      if (!codec) {          fprintf(stderr, "Codec not found\n");          exit(1);      }        parser = av_parser_init(codec->id);      if (!parser) {          fprintf(stderr, "parser not found\n");          exit(1);      }        c = avcodec_alloc_context3(codec);      if (!c) {          fprintf(stderr, "Could not allocate video codec context\n");          exit(1);      }        /* open it */      if (avcodec_open2(c, codec, NULL) < 0) {          fprintf(stderr, "Could not open codec\n");          exit(1);      }        f = fopen(filename, "rb");      if (!f) {          fprintf(stderr, "Could not open %s\n", filename);          exit(1);      }        frame = av_frame_alloc();      if (!frame) {          fprintf(stderr, "Could not allocate video frame\n");          exit(1);      }        // Create a window with the specified position, dimensions, and flags.      SDL_Window * screen = SDL_CreateWindow( // [2]                              "SDL Video Player",                              SDL_WINDOWPOS_UNDEFINED,                              SDL_WINDOWPOS_UNDEFINED,                              640,                              360,                              SDL_WINDOW_OPENGL | SDL_WINDOW_ALLOW_HIGHDPI      );        if (!screen)      {          // could not set video mode          printf("SDL: could not set video mode - exiting.\n");            // exit with Error          // return -1;      }        // //      // SDL_GL_SetSwapInterval(1);        // A structure that contains a rendering state.      SDL_Renderer * renderer = NULL;        // Use this function to create a 2D rendering context for a window.      renderer = SDL_CreateRenderer(screen, -1, SDL_RENDERER_ACCELERATED);   // [3]        // A structure that contains an efficient, driver-specific representation      // of pixel data.      SDL_Texture * texture = NULL;        // Use this function to create a texture for a rendering context.      texture = SDL_CreateTexture(  // [4]                  renderer,                  SDL_PIXELFORMAT_YV12,                  SDL_TEXTUREACCESS_STREAMING,                  640,                  360              );        while (!feof(f)) {          /* read raw data from the input file */          data_size = fread(inbuf, 1, INBUF_SIZE, f);          if (!data_size)              break;            /* use the parser to split the data into frames */          data = inbuf;          while (data_size > 0) {              ret = av_parser_parse2(parser, c, &pkt->data, &pkt->size,                                     data, data_size, AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0);              if (ret < 0) {                  fprintf(stderr, "Error while parsing\n");                  exit(1);              }              data      += ret;              data_size -= ret;                if (pkt->size)                  decode(c, frame, pkt, outfilename, screen, renderer, texture);          }      }        /* flush the decoder */      decode(c, frame, NULL, outfilename, screen, renderer, texture);        fclose(f);        av_parser_close(parser);      avcodec_free_context(&c);      av_frame_free(&frame);      av_packet_free(&pkt);        return 0;  }    

Is it possible to continuously play sdl in a browser?

https://stackoverflow.com/questions/66020171/how-can-i-display-the-video-on-sdl-converted-to-emscripten February 03, 2021 at 09:51AM

没有评论:

发表评论