70 / 14 / 3
Регистрация: 10.07.2018
Сообщений: 284
1

FFmpeg - нужна консультация, как я могу узнать что кадр был прочитан?

06.01.2023, 14:56. Показов 1179. Ответов 4
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
FFmpeg - читаю с ip камеры данные. Пока не могу обидится в том что они действительно читаются. Заметил что в строке №198 вылетает с кодом (минус) цыфра рэндомная.


C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
#include <Windows.h>
 
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <fstream>
#include <cstring>
#include <math.h>
#include <string.h>
 
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include <libavformat/avio.h>
 
#include "libavutil/imgutils.h"
#include "libavutil/opt.h"
 
#include <libavutil/imgutils.h>
#include <libavutil/samplefmt.h>
#include <libavutil/timestamp.h>
#include <libavformat/avformat.h>
#include <libswresample/swresample.h>
 
    //============================
 
#include "libavcodec/avcodec.h"
#include "libavcodec/avfft.h"
 
#include "libavdevice/avdevice.h"
 
#include "libavfilter/avfilter.h"
//#include "libavfilter/avfiltergraph.h"
#include "libavfilter/buffersink.h"
#include "libavfilter/buffersrc.h"
 
#include "libavformat/avformat.h"
#include "libavformat/avio.h"
 
// libav resample
 
#include "libavutil/opt.h"
#include "libavutil/common.h"
#include "libavutil/channel_layout.h"
#include "libavutil/imgutils.h"
#include "libavutil/mathematics.h"
#include "libavutil/samplefmt.h"
#include "libavutil/time.h"
#include "libavutil/opt.h"
#include "libavutil/pixdesc.h"
#include "libavutil/file.h"
 
// lib swresample
 
#include "libswscale/swscale.h"
 
#include <libavutil/imgutils.h>
#include <libavutil/samplefmt.h>
#include <libavutil/timestamp.h>
#include <libavformat/avformat.h>
 
}
#define INBUF_SIZE 4096
 
int main(int argc, char* argv[])
{
    setlocale(LC_ALL, "Rus");
 
    const char* filename, * outfilename;
    const AVCodec* codec = NULL;
    AVCodecParserContext* parser;
 
    // содержит данные о конфигурации медиаконтента, такой как битрейт, 
    // частота кадров, частота дискретизации, каналы, высота и многое другое.
    AVCodecContext* AVCodecContext_ = NULL;
    AVCodecParameters* AVCodecParametr_ = NULL;
    FILE* f;
    //Эта структура описывает декодированные (необработанные) аудио- или видеоданные.
    AVFrame* frame;
    uint8_t inbuf[INBUF_SIZE + AV_INPUT_BUFFER_PADDING_SIZE];
    uint8_t* data;
    size_t   data_size;
    int ret;
    int eof;
    AVFormatContext* AVfc = NULL;
    int ERRORS;
    //AVCodec* codec;
    char buf[1024];
    const char* FileName;
 
    // https://habr.com/ru/post/137793/
    // Хранит сжатый один кадр.
    AVPacket* pkt;
 
    //**********************************************************************
    // Начало чтения видео с камеры. 
    //**********************************************************************
 
    avdevice_register_all();
 
    filename = "rtsp://admin:admin@192.168.1.75:554/11";
    
    outfilename = "C:\\2.MP4";
 
    // Открываем поток видео (это файл или камера). 
    ERRORS = avformat_open_input(&AVfc, filename, NULL, NULL);
    if (ERRORS < 0) {
        fprintf(stderr, "ffmpeg: не смог открыть файл\n");
        return -1;
    }
 
    // После открытия, можем распечатать информацию о видеофайле (iformat = название формата; 
    // duration = длительность). Но так как у меня подключена камера мне написал: Duration: N/A, 
    // start: 0.000000, bitrate: N/A
    printf("Format %s, duration %lld us", AVfc->iformat->long_name, AVfc->duration);
 
 
    ERRORS = avformat_find_stream_info(AVfc, NULL);
    if (ERRORS < 0) {
        fprintf(stderr, "ffmpeg: Unable to find stream info\n");
        return -1;
    }
 
 
    int CountStream;
 
    // Узнаем кол-во потоков. 
    CountStream = AVfc->nb_streams;
 
    // Поищим кодек. 
    int video_stream;
    for (video_stream = 0; video_stream < AVfc->nb_streams; ++video_stream) {
        if (AVfc->streams[video_stream]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
            break;
        }
 
    }
 
    if (video_stream == AVfc->nb_streams) {
        fprintf(stderr, "ffmpeg: Unable to find video stream\n");
        return -1;
    }
 
    // Тут определяем вид кодека, для моей камеры он равен как AV_CODEC_ID_HEVC (Это то в чем вещает моя камера)
    codec = avcodec_find_decoder(AVfc->streams[video_stream]->codecpar->codec_id);
    //--------------------------------------------------------------------------------------
 
    // Функции для запроса возможностей libavcodec,
    AVCodecContext_ = avcodec_alloc_context3(codec);
    if (!AVCodecContext_) {
        fprintf(stderr, "Не удалось выделить контекст видеокодека, т.к. он не поддрерживается\n");
        exit(1);
    }
 
    // Эта функция используется для инициализации 
    // AVCodecContext видео и аудио кодека. Объявление avcodec_open2() находится в libavcodecavcodec.h
    // Открываем кодек. 
 
    ERRORS = avcodec_open2(AVCodecContext_, codec, NULL);
    if (ERRORS < 0) {
        fprintf(stderr, "ffmpeg: Не удается открыть кодек\n");
        return -1;
    }
 
    // Это для обработки звука - задел.
    //swr_alloc_set_opts()
    // swr_init(); 
 
    // Вывести всю информацию о видеофайле. 
    av_dump_format(AVfc, 0, argv[1], 0);
 
    //=========================================================================================
    // Далее, получаем фреймы..до этого мы только получили всю инфомрацию о входящем видео.
    //=========================================================================================
 
    // Теперь мы собираемся прочитать пакеты из потока и декодировать их в кадры, но сначала 
    // нам нужно выделить память для обоих компонентов(AVPacket и AVFrame).
    frame = av_frame_alloc();
 
    if (!frame) {
        fprintf(stderr, "Не удается выделить память для видеокадра\n");
        exit(1);
    }
    // Выделяем память для пакета 
    pkt = av_packet_alloc();
    // Чтение данных если они есть. 
    while (av_read_frame(AVfc, pkt) >= 0) {
        // Это пакет из видеопотока? Потомучто есть еще звуковая дорожка.
        if (pkt->stream_index == video_stream) {
 
            int ret;
            // Передача необработанных пакетных данных в качестве входных данных в декодер.
            // 0 при успешном выполнении, в противном случае отрицательный код ошибки: AVERROR(EAGAIN)
            // предварительно должен быть открыт с помощью avcodec_decode_video2(); (выполнено ранее)
            ret = avcodec_send_packet(AVCodecContext_, pkt);
            if (ret < 0) {
                fprintf(stderr, "Error 56: Ошибка отправки пакета для декодирования\n");
                continue;
                //exit(1);
            }
            
            while (ret >= 0) {
                // Возвращает декодированные выходные данные из декодера или 
                // кодировщика (при использовании флага AV_CODEC_FLAG_RECON_FRAME).
                ret = avcodec_receive_frame(AVCodecContext_, frame);
                if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
                    break;
                //return 57;
                else if (ret < 0) {
                    fprintf(stderr, "Ошибка при декодирование\n");
                    break;
                    //exit(1);
                }
 
                /*printf(
                    "Frame %c (%d) pts %d dts %d key_frame %d [coded_picture_number %d, display_picture_number %d]",
                    av_get_picture_type_char(/*frame->pict_type),
                    AVCodecContext_->frame_number,
                    frame->pts,
                    frame->pkt_dts,
                    frame->key_frame,
                    frame->coded_picture_number,
                    frame->display_picture_number
                );*/
 
 
 
                printf("-\n", frame->display_picture_number);
                //  fflush(stdout);
 
                    //изображение выделяется декодером.нет необходимости освобождать его
 
                //snprintf(buf, sizeof(buf), filename, AVCodecContext_->frame_number);
                //pgm_save(frame->data[0], frame->linesize[0],frame->width, frame->height, buf);
 
 
 
            }
 
        }
 
    }
 
 
    //av_parser_close(parser);
    avcodec_free_context(&AVCodecContext_);
    av_frame_free(&frame);
    av_packet_free(&pkt);
 
    return 0;
}
Добавлено через 6 минут
Вообще конечная цель записать в файл h.264. или в h.265

Добавлено через 45 секунд
Вообще можно было бы еще ради интереса вывести в окно картинку.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
06.01.2023, 14:56
Ответы с готовыми решениями:

ffmpeg как сохранить кадр в pgm
Есть код на c++, он должен открывать видео и сохранять из него кадры. Когда ему даешь ссылку на...

ffmpeg Выдернуть кадр из видеофайла
Доброго времени суток. Бьюсь 4й день над проблемкой как при помощи ffmpeg выдернуть определенный...

Не выходит закодировать кадр с помощью FFmpeg
Привет всем. У меня такая проблема - не могу закодировать кадр с помощью FFmpeg, использую эту...

C++ builder + ffmpeg: вывести кадр на TImage
я получаю кадр от ffmpeg в формате AVFrame. как вывести кадр на TImage ?

4
70 / 14 / 3
Регистрация: 10.07.2018
Сообщений: 284
08.01.2023, 11:23  [ТС] 2
Может кто то все же подскажет, сохраняет в файл но файл весит прям много 18 гб.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
#include <Windows.h>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <fstream>
#include <cstring>
#include <math.h>
#include <string.h>
 
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include <libavformat/avio.h>
#include "libavutil/imgutils.h"
#include "libavutil/opt.h"
#include <libavutil/imgutils.h>
#include <libavutil/samplefmt.h>
#include <libavutil/timestamp.h>
#include <libavformat/avformat.h>
#include <libswresample/swresample.h>
#include "libavcodec/avcodec.h"
#include "libavcodec/avfft.h"
#include "libavdevice/avdevice.h"
#include "libavfilter/avfilter.h"
#include "libavfilter/buffersink.h"
#include "libavfilter/buffersrc.h"
#include "libavformat/avformat.h"
#include "libavformat/avio.h"
#include "libavutil/opt.h"
#include "libavutil/common.h"
#include "libavutil/channel_layout.h"
#include "libavutil/imgutils.h"
#include "libavutil/mathematics.h"
#include "libavutil/samplefmt.h"
#include "libavutil/time.h"
#include "libavutil/opt.h"
#include "libavutil/pixdesc.h"
#include "libavutil/file.h"
#include "libswscale/swscale.h"
#include <libavutil/imgutils.h>
#include <libavutil/samplefmt.h>
#include <libavutil/timestamp.h>
#include <libavformat/avformat.h>
 
}
#define INBUF_SIZE 4096
 
 
static void save_gray_frame(unsigned char* buf, int wrap, int xsize, int ysize, char* filename)
{
    return;
    FILE* f = NULL;
    int i;
    f = fopen(filename, "w");
    if (f == NULL) {
        fprintf(stderr, "ffmpeg: Не удалось создать новый файл\n");
    }
    fprintf(f, "P5\n%d %d\n%d\n", xsize, ysize, 255);
    for (i = 0; i < ysize; i++)
        fwrite(buf + i * wrap, 1, xsize, f);
    fclose(f);
}
 
void pgm_save(unsigned char* buf, int wrap, int xsize, int ysize, FILE* f) {
    fprintf(f, "P5\n%d %d\n%d\n", wrap, xsize, ysize);
    for (int i = 0; i < ysize; i++) {
        fwrite(buf + i * wrap, 1, xsize, f);
    }
}
 
void decode(AVCodecContext* dec_ctx, AVFrame* Frame, AVPacket* pkt, FILE* f)
{
    int ret;
    ret = avcodec_send_packet(dec_ctx, pkt);
    if (ret < 0) {
        fprintf(stderr, "Ошибка отправки пакета в кодирование.\n");
        exit(1);
    }
 
    while (ret >= 0) {
        ret = avcodec_receive_frame(dec_ctx, Frame);
        if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
            return;
        }
        else if (ret < 0) {
            fprintf(stderr, "during decoding.\n");
            exit(1);
        }
        printf("sawing frame %3d\n", dec_ctx->frame_number);
        fflush(stdout);
        pgm_save(Frame->data[0], Frame->linesize[0], Frame->width, Frame->height, f);
    }
}
 
int main(int argc, char* argv[])
{
    setlocale(LC_ALL, "Rus");
 
    const AVCodec* codec = NULL;
    AVCodecParserContext* parser = NULL;
 
    // содержит данные о конфигурации медиаконтента, такой как битрейт, 
    // частота кадров, частота дискретизации, каналы, высота и многое другое.
    AVCodecContext* AVCodecContext_ = NULL;
    AVCodecParameters* AVCodecParametr_ = NULL;
    FILE* f = NULL;
 
    //Эта структура описывает декодированные (необработанные) аудио- или видеоданные.
    AVFrame* frame = NULL;
    uint8_t inbuf[INBUF_SIZE + AV_INPUT_BUFFER_PADDING_SIZE];
    uint8_t* data = NULL;
    size_t   data_size = NULL;
    int ret;
    int eof;
    AVFormatContext* AVfc = NULL;
    int ERRORS;
    //AVCodec* codec;
    char buf[1024];
 
    // Хранит сжатый один кадр.
    AVPacket* pkt = NULL;
 
    //**********************************************************************
    // Ниже переменные которые я задействовал для части кодирования, что бы небыло перехлеста
    // с теми которые используются для декодирования. 
    //**********************************************************************
 
    const AVCodec* AVCodecDE = NULL;
    AVCodecContext* AVCodecContextDE = NULL;
    AVFrame* AVframeDE = NULL;
    AVPacket* AVpktDE;
    FILE* fDE;
 
    //Входящий видео файл AVI
    const char* InputFileName = "c:\\1.avi";
    // Адрес с видеокамеры. 
    const char* InputCam = "rtsp://admin:admin192.168.1.75:554/11";
    //Определение видео файла для сохранения как видео.
    const char* OutFileNameDE = "C:\\Users\\Users\\Desktop\\2.yuv";
    //Определяем имя файла для сохранения картинки.
    const char* FileName1 = "C:\\Users\\Users\\Desktop\\NyFile.PGM";
 
    //**********************************************************************
    // Начало чтения видео с камеры. 
    //**********************************************************************
 
    avdevice_register_all();
 
    // Открываем поток видео (это файл или камера). 
    ERRORS = avformat_open_input(&AVfc, InputCam, NULL, NULL);
    if (ERRORS < 0) {
        fprintf(stderr, "ffmpeg: не смог открыть файл\n");
        return -1;
    }
 
    // После открытия, можем распечатать информацию о видеофайле (iformat = название формата; 
    // duration = длительность). Но так как у меня подключена камера мне написал: Duration: N/A, 
    // start: 0.000000, bitrate: N/A
    printf("Format %s, duration %lld us", AVfc->iformat->long_name, AVfc->duration);
 
    ERRORS = avformat_find_stream_info(AVfc, NULL);
    if (ERRORS < 0) {
        fprintf(stderr, "ffmpeg: Unable to find stream info\n");
        return -1;
    }
 
    int CountStream;
 
    // Узнаем кол-во потоков. 
    CountStream = AVfc->nb_streams;
 
    // Поищим кодек. 
    int video_stream;
    for (video_stream = 0; video_stream < AVfc->nb_streams; ++video_stream) {
        if (AVfc->streams[video_stream]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
 
            // В ДАННОЙ ТОЧКЕ ЧАСТО ОШИБКА ПРИ ИСПОЛЬЗОВАНИЕ IP КАМЕРЫ.
            break; // Тут вылетает ошибка, что типа не обнаружен поток, надо заново пустить. 
        }
    }
 
    if (video_stream == AVfc->nb_streams) {
        fprintf(stderr, "ffmpeg: Unable to find video stream\n");
        return -1;
    }
 
    // Тут определяем вид кодека, для моей камеры он равен как AV_CODEC_ID_HEVC (Это то в чем вещает моя камера)
    codec = avcodec_find_decoder(AVfc->streams[video_stream]->codecpar->codec_id);
 
    // Функции для запроса возможностей libavcodec,
    AVCodecContext_ = avcodec_alloc_context3(codec);
    if (!AVCodecContext_) {
        fprintf(stderr, "Не удалось выделить контекст видеокодека, т.к. он не поддрерживается\n");
        exit(1);
    }
 
    // Эта функция используется для инициализации 
    // AVCodecContext видео и аудио кодека. Объявление avcodec_open2() находится в libavcodecavcodec.h
    // Открываем кодек. 
 
    ERRORS = avcodec_open2(AVCodecContext_, codec, NULL);
    if (ERRORS < 0) {
        fprintf(stderr, "ffmpeg: Не удается открыть кодек\n");
        return -1;
    }
 
    // Это для обработки звука - задел.
    //swr_alloc_set_opts()
    // swr_init(); 
 
    // Вывести всю информацию о видеофайле. 
    av_dump_format(AVfc, 0, argv[1], 0);
 
    //=========================================================================================
    // Далее, получаем фреймы..до этого мы только получили всю инфомрацию о входящем видео.
    //=========================================================================================
 
    // Теперь мы собираемся прочитать пакеты из потока и декодировать их в кадры, но сначала 
    // нам нужно выделить память для обоих компонентов(AVPacket и AVFrame).
    frame = av_frame_alloc();
 
    f = fopen(OutFileNameDE, "w");
    if (!f) {
        fprintf(stderr, "Could not open %s\n", OutFileNameDE);
        exit(1);
    }
 
    if (!frame) {
        fprintf(stderr, "Не удается выделить память для видеокадра\n");
        exit(1);
    }
    // Выделяем память для пакета 
    pkt = av_packet_alloc();
 
    // Чтение данных если они есть. 
    while (av_read_frame(AVfc, pkt) >= 0) {
        // Это пакет из видеопотока? Потомучто есть еще звуковая дорожка.
        if (pkt->stream_index == video_stream)
        {
            int ret;
 
            // Обновление 1, типа сохраняем декодированое видео в файл. 
            decode(AVCodecContext_, frame, pkt, f);
        }
        av_packet_unref(pkt);
    }
 
 
    if (codec)
        av_free(&codec);
    if (parser)
        av_free(&parser);
    if (AVCodecContext_)
        av_free(&AVCodecContext_);
    if (AVCodecParametr_)
        av_free(&AVCodecParametr_);
    if (f)
        av_free(&f);
    if (AVfc)
        av_free(&inbuf);
 
    if (pkt)
        av_free(&pkt);
 
}
0
2712 / 866 / 327
Регистрация: 10.02.2018
Сообщений: 2,047
09.01.2023, 14:43 3
Цитата Сообщение от Юг Посмотреть сообщение
Может кто то все же подскажет, сохраняет в файл но файл весит прям много 18 гб.
Вы пытаетесь записывать декодированные кадры. Естественно, что они занимают очень много места. Попробуйте не декодировать, а сразу записать данные из поступающих видео пакетов в бинарный (fopen(..., "wb")) файл. По-идее должен получиться бинарный стрим, который может читаться разными плеерами. Если данные приходят в формате HEVC, то сделайте у файла расширение ".hevc" или ".h265", запишите в такой файл секунд 10 и попробуйте открыть его плеером.
0
70 / 14 / 3
Регистрация: 10.07.2018
Сообщений: 284
13.01.2023, 00:46  [ТС] 4
Цитата Сообщение от Ygg Посмотреть сообщение
Вы пытаетесь записывать декодированные кадры. Естественно, что они занимают очень много места. Попробуйте не декодировать, а сразу записать данные из поступающих видео пакетов в бинарный (fopen(..., "wb")) файл. По-идее должен получиться бинарный стрим, который может читаться разными плеерами. Если данные приходят в формате HEVC, то сделайте у файла расширение ".hevc" или ".h265", запишите в такой файл секунд 10 и попробуйте открыть его плеером.
Добрый день, сижу уже неделю - окончательно запутался. Вот полотно. Короче HELP

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
#include <Windows.h>
#include <fstream>
#include <iostream>
 
extern "C" {
#include <libavcodec/avcodec.h>
 
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include <libavformat/avio.h>
#include "libavutil/imgutils.h"
#include "libavutil/opt.h"
#include <libavutil/imgutils.h>
#include <libavutil/samplefmt.h>
#include <libavutil/timestamp.h>
#include <libavformat/avformat.h>
#include <libswresample/swresample.h>
#include "libavcodec/avfft.h"
#include "libavdevice/avdevice.h"
#include "libavfilter/avfilter.h"
#include "libavfilter/buffersink.h"
#include "libavfilter/buffersrc.h"
#include "libavformat/avformat.h"
#include "libavformat/avio.h"
#include "libavutil/opt.h"
#include "libavutil/common.h"
#include "libavutil/channel_layout.h"
#include "libavutil/imgutils.h"
#include "libavutil/mathematics.h"
#include "libavutil/samplefmt.h"
#include "libavutil/time.h"
#include "libavutil/opt.h"
#include "libavutil/pixdesc.h"
#include "libavutil/file.h"
#include "libswscale/swscale.h"
#include <libavutil/imgutils.h>
#include <libavutil/samplefmt.h>
#include <libavutil/timestamp.h>
#include <libavformat/avformat.h>
 
 
#include <libavformat\avformat.h>
#include <libavutil\rational.h>
#include <libswscale\swscale.h>
#include <libavutil\opt.h>
#include <libavutil\error.h>
 
 
}
#define INBUF_SIZE 4096
 
 
//Close();
int ret;
 
AVStream* stream = NULL;
 
uint32_t bitrate = 6000000; // Для изображения 1920*1080 30 кадров = 6000 
int width = 1920;
int height = 1080;
int fps = 25;
AVPixelFormat src_format; //?
AVPixelFormat dst_format; //?
const char* preset = NULL; //? 
AVFrame* frame = NULL; //?
SwsContext* sws_context = NULL; //? 
const char* filename = "C:\\Users\\**\\Desktop\\Ошибки.TXT";
uint32_t crf; // ? 0–51
uint32_t frame_index = 0; // ? 
static bool mIsOpen;  //? 
const AVFormatContext AVFormat_Context;
const AVOutputFormat AVOutput_Format;
const AVIOContext* AV_IOContext;
 
AVCodec* codec; AVCodecContext* context;
 
 
 
bool FlushPackets(AVCodecContext* AVCodecContext_Out, AVFormatContext * AVFormatContext_Out)
{
    int ret;
    do
    {
        AVPacket packet = { 0 };
 
        ret = avcodec_receive_packet(AVCodecContext_Out, &packet);
        if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
            break;
 
        if (ret < 0)
        {
            fprintf(stderr, "П130", ret);
            return false;
        }
 
        av_packet_rescale_ts(&packet, AVCodecContext_Out->time_base, stream->time_base);
        packet.stream_index = stream->index;
 
        ret = av_interleaved_write_frame(AVFormatContext_Out, &packet);
        av_packet_unref(&packet);
        if (ret < 0)
        {
            fprintf(stderr, "П131", ret);
            return false;
        }
    } while (ret >= 0);
 
    return true;
}
 
// запись в файл.
bool MyWrite(const unsigned char* data, AVFrame* AVFrame_Out, AVCodecContext* AVCodecContext_Out, AVFormatContext* AVFormatContext_Out)
{
    if (!mIsOpen)
        return false;
 
    auto ret = av_frame_make_writable(AVFrame_Out);
    if (ret < 0)
    {
        std::cout << "frame not writable" << std::endl;
        return false;
    }
 
    const int in_linesize[1] = { AVCodecContext_Out->width * 3 };
 
    sws_scale(
        sws_context,
        &data, in_linesize, 0, AVCodecContext_Out->height,  // src
        AVFrame_Out->data, AVFrame_Out->linesize // dst
    );
    AVFrame_Out->pts = frame_index++;
 
    ret = avcodec_send_frame(AVCodecContext_Out, AVFrame_Out);
    if (ret < 0)
    {
        std::cout << "error sending a frame for encoding" << std::endl;
        return false;
    }
 
    return FlushPackets(AVCodecContext_Out, AVFormatContext_Out);
}
 
// Функция закрытия файла. 
void MyClose(AVFormatContext* AVFormatContext_Out, AVCodecContext* AVCodecContext_Out)
{
    if (mIsOpen == true)
    {
        avcodec_send_frame(AVCodecContext_Out, nullptr);
 
        FlushPackets(AVCodecContext_Out, AVFormatContext_Out);
        //Как только все данные будут записаны, вызывающая сторона должна вызвать av_write_trailer() , чтобы сбросить все буферизованные пакеты и завершить выходной файл
        av_write_trailer(AVFormatContext_Out);
        //Закройте ресурс, к которому обращается AVIOContext, и освободите его.
        auto ret = avio_close(AVFormatContext_Out->pb);
        if (ret != 0)
            fprintf(stderr, "П132", ret);
    }
 
    //sws_context Масштабирование одной горизонтальной строки входных данных с помощью билинейного фильтра для получения одной строки выходных данных.
    if (sws_context)
        sws_freeContext(sws_context);
    // Декоированый кадр 
    if (frame)
        av_frame_free(&frame);
    // контекст
    if (AVCodecContext_Out)
        avcodec_free_context(&AVCodecContext_Out);
    // контекст
    if (AVCodecContext_Out)
        avcodec_close(AVCodecContext_Out);
    // уничтожить память.
    if (AVCodecContext_Out)
        avformat_free_context(AVFormatContext_Out);
 
    //mContext = {};
    mIsOpen = false;
}
 
 
// этап открытия файла. const char *filename, const Params &params
bool MyOpenFile(AVFormatContext* AVfc, AVOutputFormat* AVOutPutFormat1, const char* FormatName, const char* FileName)
{
    AVFormatContext* AVformatContext_Out = NULL; // параметры выходного файла, их настроить еще надо.
    AVIOContext* AVIOContext_Out = NULL;
    const AVCodec* AVCodec_Out;
    AVCodecContext* AVCodecContext_Out = NULL;
    int ret;
 
    // Закрываем файл в который записываем, если он открытый.
    MyClose(AVformatContext_Out, AVCodecContext_Out);
    do
    {
 
        // Выделяем память для выходного контекста, а контекст содержит кучу настроек выходного файла.
        // AVOutputFormat оставляем как NULL это означает что два параметра (format) могут быть set_
        // Выходной формат угадывается FFmpeg
        ret = avformat_alloc_output_context2(&AVformatContext_Out, nullptr, nullptr, FileName);
        if (ret < 0)
        {
            fprintf(stderr, "П1");
            break;
        }
 
 
        /*AVIOContext_Out = avio_alloc_context();
        // Используется для открытия выходного файла для записи.
        ret = avio_open(&AVIOContext_Out, FileName, AVIO_FLAG_WRITE);
        if (ret < 0)
        {
            fprintf(stderr, "Ошибка Р1");
            break;
        }*/
 
        // +Запрашивает кодек для шифрования "H.264"
        AVCodec_Out = avcodec_find_encoder(AV_CODEC_ID_H264);
        if (!AVCodec_Out)
        {
            fprintf(stderr, "Не удалось создать поток видео");
            break;
        }
 
        //Cоздает потоковый канал в AVFormatContext
        stream = avformat_new_stream(AVformatContext_Out, AVCodec_Out);
        if (stream == NULL)
        {
            fprintf(stderr, "Не удалось создать поток");
            break;
        }
 
        // присваевает потоку id от формат контекст. Я так понял передача данных от 
        // расшифровщика к шифровщику.
        stream->id = (int)(AVfc->nb_streams - 1);
 
        // выделяет память для ??
        AVCodecContext_Out = avcodec_alloc_context3(AVCodec_Out);
        if (!AVCodecContext_Out)
        {
            fprintf(stderr, "Не удалось выделить контекст кодека. ");
            break;
        }
 
        // Задаются параметры контекста, тут видео кодек тоесть если был кодек MP4 то и присваиваем MP4 ??? 
        AVCodecContext_Out->codec_id = AVfc->oformat->video_codec;
        //=============================================================================
        // Рекомендемые настройки для битрейта  https://docs.ngenix.net/services/video/bitrate
 
        // получаем битрейт
        AVCodecContext_Out->bit_rate = bitrate;  // Должно быть присвоено значение .
 
        // ширину 
        AVCodecContext_Out->width = static_cast<int>(width);
        // высоту
        AVCodecContext_Out->height = static_cast<int>(height);
 
        // единица времени (в секундах), в терминах которой представлены временные метки кадра.
        stream->time_base = av_d2q(1.0 / fps, 120);
 
        AVCodecContext_Out->time_base = stream->time_base;
        //формат пикселей. 
        AVCodecContext_Out->pix_fmt = dst_format;
 
        //Задайте размер группы рисунков.
        AVCodecContext_Out->gop_size = 12;
        AVCodecContext_Out->max_b_frames = 2;
 
 
        if (AVfc->oformat->flags & AVFMT_GLOBALHEADER)
            AVCodecContext_Out->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
 
        int ret = 0;
        if (preset)
        {
            //установить параметры, 
            ret = av_opt_set(AVCodecContext_Out->priv_data, "preset", preset, 0);
            if (ret != 0)
            {
                fprintf(stderr, "");
                break;
            }
        }
        //pb - нормальный
        {
            ret = av_opt_set_int(AVCodecContext_Out->priv_data, "crf", crf, 0);
            if (ret != 0)
            {
                fprintf(stderr, "");
                break;
            }
        }
 
        // открывает кодек.
        ret = avcodec_open2(AVCodecContext_Out, AVCodec_Out, nullptr);
        if (ret != 0)
        {
            fprintf(stderr, "");
            break;
        }
 
        frame = av_frame_alloc();
        if (!frame)
        {
            fprintf(stderr, "");
            break;
        }
        // пиксель формат установим
        frame->format = AVCodecContext_Out->pix_fmt;
        // ширина
        frame->width = AVCodecContext_Out->width;
        //высота
        frame->height = AVCodecContext_Out->height;
        //
        ret = av_frame_get_buffer(frame, 32);
        if (ret < 0)
        {
            fprintf(stderr, "");
            break;
        }
        //Все выделенные поля в par освобождаются и заменяются дубликатами соответствующих полей в кодеке.
        ret = avcodec_parameters_from_context(stream->codecpar, AVCodecContext_Out);
        if (ret < 0)
        {
            fprintf(stderr, "");
            break;
        }
 
        //вводим дополнительные данные для h.264
        sws_context = sws_getContext(
            AVCodecContext_Out->width, AVCodecContext_Out->height, src_format,   // src
            AVCodecContext_Out->width, AVCodecContext_Out->height, dst_format, // dst
            SWS_BICUBIC, nullptr, nullptr, nullptr
        );
 
        if (!sws_context)
        {
            std::cout << "could not initialize the conversion context" << std::endl;
            break;
        }
 
        //Распечатайте подробную информацию о формате ввода или вывода, такую ​​как продолжительность, 
        //битрейт, потоки, контейнер, программы, метаданные, дополнительные данные, кодек и временная база.
        av_dump_format(AVformatContext_Out, 0, filename, 1);
 
        if (AVformatContext_Out == NULL) {
            fprintf(stderr, "Ошибка 605");
            break;
        }
 
        //Создайте и инициализируйте AVIOContext для доступа к ресурсу, указанному URL-адресом.
        //&AVfc->pb
        /*ret = avio_open(&AVfc->pb, filename, AVIO_FLAG_WRITE);
        if (ret != 0)
        {
            fprintf(stderr, "Ошибка 605");
            break;
        }*/
 
        //Используется для записи заголовка видеофайла
        ret = avformat_write_header(AVformatContext_Out, nullptr);
        if (ret < 0)
        {
            std::cout << "Не получилось записать данные в файл" << std::endl;
            //Закройте ресурс, к которому обращается AVIOContext, и освободите его.
            //ret = avio_close(AVfc->pb);
            if (ret != 0)
                std::cout << "не удалось закрыть файл" << std::endl;
            break;
        }
 
        frame_index = 0;
        mIsOpen = true;
        return true;
    } while (false);
 
 
    // Функция закрытия. 
    MyClose(AVformatContext_Out, AVCodecContext_Out);
 
    return false;
}
 
static void save_gray_frame(unsigned char* buf, int wrap, int xsize, int ysize, char* filename)
{
    return;
    FILE* f = NULL;
    int i;
    f = fopen(filename, "w");
    if (f == NULL) {
        fprintf(stderr, "ffmpeg: Не удалось создать новый файл\n");
    }
    // writing the minimal required header for a pgm file format
    // portable graymap format -> https://en.wikipedia.org/wiki/Netpbm_format#PGM_example
    fprintf(f, "P5\n%d %d\n%d\n", xsize, ysize, 255);
 
    // writing line by line
    for (i = 0; i < ysize; i++)
        fwrite(buf + i * wrap, 1, xsize, f);
    fclose(f);
}
 
 
/*static void encode(AVCodecContext* enc_ctx, AVFrame* frame, AVPacket* pkt,
    FILE* outfile)
{
    int ret = 0;
    /* Отправляем кадр в кодировщик для того что бы закодировать (сжать) */
    /*if (frame)
        printf("Send frame %3\n", frame->pts);
 
 
    avcodec_send_frame(enc_ctx, NULL);
 
    ret = avcodec_send_frame(enc_ctx, frame);
    if (ret < 0) {
        fprintf(stderr, "Ошибка отправки кадра для кодирования\n");
        //exit(1);
    }
 
    // возращаем сжатый кадр из кодировщика --> записывается от в pkt с параметрами указаные в AVCodecContext *enc_ctx,
    while (ret >= 0) {
        ret = avcodec_receive_packet(enc_ctx, pkt);
        if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
            return;
        else if (ret < 0) {
            fprintf(stderr, "Error during encoding\n");
            exit(1);
        }
        // А затем пакет уже который уже в файл скидывается.
        printf("Write packet %3 (size=%5d)\n", pkt->pts, pkt->size);
        fwrite(pkt->data, 1, pkt->size, outfile);
        av_packet_unref(pkt);
    }
}*/
 
void pgm_save(unsigned char* buf, int wrap, int xsize, int ysize, FILE* f) {
    fprintf(f, "P5\n%d %d\n%d\n", wrap, xsize, ysize);
    for (int i = 0; i < ysize; i++) {
        fwrite(buf + i * wrap, 1, xsize, f);
    }
}
 
 
//**************************************************************************************//
// ПРОБУЕМ СЖИМАТЬ ПОЛУЧЕНЫЕ КАДРЫ ПРИМЕНИВ КОДИРОВАНИЕ                                   //
//**************************************************************************************//
 
// Определить экземпляры AVCodec отдельно для кодера и декодера.
 
const  AVCodec* AVCodecOut = NULL;
AVCodecContext* AVCodecContextOut = NULL;
AVIODirEntry* AVDirEntryOut;
AVFrame* FrameOut = NULL;
const int BUF_ = 16384;
 
 
void decode(AVCodecContext* dec_ctx, AVFrame* Frame, AVPacket* pkt, FILE* f)
{
 
 
 
 
 
 
 
    return;
    int ret = 0;
 
    // задаем паараметры на основе контекста для картинки 
    Frame->format = dec_ctx->pix_fmt;
    Frame->width = dec_ctx->width;
    Frame->height = dec_ctx->height;
 
    ret = av_image_alloc(
        Frame->data,  //массив, заполняемый указателем для каждой плоскости изображения
        Frame->linesize, //массив, заполненный линейным размером для каждой плоскости
        dec_ctx->width, //  ширина изображения в пикселях
        dec_ctx->height,//  высота изображения в пикселях
        dec_ctx->pix_fmt, //    AVPixelFormat изображения        
        32); //Значение, используемое для выравнивания размера буфера
 
 
    if (ret < 0) {
        fprintf(stderr, "Could not allocate raw picture buffer\n");
        exit(1);
    }
    int i, y, x;
 
    /* encode 1 second of video */
    for (i = 0; i < 25; i++) {
        //Инициализация pkt 
        //av_init_packet(pkt); // в теории создает множество пакетов. 
 
 
        pkt->data = NULL;    // пакетные данные будут распределены кодером
        pkt->size = 0;
 
        // нет информации - наверное сброс буфера ..
        fflush(stdout);
        /* prepare a dummy image */
        /* Y */
        for (y = 0; y < dec_ctx->height; y++) {  // высота  картинки 
            for (x = 0; x < dec_ctx->width; x++) { // ширина картинки 
 
 
                // тут заполняется какой та двух мерный массив с индексом [0]
                Frame->data[0][y * Frame->linesize[0] + x] = x + y + i * 3; // ? хренота какая то без бутылки не разберешся, а в магаз долеко) 
            }
        }
 
        /* Cb and Cr */
        for (y = 0; y < dec_ctx->height / 2; y++) {
            for (x = 0; x < dec_ctx->width / 2; x++) {
 
 
                //тут заполняется какой та двух мерный массив с индексом[1] и [2]
                Frame->data[1][y * Frame->linesize[1] + x] = 128 + y + i * 2;
                Frame->data[2][y * Frame->linesize[2] + x] = 64 + x + i * 5;
            }
        }
 
        Frame->pts = i; // указывается кадров в секунду. 
 
        /* закодируйте изображение */
        /*ret = avcodec_encode_video2(c, &pkt, frame, &got_output);
        if (ret < 0) {
            fprintf(stderr, "Error encoding frame\n");
            exit(1);
        }
 
        if (got_output) {
            printf("Write frame %3d (size=%5d)\n", i, pkt.size);
            fwrite(pkt.data, 1, pkt.size, f);
            av_packet_unref(&pkt); //Отмените ссылку на буфер, на который ссылается пакет, и сбросьте оставшиеся поля пакетов до значений по умолчанию.
        }*/
 
        ret = avcodec_send_packet(dec_ctx, pkt);
        if (ret < 0) {
            fprintf(stderr, "Ошибка отправки пакета в кодирование.\n");
            exit(1);
        }
 
 
        //----------------------------------------------------------------
        while (ret >= 0) {
            ret = avcodec_receive_frame(AVCodecContextOut, FrameOut);
            if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
                return;
            }
            else if (ret < 0) {
                fprintf(stderr, "during decoding.\n");
                exit(1);
            }
            printf("sawing frame %3d\n", AVCodecContextOut->frame_number);
            fflush(stdout);
            pgm_save(Frame->data[0], Frame->linesize[0], Frame->width, Frame->height, f);
        }
 
 
    }
 
 
 
 
    /* /// Для тех фреймов которые задержались.*/
    /*for (got_output = 1; got_output; i++) {
        fflush(stdout);
 
        ret = avcodec_encode_video2(c, &pkt, NULL, &got_output);
        if (ret < 0) {
            fprintf(stderr, "Error encoding frame\n");
            exit(1);
        }
 
        if (got_output) {
            printf("Write frame %3d (size=%5d)\n", i, pkt.size);
            fwrite(pkt.data, 1, pkt.size, f);
            av_packet_unref(&pkt);
        }
    }*/
 
    /* записать конец */
    //fwrite(endcode, 1, sizeof(endcode), f);
    fclose(f);
 
 
 
    avcodec_close(dec_ctx);
    av_free(dec_ctx);
    av_freep(&Frame->data[0]);
    av_frame_free(&Frame);
    printf("\n");
 
 
 
 
    //------------------------------------------------------------------------
    // Поищим для начала нужный нам кодек который сможет закодировать видео кадр   
 
 
    //av_dict_set(AVDirEntryOut, "b", "2.5M", 0);
    AVCodecOut = avcodec_find_encoder(AV_CODEC_ID_H264);
    if (AVCodecOut == NULL) {
        fprintf(stderr, "Error 100: Не получается найти кодек для кодировния AV_CODEC_ID_H264\n");
        exit(100);
    }
 
    // Создать структуру. 
    avcodec_alloc_context3(AVCodecOut);
    AVCodecContextOut = avcodec_alloc_context3(AVCodecOut);
 
    // Требуется установить обязательные параметры для видео которое мы хотим получить в итоге.
    AVCodecContextOut->gop_size = 10;
    AVCodecContextOut->max_b_frames = 1;
    AVCodecContextOut->pix_fmt = AV_PIX_FMT_YUV420P;
    AVCodecContextOut->width = 1920;
    AVCodecContextOut->height = 1080;
    AVCodecContextOut->time_base = { 1,25 };
    AVCodecContextOut->framerate = { 25, 1 };
    //? 
 
    FrameOut = av_frame_alloc();
    if (!FrameOut) {
        fprintf(stderr, "Could not allocate video frame\n");
        exit(1);
    }
 
    FrameOut->format = AVCodecContextOut->pix_fmt;
    FrameOut->width = AVCodecContextOut->width;
    FrameOut->height = AVCodecContextOut->height;
 
 
    // Затем откроем этот кодек. 
    ret = avcodec_open2(AVCodecContextOut, AVCodecOut, NULL);
    if (AVCodecOut == NULL) {
        fprintf(stderr, "Error 102:\n");
        exit(100);
    }
 
    ret = avcodec_send_packet(dec_ctx, pkt);
    if (ret < 0) {
        fprintf(stderr, "Ошибка отправки пакета в кодирование.\n");
        exit(1);
    }
 
 
    //----------------------------------------------------------------
    while (ret >= 0) {
        ret = avcodec_receive_frame(AVCodecContextOut, FrameOut);
        if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
            return;
        }
        else if (ret < 0) {
            fprintf(stderr, "during decoding.\n");
            exit(1);
        }
        printf("sawing frame %3d\n", AVCodecContextOut->frame_number);
        fflush(stdout);
        pgm_save(Frame->data[0], Frame->linesize[0], Frame->width, Frame->height, f);
 
 
 
        /*ret = avcodec_send_packet(dec_ctx, pkt);
        if (ret < 0) {
            fprintf(stderr, "Ошибка отправки пакета в кодирование.\n");
            exit(1);
        }
 
        while (ret >= 0) {
            ret = avcodec_receive_frame(dec_ctx, Frame);
            if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
                return;
            }
            else if (ret < 0) {
                fprintf(stderr, "during decoding.\n");
                exit(1);
            }
            printf("sawing frame %3d\n", dec_ctx->frame_number);
            fflush(stdout);
            pgm_save(Frame->data[0], Frame->linesize[0], Frame->width, Frame->height, f);*/
    }
}
 
int main(int argc, char* argv[])
{
    setlocale(LC_ALL, "Rus");
 
    FILE* f = NULL;
    uint8_t inbuf[INBUF_SIZE + AV_INPUT_BUFFER_PADDING_SIZE];
    uint8_t* data = NULL;
    size_t   data_size = NULL;
    int ret;
    int eof;
    int ERRORS;
    char* MyOutFormat = NULL;
    const char* MyFormat = "h264";
 
 
    const AVCodec* codec = NULL;
    AVCodecParserContext* parser = NULL;
 
    // содержит данные о конфигурации медиаконтента, такой как битрейт, 
    // частота кадров, частота дискретизации, каналы, высота и многое другое.
    AVCodecContext* AVCodecContext_ = NULL;
    AVFormatContext* AVfc = NULL;
    AVCodecParameters* AVCodecParametr_ = NULL;
    AVOutputFormat* AVOutputFormat_ = NULL;
 
    // Эта структура описывает декодированные (необработанные) аудио- или видеоданные.
    AVFrame* frame = NULL;
    // Хранит один сжатый кадр. 
    AVPacket* pkt = NULL;
 
    //Входящий видео файл AVI
    const char* InputFileName = "c:\\1.avi";
    // Адрес с видеокамеры. 
    const char* InputCam = "rtsp://admin@admin@11041988@192.168.1.75:554/11";
    //Определение видео файла для сохранения как видео.
    const char* OutFileName = "C:\\Users\\Павел\\Desktop\\УРА.H264";
    //Определяем имя файла для сохранения картинки.
    const char* FileName1 = "C:\\Users\\Павел\\Desktop\\NyFile.PGM";
 
    //**********************************************************************
    // Начало чтения видео с камеры или из файла
    //**********************************************************************
 
    // Первоначальная инициализация всех библиотек ver.3.14
    //avdevice_register_all();
 
    // Определяем тип выходного файла по расширению - это удобно.
    avformat_alloc_output_context2(&AVfc, NULL, NULL, OutFileName);
    if (!AVfc) {
        printf("Не удалось вывести выходной формат из расширения файла: с помощью MPEG.\n");
        //avformat_alloc_output_context2(&oc, NULL, "mpeg", имя файла);
        return -101;
    }
 
    // Открываем поток видео (это файл или камера). В данном случае читаем обычный пока файл.
    ERRORS = avformat_open_input(&AVfc, InputFileName, NULL, NULL);
    if (ERRORS < 0) {
        fprintf(stderr, "Error 1: не смог открыть файл\n");
        return -1;
    }
 
    // Выполним поиск де-кодека который необходим для чтения файла / камеры. 
    ERRORS = avformat_find_stream_info(AVfc, NULL);
    if (ERRORS < 0) {
        fprintf(stderr, "Error 2: Не уалось найти подходящий кодек, возможно он не поддердивается ffmpeg\n");
        return -1;
    }
 
    // После открытия, можем распечатать информацию о видеофайле (iformat = название формата; 
    // duration = длительность). Но так как у меня подключена камера мне написал: Duration: N/A, 
    // start: 0.000000, bitrate: N/A
    printf("Format %s, duration %lld us", AVfc->iformat->long_name, AVfc->duration);
 
 
    // Отрожает кол-во потоков в видео файле / камере. Бывает 2 потока и более (звук и видео). 
    int CountStream;
 
    // Узнаем кол-во потоков. 
    CountStream = AVfc->nb_streams;
 
    // Производим поиск видео потока о чем указывает флаг AVMEDIA_TYPE_VIDEO
    int video_stream;
    for (video_stream = 0; video_stream < AVfc->nb_streams; ++video_stream) {
        if (AVfc->streams[video_stream]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
 
            // Тут начинаем обработку видео потока. 
            if (video_stream == AVfc->nb_streams) {
                fprintf(stderr, "Error 3: Не удается найти видеопоток\n");
                return -1;
            }
 
            // Тут определяем вид кодека, для моей камеры он равен как AV_CODEC_ID_HEVC.
            codec = avcodec_find_decoder(AVfc->streams[video_stream]->codecpar->codec_id);
 
            // Функции для запроса возможностей libavcodec,
            AVCodecContext_ = avcodec_alloc_context3(codec);
            if (!AVCodecContext_) {
                fprintf(stderr, "Не удалось выделить контекст видеокодека, т.к. он не поддрерживается\n");
                exit(1);
            }
 
            // Открываем кодек. 
            ERRORS = avcodec_open2(AVCodecContext_, codec, NULL);
            if (ERRORS < 0) {
                fprintf(stderr, "ffmpeg: Не удается открыть кодек\n");
                return -1;
            }
            // Это для обработки звука - задел. Но возможно что я нахожу автоматически необходимый
            // кодек, а тут подразумивается установка кодека в ручном режиме.
            // swr_alloc_set_opts()
            // swr_init(); 
 
 
            // Вывести всю информацию о видеофайле. 
            av_dump_format(AVfc, 0, NULL, 0);
 
            //=========================================================================================
            // Далее, получаем фреймы..до этого мы только получили всю инфомрацию о входящем видео.
            //=========================================================================================
 
            // Теперь мы собираемся прочитать пакеты из потока и декодировать их в кадры, но сначала 
            // нам нужно выделить память для обоих компонентов(AVPacket и AVFrame).
            frame = av_frame_alloc();
 
            // Подготовимся для записи в файл. 
            f = fopen(OutFileName, "w");
            if (!f) {
                fprintf(stderr, "Could not open %s\n", OutFileName);
                exit(1);
            }
 
            if (!frame) {
                fprintf(stderr, "Не удается выделить память для видеокадра\n");
                exit(1);
            }
 
            // Выделяем память для пакета 
            pkt = av_packet_alloc();
 
            // Чтение данных если они есть. 
            while (av_read_frame(AVfc, pkt) >= 0) {
                // Это пакет из видеопотока? Потомучто есть еще звуковая дорожка.
                if (pkt->stream_index == video_stream)
                {
                    int ret;
 
                    // Открываем файл для записи информации пережатой в файл.
                    MyOpenFile(AVfc, AVOutputFormat_, MyFormat, OutFileName);
 
 
 
 
 
 
                }
                //av_packet_unref(pkt);
 
            }
 
            break; // Тут вылетает ошибка, что типа не обнаружен поток, надо заново пустить. 
        }
    }
 
 
    // Уничтожаем все созданые обьекты.  
    if (codec)
        av_free(&codec);
    if (parser)
        av_free(&parser);
    if (AVCodecContext_)
        av_free(&AVCodecContext_);
    if (AVCodecParametr_)
        av_free(&AVCodecParametr_);
    if (f)
        av_free(&f);
    if (AVfc)
        av_free(&inbuf);
 
    if (pkt)
        av_free(&pkt);
}
Добавлено через 7 минут
Читаю AVI и потом пытаюсь снова закодировать в H264 но кругом ошибки сыпется и вылетает прога. А судя по примеру функция write вообще нонсенс. какой ее чайник в тащил;
0
70 / 14 / 3
Регистрация: 10.07.2018
Сообщений: 284
22.03.2023, 19:44  [ТС] 5
Кто ни будь может подсказать по этому вопросу ?
0
22.03.2023, 19:44
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
22.03.2023, 19:44
Помогаю со студенческими работами здесь

Как узнать что сайт под фильтром или был там?
Интересует вот что: как узнать был ли сайт под фильтрами яндекса вообще и когда и под какими или...

Как узнать что при считывание очередного слова в string был сделан переход на новую строку в файле?
подскажите пожалуйста, как узнать что при считывание очередного слова в string был сделан переход...

Нужна консультация что такое Pascal Debuy
Вообщем дали мне реферат на тему: Pascal Debuy вообще не чего не нахожу, что это, кто это и с чем...

Нужна консультация по iframe + javascript или что-то другое
Хочу сделать некоммерческий (бесплатный) сервис для людей. Помогите консультацией. По замыслу,...

Аутентификация mode="Forms". Как узнать, что IIS сервер был перезапущен?
Настройка из web.config: &lt;authentication mode=&quot;Forms&quot;&gt; &lt;/authentication&gt; В общем, мне нужно...

Как через FFmpeg узнать продолжительность видео?
Подскажите пожалуйста, как с помощью консольного FFmpeg узнать продолжительность flv-видео. Видео...

Узнать, что курсор до клика был в поле
На текстовое поле вешаю событие search.onclick Вопрос в том, каким образом при клике на поле...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
5
Ответ Создать тему
Опции темы

Новые блоги и статьи
Как подключить JavaScript файл в другом JavaScript файле
InfoMaster 20.01.2025
В современной веб-разработке организация кодовой базы играет ключевую роль в создании масштабируемых и поддерживаемых приложений. Модульность и правильное структурирование кода стали неотъемлемыми. . .
Как откатить изменения в исходниках, не внесенные в Git
InfoMaster 20.01.2025
При работе с системой контроля версий Git разработчики часто сталкиваются с необходимостью отменить внесенные изменения в исходном коде. Особенно актуальной становится ситуация, когда изменения еще. . .
В чем разница между px, in, mm, pt, dip, dp, sp
InfoMaster 20.01.2025
В мире цифрового дизайна и разработки интерфейсов правильный выбор единиц измерения играет ключевую роль в создании качественного пользовательского опыта. История развития систем измерений для. . .
Как изменить адрес удалённого репозитория (origin) в Git
InfoMaster 20.01.2025
В терминологии Git термин origin является стандартным именем для основного удаленного репозитория, с которым взаимодействует локальная копия проекта. Когда разработчик клонирует репозиторий с. . .
Как переместить последние коммиты в новую ветку (branch) в Git
InfoMaster 20.01.2025
При работе над проектом часто возникают ситуации, когда необходимо изолировать определенные изменения от основной линии разработки. Это может быть связано с экспериментальными функциями, исправлением. . .
Как вернуть результат из асинхронной функции в JavaScript
InfoMaster 20.01.2025
Асинхронное программирование представляет собой фундаментальную концепцию в JavaScript, которая позволяет выполнять длительные операции без блокировки основного потока выполнения программы. В. . .
Какой локальный веб-сервер выбрать
InfoMaster 19.01.2025
В современной веб-разработке локальные веб-серверы играют ключевую роль, предоставляя разработчикам надежную среду для создания, тестирования и отладки веб-приложений без необходимости использования. . .
Почему планшеты и iPad уже не так популярны, как раньше
InfoMaster 19.01.2025
Эра революционных инноваций История планшетов началась задолго до того, как эти устройства стали привычными спутниками нашей повседневной жизни. В начале 1990-х годов появились первые прототипы,. . .
Как самому прошить BIOS ноутбука
InfoMaster 19.01.2025
BIOS (Basic Input/ Output System) представляет собой важнейший компонент любого компьютера или ноутбука, который обеспечивает базовое взаимодействие между аппаратным и программным обеспечением. . .
Какой Linux выбрать для домашнего компьютера
InfoMaster 19.01.2025
Современные реалии выбора операционной системы В современном мире выбор операционной системы для домашнего компьютера становится все более важным решением, которое может существенно повлиять на. . .
Как объединить два словаря одним выражением в Python
InfoMaster 19.01.2025
В мире программирования на Python работа со словарями является неотъемлемой частью разработки. Словари представляют собой мощный инструмент для хранения и обработки данных в формате "ключ-значение". . . .
Как без исключения проверить существование файла в Python
InfoMaster 19.01.2025
При разработке программного обеспечения на Python часто возникает необходимость проверить существование файла перед выполнением операций с ним. Это критически важная задача, которая помогает избежать. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru