ffmpeg and sdl library implement video decoding and playback

1. Interpretation of steps

1.1 SDL initialization, initialize the subsystems in SDL. The specific parameters are as follows:

1.2 Opening multimedia files:

Parameters: 1. ps: directly defines the pointer of the AVFormatContext class (null pointer)

2. filename: the path of the audio file

1.3 Get the message of the audio file:

1.4: Get stream encoding

By looping through the audio stream, obtain the encoding of the stream that needs to be decoded.

The types of streams are:

  1. AVMEDIA_TYPE_UNKNOWN: Unknown type. Typically treated as AVMEDIA_TYPE_DATA (data type).
  2. AVMEDIA_TYPE_VIDEO: Video stream type. Used to represent video data in multimedia files.
  3. AVMEDIA_TYPE_AUDIO: Audio stream type. Used to represent audio data in multimedia files.
  4. AVMEDIA_TYPE_DATA: Data stream type. Used to represent opaque data information in multimedia files, usually continuous.
  5. AVMEDIA_TYPE_SUBTITLE: Subtitle stream type. Used to represent subtitle data in multimedia files.
  6. AVMEDIA_TYPE_ATTACHMENT: Attachment stream type. Used to represent opaque data information in multimedia files, usually sparse.
 for(int i=0;i<(int)avformat_context->nb_streams; + + i)
    {

        if(avformat_context->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
        {
            videoStream = i;
        }
    }

1.5 Get the decoder

1.5.1 Create decoding context

 pCodecCtx = avcodec_alloc_context3(NULL);
    if (pCodecCtx == NULL)
    {
        printf("Could not allocate AVCodecContext\
");
        return;
    }

1.5.2 Copy codec parameters

 if (avcodec_parameters_to_context(pCodecCtx, pFormatCtx->streams[audioindex]->codecpar) < 0)
    {
        printf("Could not init AVCodecContext\
");
        return;
    }

pFormatCtx->streams[audioindex]->codecpar represents the codec parameters of audio and video streams.

1.5.3 Get the decoder

 pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
    if (pCodec == NULL) {
        printf("Codec not found.\
");
        return;
    }
  • Use the avcodec_find_decoder function to find the corresponding decoder based on the encoder ID (pCodecCtx->codec_id) in the decoding context.

1.6 Open the decoder

1.7 SDL_CreateWindow` function is used to create a window

extern DECLSPEC SDL_Window * SDLCALL SDL_CreateWindow(const char *title,
                                                      int x, int y, int w,
                                                      int h, Uint32 flags);
parameter:
    x, window x coordinate; y, window y coordinate; w, window width; h, window height;
    flags, window attributes (select attributes on enumeration SDL_WindowFlags) 

1.8 The `SDL_CreateRenderer` function is used to create a renderer.

extern DECLSPEC SDL_Renderer * SDLCALL SDL_CreateRenderer(SDL_Window * window,
                                               int index, Uint32 flags);
parameter;
    window: the rendered window
    index: - `-1`: Index of the renderer, indicating to use the first supported renderer.
               - `0`: The flag of the renderer, which means there is no special flag.
    flags: Select attributes on the enumeration SDL_RendererFlags

1.9 The `SDL_CreateTexture` function is used to create a texture.

extern DECLSPEC SDL_Texture * SDLCALL SDL_CreateTexture(SDL_Renderer * renderer,
                                                        Uint32 format,
                                                        int access, int w,
                                                        int h);
parameter:
    renderer: the renderer on which to create the texture
    format: The pixel format of the texture, here IYUV format is used (enumeration SDL_PixelFormatEnum)
    access: The access method of the texture, which means that the texture can be accessed through the stream (enumeration SDL_TextureAccess)
    W: The width of the texture, using the width of the decoder context
    h: The height of the texture, using the height of the decoder context

1.10 The `sws_getContext` function is used to create an image conversion context.

struct SwsContext *sws_getContext(int srcW, int srcH, enum AVPixelFormat srcFormat,
                                  int dstW, int dstH, enum AVPixelFormat dstFormat,
                                  int flags, SwsFilter *srcFilter,
                                  SwsFilter *dstFilter, const double *param);

parameter:
    srcW: width of input image
    srcH: height of input image
    enum AVPixelFormat srcFormat: pixel format of the input image
    dstW: width of the output image
    dstH: height of the output image
    enum AVPixelFormat dstFormat: pixel format of the output image
    flags: Specify the algorithm and options to use for rescaling
    SwsFilter *srcFilter: Row size of source image (NULL is automatically calculated)
    SwsFilter *dstFilter: row size of the target image (NULL is automatically calculated)
    const double *param: additional options

1.11 The `av_image_alloc` function is used to allocate an image data buffer

int av_image_alloc(uint8_t *pointers[4], int linesizes[4],
                   int w, int h, enum AVPixelFormat pix_fmt, int align);
parameter:
    pointers[4]: array of pointers pointing to image data
    linesizes[4]: array pointing to image data line sizes
    w: width of the image
    h: height of the image
    pix_fmt: pixel format of the image
    align: Alignment of image data (align the value to be used for buffer size alignment)

1.12 Read data (12 to 18 are implemented in a loop)

int av_read_frame(AVFormatContext *s, AVPacket *pkt);
parameter:
    s:AVFormatContext structure, representing the format context of the video file.
    pkt: AVPacket structure, used to store read data packets. (Need to open up heap space)

1.13 Data decoding

int avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt);
parameter:
    avctx:AVCodecContext structure, representing the context of the decoder
    avpkt:AVPacket structure, the data packet to be sent
Function: Submit the data packet to the decoder
int avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame);
parameter:
    avctx:AVCodecContext structure, representing the context of the decoder
    frame: AVFrame structure, used to store received frame data.
Function: Read from decoder, decode data

frame is created by av_frame_alloc()

1.14 Convert decoded frame data to target format

int sws_scale(struct SwsContext *c, const uint8_t *const srcSlice[],
              const int srcStride[], int srcSliceY, int srcSliceH,
              uint8_t *const dst[], const int dstStride[]);

parameter:
    c: SwsContext structure, representing the image conversion context
    srcSlice: decoded frame data
    srcStride: The size of each line of decoded frame data
    srcSliceY: the starting line of the source image
    srcSliceH: Number of lines of source image
    dst: array of pointers to target image data
    dstStride: The size of each row of target image data

1.15. Update texture data

extern DECLSPEC int SDLCALL SDL_UpdateYUVTexture(SDL_Texture * texture,
                                                 const SDL_Rect * rect,
                                                 const Uint8 *Yplane, int Ypitch,
                                                 const Uint8 *Uplane, int Upitch,
                                                 const Uint8 *Vplane, int Vpitch);
parameter:
    texture: the texture to be updated
    rect: plane raw data
    Yplane: Y component data
    Ypitch: The size of each line of the Y component
    Uplane: U component data
    Upitch: The size of each row of the U component
    Vplane:V component data
    Vpitch: The size of each line of the V component
Function: YUV data texture update

1.16 Clear renderer

extern DECLSPEC int SDLCALL SDL_RenderClear(SDL_Renderer * renderer);

Parameters: renderer: clear renderer name

1.17 Copy the texture to the renderer’s render target

extern DECLSPEC int SDLCALL SDL_RenderCopy(SDL_Renderer * renderer,
                                           SDL_Texture * texture,
                                           const SDL_Rect * srcrect,
                                           const SDL_Rect * dstrect);
parameter:
    renderer: renderer name
    texture: the name of the texture to be copied
    srcrect: source rectangle, indicating copying the entire texture
    dstrect: target rectangle, indicating the position and size copied to the renderer
Note:
    dstect needs to set coordinates (x, y) and length and width

1.18 The renderer’s render target is rendered to the window

SDL_RenderPresent(renderer);
SDL_Delay(1000 / 30);

1.19 Destruction

SDL_DestroyTexture(texture); used to destroy SDL texture
SDL_DestroyRenderer(renderer); used to destroy the SDL renderer
SDL_DestroyWindow(window); used to destroy the SDL window
SDL_Quit(); used to terminate the use of the SDL library and release the resources occupied by SDL