<div dir="ltr"><div class="gmail-adn gmail-ads"><div class="gmail-gs"><div class="gmail-"><div id="gmail-:1y8" class="gmail-ii gmail-gt gmail-adO"><div id="gmail-:1y7" class="gmail-a3s gmail-aiL"><div dir="ltr"><span class="gmail-VIiyi" lang="en"><span class="gmail-JLqJ4b gmail-ChMk0b"><span>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).</span></span></span> <br></div><div dir="ltr">i tested this code (below) but I noticed macroblocks and intolerable cuts in reception (unusable)<br>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?<br>+++++++++++++++++++++++++++++++++<br>#include <stdio.h><br>#include <stdlib.h><br>#include <stdbool.h><br>#include <time.h><br>#include <windows.h><br>#include <libavcodec/avcodec.h><br>#include <libavformat/avformat.h><br>#include <SDL.h><br><br>void display(AVCodecContext* ctx, AVPacket* pkt, AVFrame* frame, SDL_Rect* rect,<br> SDL_Texture* texture, SDL_Renderer* renderer, double fpsrend);<br><br>int main(int argc, char* argv[]) {<br> <br> char* url = "rtp://<a href="http://192.168.3.3:5501" target="_blank">192.168.3.3:5501</a>"; //src rtp stream mpeg ts dvb-s<br> // ffmpeg part<br> AVFormatContext* pFormatCtx;<br> AVFormatContext* ppf;<br> int vidId = -1;<br> double fpsrendering = 0.0;<br> AVCodecContext* vidCtx;<br> AVCodec* vidCodec=NULL;<br> AVCodecParameters* vidpar=NULL;<br> AVFrame* vframe;<br> AVPacket* packet=NULL;<br> <br> //sdl part<br> int swidth, sheight;<br> SDL_Window* screen;<br> SDL_Renderer* renderer;<br> SDL_Texture* texture;<br> SDL_Rect rect;<br> //SDL_AudioDeviceID auddev;<br> //SDL_AudioSpec want, have;<br><br> SDL_Init(SDL_INIT_EVERYTHING);<br> pFormatCtx = avformat_alloc_context();<br> ppf = avformat_alloc_context();<br> // char bufmsg[1024];<br><br> if (avformat_open_input(&pFormatCtx, url , NULL, NULL) < 0) {<br> printf("Cannot open %s", url);<br> <br> }<br> if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {<br> perror("Cannot find stream info. Quitting.");<br> goto clean_format_context;<br> }<br><br> int val = avformat_flush(pFormatCtx);<br> //int p = pFormatCtx->programs->program_num==54;<br> bool foundVideo = false;<br> for (int i = 0; i < pFormatCtx->nb_streams; i++)<br> {<br> AVCodecParameters* localparam = pFormatCtx->streams[i]->codecpar;<br> AVCodec* localcodec = avcodec_find_decoder(localparam->codec_id);<br>
if (localparam->codec_type == AVMEDIA_TYPE_VIDEO &&
localparam->codec_id == AV_CODEC_ID_MPEG2VIDEO &&
!foundVideo) {<br> vidCodec = localcodec;<br> vidpar = localparam;<br> vidId = i;<br> AVRational rational = pFormatCtx->streams[i]->avg_frame_rate;<br> fpsrendering = 1.0 / ((double)rational.num / (double)(rational.den));<br> foundVideo = true;<br> }<br> if (foundVideo) { break; }<br> }<br> <br><br><br> vidCtx = avcodec_alloc_context3(vidCodec);<br><br> if (avcodec_parameters_to_context(vidCtx, vidpar) < 0) {<br> perror("vidCtx");<br> goto clean_codec_context;<br> }<br><br> if (avcodec_open2(vidCtx, vidCodec, NULL) < 0) {<br> perror("vidCtx");<br> goto clean_codec_context;<br> }<br><br> vframe = av_frame_alloc();<br><br> packet = av_packet_alloc();<br> swidth = vidpar->width;<br> sheight = vidpar->height;<br> screen = SDL_CreateWindow("ouldji_V", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,<br> swidth, sheight, SDL_WINDOW_RESIZABLE);<br> if (!screen) {<br> perror("screen");<br> goto clean_packet_frame;<br> }<br> renderer = SDL_CreateRenderer(screen, -1, SDL_RENDERER_ACCELERATED);<br> if (!renderer) {<br> perror("renderer");<br> goto clean_renderer;<br> }<br> texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_IYUV,<br> SDL_TEXTUREACCESS_STREAMING | SDL_TEXTUREACCESS_TARGET,<br> swidth, sheight);<br> if (!texture) {<br> perror("texture");<br> goto clean_texture;<br> }<br> rect.x = 0;<br> rect.y = 0;<br> rect.w = swidth;<br> rect.h = sheight;<br><br> SDL_Event evt;<br> uint32_t windowID = SDL_GetWindowID(screen);<br> bool running = true;<br> while (running) {<br> while (av_read_frame(pFormatCtx, packet) >= 0)<br> {<br> while (SDL_PollEvent(&evt))<br> {<br> switch (evt.type) {<br> case SDL_WINDOWEVENT: {<br> if (evt.window.windowID == windowID) {<br> switch (evt.window.event) {<br> case SDL_WINDOWEVENT_CLOSE: {<br> evt.type = SDL_QUIT;<br> running = false;<br> SDL_PushEvent(&evt);<br> break;<br> }<br> };<br> }<br> break;<br> }<br> case SDL_QUIT: {<br> running = false;<br> break;<br> }<br> }<br> }<br><br> if (packet->stream_index == vidId) {<br> display(vidCtx, packet, vframe, &rect,<br> texture, renderer, fpsrendering);<br><br> }<br> av_packet_unref(packet);<br> }<br> }<br><br><br> //clean_audio_device:<br> // SDL_CloseAudioDevice(auddev);<br>clean_texture:<br> SDL_DestroyTexture(texture);<br>clean_renderer:<br> SDL_DestroyRenderer(renderer);<br> SDL_DestroyWindow(screen);<br>clean_packet_frame:<br> av_packet_free(&packet);<br> av_frame_free(&vframe);<br> //av_frame_free(&aframe);<br>clean_codec_context:<br> avcodec_free_context(&vidCtx);<br> // avcodec_free_context(&audCtx);<br>clean_format_context:<br> avformat_close_input(&pFormatCtx);<br> avformat_free_context(pFormatCtx);<br><br> SDL_Quit();<br> // free(mtsc);<br> return 0;<br>}<br><br><br>void display(AVCodecContext* ctx, AVPacket* pkt, AVFrame* frame, SDL_Rect* rect,<br> SDL_Texture* texture, SDL_Renderer* renderer, double fpsrend)<br>{<br> time_t start = time(NULL);<br> if (avcodec_send_packet(ctx, pkt) < 0) {<br> perror("send packet");<br> return;<br> }<br> if (avcodec_receive_frame(ctx, frame) < 0) {<br> perror("receive frame");<br> return;<br> }<br> int framenum = ctx->frame_number;<br> if ((framenum % 1000) == 0) {<br> printf("Frame %d (size=%d pts %lld dts %lld key_frame %d"<br> " [ codec_picture_number %d, display_picture_number %d\n",<br> framenum, frame->pkt_size, frame->pts, frame->pkt_dts, frame->key_frame,<br> frame->coded_picture_number, frame->display_picture_number);<br> }<br> SDL_UpdateYUVTexture(texture, rect,<br> frame->data[0], frame->linesize[0],<br> frame->data[1], frame->linesize[1],<br> frame->data[2], frame->linesize[2]);<br> SDL_RenderClear(renderer);<br> SDL_RenderCopy(renderer, texture, NULL, rect);<br> SDL_RenderPresent(renderer);<br> time_t end = time(NULL);<br> double diffms = difftime(end, start) / 1000.0;<br> if (diffms < fpsrend) {<br> uint32_t diff = (uint32_t)((fpsrend - diffms) * 1000);<br> printf("diffms: %f, delay time %d ms.\n", diffms, diff);<br> SDL_Delay(diff);<br> }<br>}<div class="gmail-yj6qo gmail-ajU"><div id="gmail-:1ym" class="gmail-ajR" tabindex="0"><img class="gmail-ajT" src="https://ssl.gstatic.com/ui/v1/icons/mail/images/cleardot.gif"></div></div></div></div></div></div></div></div><div class="gmail-gA gmail-gt gmail-acV"><div class="gmail-gB gmail-xu"><div class="gmail-ip gmail-iq"><div id="gmail-:1y9"><table class="gmail-cf gmail-wS"><tbody><tr><td class="gmail-amq"><img id="gmail-:x2_30" name=":x2" src="https://lh3.googleusercontent.com/a-/AOh14GjhJXJQSSLA_wzqks8nkqCQ_jeiLZ2O_pYwcUnB=s40" class="gmail-ajn gmail-bofPge"></td><td class="gmail-amr"><br></td></tr></tbody></table></div></div></div></div></div>