FFDemux’s Open implementation opens media files

FFdemux Read frame data interface

Project Address:Github.com/popobo/BoPl…

It mainly adds three classes XData, IDemux and FFDemux. The specific implementation and functions are as follows

Data class: XData

  • This class is used to store interactive data produced by individual threads
  • Unsigned char *data Specifies the address of the data to be stored
  • Int size Specifies the size of the data to be stored
  • Void Drop() releases resources
//XData.h
#ifndef BOPLAY_XDATA_H
#define BOPLAY_XDATA_H

struct XData {
    unsigned char *data = 0;
    int size = 0;
    void Drop(a);
};

#endif //BOPLAY_XDATA_H
Copy the code
//XData.cpp
#include "XData.h"
extern "C"{
#include "libavformat/avformat.h"
}

void XData::Drop() {
    if(! data){return;
    }
    av_packet_free((AVPacket **)&data);
    data = 0;
    size = 0;
}
Copy the code

Unencapsulation interface classes: IDemux, the target abstract class for the adapter pattern, defines the ports required by the customer

  • Virtual bool Open(const char * URL) : The interface opens a file or streaming media link, unwraps it, and obtains basic audio and video information (such as encapsulation format, encoding format, and video duration, etc.). The parameter passed in is the local file address or streaming media URL
  • Virtual XData Read() : This interface is responsible for reading a frame of data and returning it
//IDemux.h
#ifndef BOPLAY_IDEMUX_H
#define BOPLAY_IDEMUX_H

#include "XData.h"

// Unpack the interface class
class IDemux {
public:
    // Open files or stream media RTMP HTTP RTSP
    virtual bool Open(const char *url) = 0;

    // Reads a frame of data, which is cleaned up by the caller
    virtual XData Read(a) = 0;

    // Total duration (ms)
    int totalMs = 0;
};

#endif //BOPLAY_IDEMUX_H
Copy the code
//IDemux.cpp
#include "IDemux.h"
Copy the code

Unencapsulation implementation class: FFDemux, the adapter class in the adapter pattern, the adapter can call another interface, as a converter, Adaptee and Target, the adapter class is the core of the adapter pattern, in the object adapter, it inherits Target and associates an Adaptee object to make the connection between the two. FFDemux calls FFmPEG

//FFDemux.h
#ifndef BOPLAY_FFDEMUX_H
#define BOPLAY_FFDEMUX_H

#include "IDemux.h"
// declare that there is no reference to the header file, and the caller does not need to know the ffmPEG header file after encapsulation
struct AVFormatContext;

class FFDemux: public IDemux{
public:
    // Open files or stream media RTMP HTTP RTSP
    virtual bool Open(const char *url);

    // Reads a frame of data, which is cleaned up by the caller
    virtual XData Read(a);

    FFDemux();

private:
    // This assignment is valid only if there is no argument constructor
    //AVFormatContext describes the composition and basic information of a media file or stream
    AVFormatContext *ic = 0;
};

#endif //BOPLAY_FFDEMUX_H
Copy the code
//FFDemux.cpp
#include "FFDemux.h"
#include "XLog.h"
extern "C"{
#include "libavformat/avformat.h"
}
bool FFDemux::Open(const char *url) {
    XLOGI("open url %s begin", url);
    int re = avformat_open_input(&ic, url, 0.0);
    if(re ! =0) {char buf[1024] = {0};
        av_strerror(re, buf, sizeof(buf));
        XLOGE("FFDemux open %s failed!", url);
        return false;
    }
    XLOGI("FFDemux open %s successfully!", url);

    // Read file information
    re = avformat_find_stream_info(ic, 0);
    if(re ! =0) {char buf[1024] = {0};
        av_strerror(re, buf, sizeof(buf));
        XLOGE("FFDemux avformat_find_stream_info %s failed!", url);
        return false;
    }
    Duration Unit of time, 1,000,000 times per second. This value may not exist because the information may be in the stream, not in the encapsulated header
    this->totalMs = ic->duration/(AV_TIME_BASE)*1000;
    XLOGI("total ms = %d", totalMs);

    return true;
}

// Read a frame of data
XData FFDemux::Read() {
    if(! ic){return XData();
    }
    XData xData;
    AVPacket *pkt = av_packet_alloc();
    int re = av_read_frame(ic, pkt);
    if(re ! =0){
        av_packet_free(&pkt);
        return XData();
    }
    XLOGI("pack size %d pts %lld", pkt->size, pkt->pts);
    xData.data = (unsigned char*)pkt;
    xData.size = pkt->size;


    return xData;
}

FFDemux::FFDemux() {
    // Do not create objects at the same time
    static bool isFirst = true;
    if (isFirst){
        isFirst = false;
        // Register all wrappers
        av_register_all();
        // Register all decoders
        avcodec_register_all();
        // Initialize the network
        avformat_network_init();
        XLOGI("register ffmpeg"); }}Copy the code