[Libav-user] how can i get psi/si table for mpeg-ts stream

David Get houldji at gmail.com
Thu May 20 00:11:22 EEST 2021


I am looking to develop an application which demux and decodes an mpeg ts
stream in real time for a multi-viewer (reception multi services tv).
i tested this code (below) but I noticed macroblocks and intolerable cuts
in reception (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 ? how to get
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"; //src rtp stream mpeg ts dvb-s
    // 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);
    }
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://ffmpeg.org/pipermail/libav-user/attachments/20210519/3fd94de1/attachment.htm>


More information about the Libav-user mailing list