[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