[Libav-user] struct MpegTSContext

David Get houldji at gmail.com
Wed May 19 16:33:12 EEST 2021


My goal is to develop an application which demux and decodes a real-time
multiservice mpeg-ts stream (mcpc dvb-s) to create a multi-viewer and an
alarm manager.
I tested this code (below) but I noticed macroblocks and intolerable cuts
(unusable)
In my opinion, the problem is that I have to read the psi / si table well
to recover the data necessary for the demuxing and decoding, the thing that
I could not do with the libav functions? Are there any APIs or functions
that make it easier for me? how to recover the psi / si table?
+++++++++++++++++++++++++++++++++
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <time.h>
#include <windows.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <SDL.h>

void display(AVCodecContext* ctx, AVPacket* pkt, AVFrame* frame, SDL_Rect*
rect,
    SDL_Texture* texture, SDL_Renderer* renderer, double fpsrend);

int main(int argc, char* argv[]) {

    char* url = "rtp://192.168.3.3:5501";
    // ffmpeg part
    AVFormatContext* pFormatCtx;
    AVFormatContext* ppf;
    int vidId = -1;
    double fpsrendering = 0.0;
    AVCodecContext* vidCtx;
    AVCodec* vidCodec=NULL;
    AVCodecParameters* vidpar=NULL;
    AVFrame* vframe;
    AVPacket* packet=NULL;

     //sdl part
    int swidth, sheight;
    SDL_Window* screen;
    SDL_Renderer* renderer;
    SDL_Texture* texture;
    SDL_Rect rect;
    //SDL_AudioDeviceID auddev;
    //SDL_AudioSpec want, have;

    SDL_Init(SDL_INIT_EVERYTHING);
    pFormatCtx = avformat_alloc_context();
    ppf = avformat_alloc_context();
   // char bufmsg[1024];

    if (avformat_open_input(&pFormatCtx, url , NULL, NULL) < 0) {
        printf("Cannot open %s", url);

    }
    if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {
        perror("Cannot find stream info. Quitting.");
        goto clean_format_context;
    }

    int val = avformat_flush(pFormatCtx);
    //int p = pFormatCtx->programs->program_num==54;
    bool foundVideo = false;
    for (int i = 0; i < pFormatCtx->nb_streams; i++)
    {
        AVCodecParameters* localparam = pFormatCtx->streams[i]->codecpar;
        AVCodec* localcodec = avcodec_find_decoder(localparam->codec_id);
        if (localparam->codec_type == AVMEDIA_TYPE_VIDEO &&
localparam->codec_id == AV_CODEC_ID_MPEG2VIDEO && !foundVideo) {
            vidCodec = localcodec;
            vidpar = localparam;
            vidId = i;
            AVRational rational = pFormatCtx->streams[i]->avg_frame_rate;
            fpsrendering = 1.0 / ((double)rational.num /
(double)(rational.den));
            foundVideo = true;
        }
        if (foundVideo) { break; }
    }



    vidCtx = avcodec_alloc_context3(vidCodec);

    if (avcodec_parameters_to_context(vidCtx, vidpar) < 0) {
        perror("vidCtx");
        goto clean_codec_context;
    }

    if (avcodec_open2(vidCtx, vidCodec, NULL) < 0) {
        perror("vidCtx");
        goto clean_codec_context;
    }

    vframe = av_frame_alloc();

    packet = av_packet_alloc();
    swidth = vidpar->width;
    sheight = vidpar->height;
    screen = SDL_CreateWindow("ouldji_V", SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
        swidth, sheight, SDL_WINDOW_RESIZABLE);
    if (!screen) {
        perror("screen");
        goto clean_packet_frame;
    }
    renderer = SDL_CreateRenderer(screen, -1, SDL_RENDERER_ACCELERATED);
    if (!renderer) {
        perror("renderer");
        goto clean_renderer;
    }
    texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_IYUV,
        SDL_TEXTUREACCESS_STREAMING | SDL_TEXTUREACCESS_TARGET,
        swidth, sheight);
    if (!texture) {
        perror("texture");
        goto clean_texture;
    }
    rect.x = 0;
    rect.y = 0;
    rect.w = swidth;
    rect.h = sheight;

    SDL_Event evt;
    uint32_t windowID = SDL_GetWindowID(screen);
    bool running = true;
    while (running) {
        while (av_read_frame(pFormatCtx, packet) >= 0)
        {
            while (SDL_PollEvent(&evt))
            {
                switch (evt.type) {
                case SDL_WINDOWEVENT: {
                    if (evt.window.windowID == windowID) {
                        switch (evt.window.event) {
                        case SDL_WINDOWEVENT_CLOSE: {
                            evt.type = SDL_QUIT;
                            running = false;
                            SDL_PushEvent(&evt);
                            break;
                        }
                        };
                    }
                    break;
                }
                case SDL_QUIT: {
                    running = false;
                    break;
                }
                }
            }

            if (packet->stream_index == vidId) {
                display(vidCtx, packet, vframe, &rect,
                    texture, renderer, fpsrendering);

            }
            av_packet_unref(packet);
        }
    }


    //clean_audio_device:
   // SDL_CloseAudioDevice(auddev);
clean_texture:
    SDL_DestroyTexture(texture);
clean_renderer:
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(screen);
clean_packet_frame:
    av_packet_free(&packet);
    av_frame_free(&vframe);
    //av_frame_free(&aframe);
clean_codec_context:
    avcodec_free_context(&vidCtx);
    // avcodec_free_context(&audCtx);
clean_format_context:
    avformat_close_input(&pFormatCtx);
    avformat_free_context(pFormatCtx);

    SDL_Quit();
  //  free(mtsc);
    return 0;
}


void display(AVCodecContext* ctx, AVPacket* pkt, AVFrame* frame, SDL_Rect*
rect,
    SDL_Texture* texture, SDL_Renderer* renderer, double fpsrend)
{
    time_t start = time(NULL);
    if (avcodec_send_packet(ctx, pkt) < 0) {
        perror("send packet");
        return;
    }
    if (avcodec_receive_frame(ctx, frame) < 0) {
        perror("receive frame");
        return;
    }
    int framenum = ctx->frame_number;
    if ((framenum % 1000) == 0) {
        printf("Frame %d (size=%d pts %lld dts %lld key_frame %d"
            " [ codec_picture_number %d, display_picture_number %d\n",
            framenum, frame->pkt_size, frame->pts, frame->pkt_dts,
frame->key_frame,
            frame->coded_picture_number, frame->display_picture_number);
    }
    SDL_UpdateYUVTexture(texture, rect,
        frame->data[0], frame->linesize[0],
        frame->data[1], frame->linesize[1],
        frame->data[2], frame->linesize[2]);
    SDL_RenderClear(renderer);
    SDL_RenderCopy(renderer, texture, NULL, rect);
    SDL_RenderPresent(renderer);
    time_t end = time(NULL);
    double diffms = difftime(end, start) / 1000.0;
    if (diffms < fpsrend) {
        uint32_t diff = (uint32_t)((fpsrend - diffms) * 1000);
        printf("diffms: %f, delay time %d ms.\n", diffms, diff);
        SDL_Delay(diff);
    }
}

Le mar. 18 mai 2021 à 11:02, Nicolas George <george at nsup.org> a écrit :

> David Get (12021-05-17):
> > I am looking to develop an application in c / c ++ which demux and
> decodes
> > a mpeg ts stream in real time and which contains several tv and radio
> > services (mcpc dvb-s), for that I opted to operate the ffmpeg library. I
> > work under the unix environment, I installed the library well and I
> > succeeded in demuxing and decoding video and audio using the libavformat.
>
> Good.
>
> > however, when I see the include / libavformat folder I can't find all the
> > headers I need such as mpegts.h mpeg.h .... (I find avformat.h, avio.h
> and
> > internal.h)!
> > Is adding headers manually in the libavformation folder correct or not?
> if
> > so why can't I load the MpegTsContext structure with the MpegTSContext *
> > function avpriv_mpegts_parse_open (AVFormatContext * s)?
>
> These headers and functions are not public, they are there to implement
> the workings of the FFmpeg libraries, but they are not available to
> applications programmers. Only functions and structures whose name
> starts in AV are available to you. And not functions whose name starts
> with avpriv, that should be pretty obvious.
>
> Since FFmpeg is Libre Software, you are obviously free to take the
> source code and make anything you need available to you. But if you do
> that:
>
> 1. It is unlikely you will get help for that.
>
> 2. We will not take your needs into consideration. If we need to change
> these structures, and it breaks your project, that would be your
> problem.
>
> > How to track the PIDs of each TV and radio service in real time?
>
> A much better solution would be for you to describe exactly what you
> want to do (I am personally not versed in MPEG-TS enough), what you
> tried with the public API and how you think it is not sufficient.
>
> Regards,
>
> --
>   Nicolas George
> _______________________________________________
> Libav-user mailing list
> Libav-user at ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/libav-user
>
> To unsubscribe, visit link above, or email
> libav-user-request at ffmpeg.org with subject "unsubscribe".
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://ffmpeg.org/pipermail/libav-user/attachments/20210519/f7c8d58c/attachment.htm>


More information about the Libav-user mailing list