[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