Daher möchte ich dasselbe mit der Programmierung in C/C++ erreichen ffmpeg Bücherei. Ich denke, das muss möglich sein.
Lassen Sie mich also zwei einfache Fragen formulieren:
Wie erhalte ich den Stream in einem C/C++-Programm mit der FFMPEG-Bibliothek? (Geben Sie einfach eine URL/ein Tutorial an, da Google nicht hilfreich war)
Wie zeige ich das empfangene Video an? (dasselbe hier, eine gute URL, um mich zu leiten).
Für rtsp-Streams funktioniert bei mir Folgendes (nach dem Empfangen von Frames speichere ich das Ergebnis in einer ppm-Datei):
danke für die Antwort. Ich habe ffmpeg und x264 im Anschluss installiert diese Anweisungen. Die Installation ist erfolgreich und die Bibliotheken werden in /usr/lib meines Ubuntu-Systems installiert. Und wenn ich versuche, Ihren Code (von /home/bhanu/main.cpp) mit Aber ich habe einige Probleme mit entsprechenden Flags zu kompilieren, erhalte ich immer wieder Linker-Fehler. Ich werde sie posten, bitte führen Sie mich, was/wo der Fehler sein könnte?
– Bhanu Kiran
13. Juli 12 um 14:03 Uhr
Der Befehl, den ich verwende, ist g++ main.cpp -lavcodec -lavdevice -lavfilter -lavformat -lavutil -logg -lrtmp -lswscale -lx264 -lpthread -lvorbis -L/usr/lib, erhalte ich die folgende Ausgabe main.cpp: In function 'int main(int, char**)': /home/bhanu/work_environment/softwares/ffmpeg/libavformat/allformats.c:49: undefined reference to 'avcodec_register_all' /usr/lib/libavformat.a(oggparsevorbis.o): In function 'vorbis_packet': collect2: ld returned 1 exit status und wenige ähnliche Fehler. Bitte Link beachten Hier für die vollständige Compilerausgabe.
– Bhanu Kiran
13. Juli 12 um 14:17 Uhr
cnt <1000) {//read 100 frames es sieht so aus, als würde der Code stattdessen 1000 Frames lesen …
– Pimgd
19. August 14 um 14:59 Uhr
Ich habe einen Kern für die Fehlerprotokolle erstellt, die während der Dekodierung des RTSP-Streams mit FFMPEG generiert werden. gist.github.com/anonymous/64b3df25b7f103c0da54 Irgendeine Idee, wie man die obigen Fehlerprotokolle löst. Das angezeigte Bild ist verschwommen.
– Tarik
27. Juni 15 um 11:46 Uhr
@technique Das war hilfreich für mich und ich habe eine aktualisierte Version als neue Antwort hinzugefügt, die mit Bibliotheken mit ffmpeg 3.2.2 funktioniert, falls jemand dies über Google findet. Sie haben einige der Funktionen und Aufzählungen geändert, die mich zuerst für eine Schleife warfen.
– synthetisch
11. Januar 17 um 18:13 Uhr
synthetisch
FWIW, ich habe den von @technique bereitgestellten Code aktualisiert, um mit den Bibliotheken zu arbeiten, die ich von FFMPEG 3.2.2 habe. Hoffentlich hilft das jemandem, der das googelt. Es gibt einige kleine Änderungen, die für Leute, die über diese Antwort stolpern, verwirrend sein könnten.
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <fstream>
#include <sstream>
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavformat/avio.h>
#include <libswscale/swscale.h>
}
int main(int argc, char** argv) {
// Open the initial context variables that are needed
SwsContext *img_convert_ctx;
AVFormatContext* format_ctx = avformat_alloc_context();
AVCodecContext* codec_ctx = NULL;
int video_stream_index;
// Register everything
av_register_all();
avformat_network_init();
//open RTSP
if (avformat_open_input(&format_ctx, "rtsp://134.169.178.187:8554/h264.3gp",
NULL, NULL) != 0) {
return EXIT_FAILURE;
}
if (avformat_find_stream_info(format_ctx, NULL) < 0) {
return EXIT_FAILURE;
}
//search video stream
for (int i = 0; i < format_ctx->nb_streams; i++) {
if (format_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
video_stream_index = i;
}
AVPacket packet;
av_init_packet(&packet);
//open output file
AVFormatContext* output_ctx = avformat_alloc_context();
AVStream* stream = NULL;
int cnt = 0;
//start reading packets from stream and write them to file
av_read_play(format_ctx); //play RTSP
// Get the codec
AVCodec *codec = NULL;
codec = avcodec_find_decoder(AV_CODEC_ID_H264);
if (!codec) {
exit(1);
}
// Add this to allocate the context by codec
codec_ctx = avcodec_alloc_context3(codec);
avcodec_get_context_defaults3(codec_ctx, codec);
avcodec_copy_context(codec_ctx, format_ctx->streams[video_stream_index]->codec);
std::ofstream output_file;
if (avcodec_open2(codec_ctx, codec, NULL) < 0)
exit(1);
img_convert_ctx = sws_getContext(codec_ctx->width, codec_ctx->height,
codec_ctx->pix_fmt, codec_ctx->width, codec_ctx->height, AV_PIX_FMT_RGB24,
SWS_BICUBIC, NULL, NULL, NULL);
int size = avpicture_get_size(AV_PIX_FMT_YUV420P, codec_ctx->width,
codec_ctx->height);
uint8_t* picture_buffer = (uint8_t*) (av_malloc(size));
AVFrame* picture = av_frame_alloc();
AVFrame* picture_rgb = av_frame_alloc();
int size2 = avpicture_get_size(AV_PIX_FMT_RGB24, codec_ctx->width,
codec_ctx->height);
uint8_t* picture_buffer_2 = (uint8_t*) (av_malloc(size2));
avpicture_fill((AVPicture *) picture, picture_buffer, AV_PIX_FMT_YUV420P,
codec_ctx->width, codec_ctx->height);
avpicture_fill((AVPicture *) picture_rgb, picture_buffer_2, AV_PIX_FMT_RGB24,
codec_ctx->width, codec_ctx->height);
while (av_read_frame(format_ctx, &packet) >= 0 && cnt < 1000) { //read ~ 1000 frames
std::cout << "1 Frame: " << cnt << std::endl;
if (packet.stream_index == video_stream_index) { //packet is video
std::cout << "2 Is Video" << std::endl;
if (stream == NULL) { //create stream in file
std::cout << "3 create stream" << std::endl;
stream = avformat_new_stream(output_ctx,
format_ctx->streams[video_stream_index]->codec->codec);
avcodec_copy_context(stream->codec,
format_ctx->streams[video_stream_index]->codec);
stream->sample_aspect_ratio =
format_ctx->streams[video_stream_index]->codec->sample_aspect_ratio;
}
int check = 0;
packet.stream_index = stream->id;
std::cout << "4 decoding" << std::endl;
int result = avcodec_decode_video2(codec_ctx, picture, &check, &packet);
std::cout << "Bytes decoded " << result << " check " << check
<< std::endl;
if (cnt > 100) //cnt < 0)
{
sws_scale(img_convert_ctx, picture->data, picture->linesize, 0,
codec_ctx->height, picture_rgb->data, picture_rgb->linesize);
std::stringstream file_name;
file_name << "test" << cnt << ".ppm";
output_file.open(file_name.str().c_str());
output_file << "P3 " << codec_ctx->width << " " << codec_ctx->height
<< " 255n";
for (int y = 0; y < codec_ctx->height; y++) {
for (int x = 0; x < codec_ctx->width * 3; x++)
output_file
<< (int) (picture_rgb->data[0]
+ y * picture_rgb->linesize[0])[x] << " ";
}
output_file.close();
}
cnt++;
}
av_free_packet(&packet);
av_init_packet(&packet);
}
av_free(picture);
av_free(picture_rgb);
av_free(picture_buffer);
av_free(picture_buffer_2);
av_read_pause(format_ctx);
avio_close(output_ctx->pb);
avformat_free_context(output_ctx);
return (EXIT_SUCCESS);
}
Es kann durch etwas kompiliert werden mit dem Effekt von:
Ich schließe die ein -w da es viele Verfallswarnungen für diese Funktionen in der Bibliothek gibt. Sie müssen pkg-config sowie die Bibliotheken libavcodec, libavformat, libswscale und libavutil installiert haben. (h/t @BobCheng für fehlende Bibliotheken).
Seit deinem Update hat sich einiges geändert. Bitte erwägen Sie, eine neue Version hinzuzufügen. Danke 🙂
– Folkert van Heusden
10. August 17 um 11:22 Uhr
@FolkertvanHeusden Ich arbeite nur mit 3.2.2 (und das musste ich schon lange nicht mehr), also bin ich leider nicht auf dem Laufenden über neue Funktionen oder Änderungen 🙁
– synthetisch
9. Mai 18 um 14:26 Uhr
Kleine Änderung: Sie benötigen libavcodec & libavutil, um erfolgreich zu kompilieren: g++ -w my_streamer.cpp -o my_streamer $(pkg-config –cflags –libs libavcodec libavformat libswscale libavutil)
– Bob Cheng
6. Januar 21 um 8:17 Uhr
Schätzen Sie es @BobCheng – ich bin mir nicht sicher, ob mein Setup es mir erlaubt hat, diese aus irgendeinem Grund nicht einzuschließen, aber trotzdem funktioniert. Ich habe es der Antwort für alle, die es kopieren/einfügen, hinzugefügt
– synthetisch
7. Januar 21 um 18:10 Uhr
Qin Peixi
FFmpeg kann rtsp-Streams direkt öffnen, genau wie das Öffnen lokaler Videodateien. Hier ist ein Tutorial-Code, der mit der neuesten Version von FFmpeg aktualisiert wird.
Prashant
Überprüfen Sie Ihre ./configure-Datei. Kann sein, dass es kompiliert wird armlinux nicht für die x86. Deshalb erhalten Sie einen undefinierten Verweis auf 'avcodec_register_all'
Hier ist die Lösung: –
$ cd ffmpeg
$export LD_RUN_PATH=/usr/local/lib:/usr/lib:/lib
$ ./configure
$ make && make install
Und danach stellen Sie Ihre Bewerbung zusammen.
.
6047900cookie-checkEmpfangen des RTSP-Streams mit der FFMPEG-Bibliothekyes