Форум программистов, компьютерный форум CyberForum.ru

C++

Войти
Регистрация
Восстановить пароль
 
 
vxg
Модератор
3057 / 1859 / 195
Регистрация: 13.01.2012
Сообщений: 7,069
#1

Ffmpeg выдает moov atom not found если прервать процесс кодирования - C++

08.02.2016, 10:27. Просмотров 1189. Ответов 22
Метки нет (Все метки)

имеется код выполняющий кодирование и запись видео в файл (через avio_open2 / avformat_write_header / av_interleaved_write_frame / av_write_trailer / avio_close)
Кликните здесь для просмотра всего текста
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
extern "C" {
#include <libavformat/avformat.h>
#include <libavdevice/avdevice.h>
#include <libswscale/swscale.h>
}
 
#include <stdio.h>
#include <windows.h>
#include <time.h>
 
int main(int argc, char *argv[])
{
  AVFormatContext *ofcx;
  AVOutputFormat *ofmt;
  AVStream *ost;
 
  AVPacket pkt;
 
  const char *sFileOutput = "test.mp4";
 
  // Initialize library
  av_register_all();
  avformat_network_init();
 
  //
  // Output
  //
 
  //open output file
  ofmt = av_guess_format( NULL, sFileOutput, NULL );
  ofcx = avformat_alloc_context();
  ofcx->oformat = ofmt;
 
  int w = 800;
  int h = 600;
  int den = 25;
  int gop_size = 10;
  int codec_id = CODEC_ID_H264;
 
  // Create output stream
  AVCodec *ocodec = avcodec_find_encoder( (AVCodecID)codec_id );
  ost = avformat_new_stream( ofcx, ocodec );
  ost->codec->width = w;
  ost->codec->height = h;
  ost->codec->pix_fmt = ocodec->pix_fmts[0];
  ost->codec->time_base.num = 1; 
  ost->codec->time_base.den = den; 
  ost->time_base.num = 1;
  ost->time_base.den = den;
  ost->codec->gop_size = gop_size; 
  if ( ofcx->oformat->flags & AVFMT_GLOBALHEADER ) ost->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
  avcodec_open2( ost->codec, ocodec, 0 );
  
  AVFrame *frame = av_frame_alloc();
  frame->format = PIX_FMT_YUV420P;
  frame->width = w;
  frame->height = h;
  int buffer_size = avpicture_get_size(PIX_FMT_YUV420P, w, h);
  uint8_t *buffer = (uint8_t *)av_malloc(buffer_size * sizeof(uint8_t));
  avpicture_fill((AVPicture *)frame, 0, PIX_FMT_YUV420P, w, h);
 
  frame->data[0] = buffer;
  frame->data[1] = frame->data[0] + w * h;
  frame->data[2] = frame->data[1] + (w * h) / 4;
  frame->linesize[0] = w;
  frame->linesize[1] = w / 2;
  frame->linesize[2] = w / 2;
 
  avio_open2( &ofcx->pb, sFileOutput, AVIO_FLAG_WRITE, NULL, NULL );
 
  avformat_write_header( ofcx, NULL );
 
  av_init_packet( &pkt );
  for ( int i = 0; i < 25 * 10; i++ )
  {
        /* Y */
        for ( int y = 0; y < ost->codec->height; ++y ) {
            for ( int x = 0; x < ost->codec->width; ++x ) {
                frame->data[0][y * frame->linesize[0] + x] = x + y + i * 3;
            }
        }
 
        /* Cb and Cr */
        for ( int y = 0; y < ost->codec->height / 2; ++y ) {
            for ( int x = 0; x < ost->codec->width / 2; ++x ) {
                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 = av_rescale_q(i, ost->codec->time_base, ost->time_base);
 
        int got_packet;
        if (avcodec_encode_video2(ost->codec, &pkt, frame, &got_packet) != 0) break;
 
        if (got_packet) 
        {
            av_interleaved_write_frame( ofcx, &pkt );
            av_free_packet( &pkt );
            avio_flush(ofcx->pb);
        }
  }
  av_write_trailer( ofcx );
  avio_close( ofcx->pb );
  avformat_free_context( ofcx );
 
  return 0;
}

если прервать процесс кодирования до вызова av_write_trailer (закрыть программу до того как процесс будет завершен, прервать выполнение программы завершив процесс из диспетчера задач, отключить питание ПК), то файл формируется неправильно и не может быть воспроизведен - ffprobe выдает сообщение
[mov,mp4,m4a,3gp,3g2,mj2 @ 00d44c20] moov atom not found
test.mp4: Invalid data found when processing input
castaway предложил код производящий прямую запись пакетов получаемых при кодировании на диск (через fopen / fwrite / fclose)
Кликните здесь для просмотра всего текста
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
#include <iostream>
 
extern "C" {
 #define __STDC_CONSTANT_MACROS
 #include <libavutil/opt.h>
 #include <libavutil/imgutils.h>
 #include <libavformat/avformat.h>
 #include <libavcodec/avcodec.h>
}
 
int main()
{
    avcodec_register_all();
    av_register_all();
 
    AVCodec * codec = avcodec_find_encoder( AV_CODEC_ID_H264 );
    if ( codec ) {
        AVCodecContext * avCtx = avcodec_alloc_context3( codec );
        if ( avCtx ) {
 
            /// MUST be set by user.
            avCtx->width    = 720;
            avCtx->height   = 304;
 
            /// Set by user.
            avCtx->pix_fmt  = AV_PIX_FMT_YUV420P;
 
            avCtx->gop_size = 10;
            avCtx->max_b_frames = 1;
 
            /// MUST be set by user.
            avCtx->time_base = (AVRational){ 1, 25 }; // 1/fps
 
            /// Set by user; unused for constant quantizer encoding.
            avCtx->bit_rate = 1024 * 256;
 
            av_opt_set( avCtx->priv_data, "preset", "slow", 0 );
 
            if ( avcodec_open2( avCtx, codec, 0 ) >= 0 ) {
                AVFrame * frame = av_frame_alloc();
                if ( frame ) {
                    frame->format = avCtx->pix_fmt;
                    frame->width  = avCtx->width;
                    frame->height = avCtx->height;
 
                    int ret = av_image_alloc( frame->data, frame->linesize, avCtx->width, avCtx->height, avCtx->pix_fmt, 32 );
                    if ( ret >= 0 ) {
 
                        FILE * fp = fopen( "out.mp4", "wb+" );
                        if ( !fp ) {
                            std::cerr << "can't open output file\n";
                            return 1;
                        }
 
                        AVPacket pkt;
                        int got_output;
                        for ( int i = 0; i < 25 * 10/*seconds*/; ++i ) {
                            av_init_packet( &pkt );
                            pkt.data = NULL; // packet data will be allocated by the encoder
                            pkt.size = 0;
 
                            /* Y */
                            for ( int y = 0; y < avCtx->height; ++y ) {
                                for ( int x = 0; x < avCtx->width; ++x ) {
                                    frame->data[0][y * frame->linesize[0] + x] = x + y + i * 3;
                                }
                            }
 
                            /* Cb and Cr */
                            for ( int y = 0; y < avCtx->height / 2; ++y ) {
                                for ( int x = 0; x < avCtx->width / 2; ++x ) {
                                    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( avCtx, &pkt, frame, &got_output );
                            if ( ret >= 0 && got_output ) {
                                fwrite( pkt.data, 1, pkt.size, fp );
                                av_packet_unref( &pkt );
                            }
                        }
 
                        /* get the delayed frames */
                        do {
                            ret = avcodec_encode_video2( avCtx, &pkt, NULL, &got_output );
                            if ( ret >= 0 && got_output ) {
                                fwrite( pkt.data, 1, pkt.size, fp );
                                av_packet_unref( &pkt );
                            }
                        } while ( got_output );
 
                        fclose( fp );
                    }
 
                    av_frame_free( &frame );
                }
            }
            av_free( avCtx );
        }
        avcodec_close( avCtx );
    }
}

файл формируемый этим кодом может быть воспроизведен даже в случае прерывания процесса кодирования. однако файлы получаемые в результате работы этого кода имеют некие особенности из-за которых они не могут быть воспроизведены например через VLC или KMP. вот что выдает ffprobe для файла формируемого моим кодом
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'test.mp4':
Metadata:
major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
encoder : Lavf56.30.100
Duration: 00:00:09.32, start: 0.000000, bitrate: 791 kb/s
Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 800x600,
789 kb/s, 25 fps, 25 tbr, 12800 tbn, 50 tbc (default)
Metadata:
handler_name : VideoHandler
и вот что выдает ffprobe для кода castaway
Input #0, h264, from 'out.mp4':
Duration: N/A, bitrate: N/A
Stream #0:0: Video: h264 (High), yuv420p, 720x304, 25 fps, 25 tbr, 1200k tbn
, 50 tbc
видна некая "неполнота" файла...
вопрос - как правильно записывать файл содержащий всю необходимую для воспроизведения информацию что бы прерывание процесса кодирования не приводило к его повреждению? нужна либо правка моего метода делающая его устойчивым к прерыванию кодирования либо правка метода castaway формирующая файл корректно
Лучшие ответы (1)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
08.02.2016, 10:27     Ffmpeg выдает moov atom not found если прервать процесс кодирования
Посмотрите здесь:

CreateFile. Как правильно открытьфайл на запись, если запущен одноимённый процесс? C++ WinAPI
что делать если выдает такую ошибку? C++
Исправьте код, выдает ошибку (заданы коэффициенты квадратного уравнения. Найти его действительные корни, если они существуют.) C++
C++ Builder Открыть процесс процесс на полный доступ, и запретить для других
C++ Процесс А инициализирует массив случайными значениями и записывает их в файл, а затем запускает процесс Б
Почему условный оператор даже, если условие неверно, выдает истину? C++
C++ Builder Прервать выполнение, если сработало условие
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
castaway
Эксперт С++
4876 / 3015 / 370
Регистрация: 10.11.2010
Сообщений: 11,075
Записей в блоге: 10
Завершенные тесты: 1
08.02.2016, 12:59     Ffmpeg выдает moov atom not found если прервать процесс кодирования #2
Предполагается ОС Windows (со слов vxg).

Обработку простых вариантов (закрытие окна через крестик, обычное выключение ПК, Ctrl-C, ...) можно реализовать через SetConsoleCtrlHandler.
Кликните здесь для просмотра всего текста
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
#include <windows.h>
 
BOOL WINAPI ctrl_handler( DWORD fdwCtrlType ) {
    switch ( fdwCtrlType ) {
        case CTRL_C_EVENT:
        case CTRL_CLOSE_EVENT:
        case CTRL_BREAK_EVENT:
        case CTRL_LOGOFF_EVENT:
        case CTRL_SHUTDOWN_EVENT:
 
            // ... безопасно прекращаем цикл записи ...
 
            return TRUE;
    }
    return FALSE;
}
 
int main() {
    ::SetConsoleCtrlHandler( ctrl_handler, TRUE );
 
    // ... кодируем ...
 
    ::SetConsoleCtrlHandler( ctrl_handler, FALSE );
}


Всё гораздо сложнее обстоит с завершением процесса через диспетчер задач и выключением ПК из розетки.
Событие завершением процесса через диспетчер задач вроде как-то можно отловить нестандартным путём. Об этом надо почитать.
На случай выключения ПК из розетки конечно же лучше иметь ИБП, но этот вариант не рассматривается, поэтому единственный выход который я вижу - периодически закрывать выходной поток данных. Как это лучше сделать тоже надо подумать...
vxg
Модератор
3057 / 1859 / 195
Регистрация: 13.01.2012
Сообщений: 7,069
08.02.2016, 13:30  [ТС]     Ffmpeg выдает moov atom not found если прервать процесс кодирования #3
Цитата Сообщение от castaway Посмотреть сообщение
Всё гораздо сложнее
как можете прокомментировать необычности в поведении файла формируемого прямой записью пакетов на диск? почему некоторые программы его могут открыть а другие ругаются и почему ffprobe показывает несколько странные данные?
castaway
Эксперт С++
4876 / 3015 / 370
Регистрация: 10.11.2010
Сообщений: 11,075
Записей в блоге: 10
Завершенные тесты: 1
08.02.2016, 16:14     Ffmpeg выдает moov atom not found если прервать процесс кодирования #4
Цитата Сообщение от vxg Посмотреть сообщение
как можете прокомментировать необычности в поведении файла формируемого прямой записью пакетов на диск? почему некоторые программы его могут открыть а другие ругаются и почему ffprobe показывает несколько странные данные?
Насколько мне известно, там должна быть какая-то завершающая последовательность. Если её нет, то файл считается повреждённым.
Просто одни плееры лучше других обрабатывают испорченные файлы.
Кстати, вам принципиально использовать именно этот контейнер? Можно попробовать подобрать другой, с которым может быть меньше проблем.

Добавлено через 2 часа 16 минут
Input #0, h264, from 'out.mp4':
Duration: N/A, bitrate: N/A
Stream #0:0: Video: h264 (High), yuv420p, 720x304, 25 fps, 25 tbr, 1200k tbn, 50 tbc
Похоже причина в том, что в моём примере пишется сырое видео, без контейнера. Вполне возможно что именно поэтому некоторые плееры его не проигрывают.
vxg
Модератор
3057 / 1859 / 195
Регистрация: 13.01.2012
Сообщений: 7,069
08.02.2016, 16:43  [ТС]     Ffmpeg выдает moov atom not found если прервать процесс кодирования #5
Цитата Сообщение от castaway Посмотреть сообщение
видео, без контейнера
а как его оставив сырым контейнеризовать)?
castaway
Эксперт С++
4876 / 3015 / 370
Регистрация: 10.11.2010
Сообщений: 11,075
Записей в блоге: 10
Завершенные тесты: 1
08.02.2016, 17:04     Ffmpeg выдает moov atom not found если прервать процесс кодирования #6
Цитата Сообщение от vxg Посмотреть сообщение
а как его оставив сырым контейнеризовать)?
Я имею в виду что кадры тупо пишутся в файл подряд.
Я как раз сейчас думаю над тем, как его 'контейнизировать'...

Добавлено через 8 минут
Цитата Сообщение от vxg Посмотреть сообщение
moov atom not found
Я понял из-за чего появляется это сообщение. Этот атом пишет функция av_write_trailer. Которая естественно не вызывается при прерывании программы.
vxg
Модератор
3057 / 1859 / 195
Регистрация: 13.01.2012
Сообщений: 7,069
08.02.2016, 18:14  [ТС]     Ffmpeg выдает moov atom not found если прервать процесс кодирования #7
Цитата Сообщение от castaway Посмотреть сообщение
Я понял из-за чего появляется это сообщение. Этот атом пишет функция av_write_trailer. Которая естественно не вызывается при прерывании программы.
я знал об этом и вопрос лишь в том как так сконфигурировать вывод что бы даже без этой функции все было нормально. я знаю что это возможно. я видел программы которые пишут нормальные контейнеры устойчивые к прерыванию кодирования. как они это делают я пока не знаю. ffmpeg как минимум может это делать из командной строки если настроить запись по сегментам. но у меня не получается сделать то же самое из C++
castaway
Эксперт С++
4876 / 3015 / 370
Регистрация: 10.11.2010
Сообщений: 11,075
Записей в блоге: 10
Завершенные тесты: 1
08.02.2016, 18:22     Ffmpeg выдает moov atom not found если прервать процесс кодирования #8
Цитата Сообщение от vxg Посмотреть сообщение
ffmpeg как минимум может это делать из командной строки если настроить запись по сегментам. но у меня не получается сделать то же самое из C++
Даже если прервать через диспетчер задач?
Под записью по сегментам вы подразумеваете несколько выходных файлов? Если так, то это ещё проще.
vxg
Модератор
3057 / 1859 / 195
Регистрация: 13.01.2012
Сообщений: 7,069
08.02.2016, 18:43  [ТС]     Ffmpeg выдает moov atom not found если прервать процесс кодирования #9
Да даже если прервать. Нет запись идёт одним файлом. Подробнее в описании ключей -f segment и -segment_time N
castaway
Эксперт С++
4876 / 3015 / 370
Регистрация: 10.11.2010
Сообщений: 11,075
Записей в блоге: 10
Завершенные тесты: 1
08.02.2016, 18:55     Ffmpeg выдает moov atom not found если прервать процесс кодирования #10
Пример завершения при закрытии консольного окна
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
#include <windows.h>
#include <iostream>
 
extern "C" {
 #define __STDC_CONSTANT_MACROS
 #include <libavutil/opt.h>
 #include <libavutil/time.h>
 #include <libavutil/imgutils.h>
 #include <libavformat/avformat.h>
 #include <libavcodec/avcodec.h>
}
 
static BOOL g_bStop = FALSE;
static BOOL g_bCanExit = FALSE;
 
static BOOL WINAPI ctrl_handler( DWORD fdwCtrlType ) {
    switch ( fdwCtrlType ) {
        case CTRL_C_EVENT:
        case CTRL_CLOSE_EVENT:
        case CTRL_BREAK_EVENT:
        case CTRL_LOGOFF_EVENT:
        case CTRL_SHUTDOWN_EVENT:
            g_bStop = TRUE;
            while ( !g_bCanExit ) ::Sleep( 100 );
            return TRUE;
    }
    return FALSE;
}
 
int main()
{
    ::SetConsoleCtrlHandler( ctrl_handler, TRUE );
    av_register_all();
 
    const char * filename = "out.mp4";
 
    AVFormatContext * p_fmt_ctx;
    avformat_alloc_output_context2( &p_fmt_ctx, NULL, NULL, filename );
    if ( !p_fmt_ctx ) {
        std::cerr << "Could not deduce output format from file extension" << std::endl;
    } else {
        enum AVCodecID codec_id = AV_CODEC_ID_H264;
        AVCodec * p_codec = avcodec_find_encoder( codec_id );
        if ( !p_codec ) {
            std::cerr << "Could not find encoder for " << avcodec_get_name( codec_id ) << std::endl;
        } else {
            AVStream * p_stream = avformat_new_stream( p_fmt_ctx, p_codec );
            if ( !p_stream ) {
                std::cerr << "Could not allocate stream" << std::endl;
            } else {
                p_stream->id = p_fmt_ctx->nb_streams - 1;
 
                AVCodecContext * c = p_stream->codec;
                av_opt_set( c->priv_data, "preset", "slow", 0 );
 
                c->codec_id = codec_id;
 
                c->bit_rate = 1024 * 128;
                c->width    = 352;
                c->height   = 288;
 
                p_stream->time_base = (AVRational){ 1, 25 };
                c->time_base = p_stream->time_base;
 
                c->gop_size = 12; /* emit one intra frame every twelve frames at most */
                c->pix_fmt = AV_PIX_FMT_YUV420P;
 
                av_dump_format( p_fmt_ctx, 0, filename, 1 );
 
                /// open file
                avio_open2( &p_fmt_ctx->pb, filename, AVIO_FLAG_WRITE, NULL, NULL );
 
                /// write header
                if ( avformat_write_header( p_fmt_ctx, NULL ) != 0 ) {
                    std::cerr << "Could not write header" << std::endl;
                }
 
                /// open codec
                if ( avcodec_open2( c, p_codec, 0 ) >= 0 ) {
                    AVFrame * p_frame = av_frame_alloc();
                    if ( p_frame ) {
                        p_frame->format = c->pix_fmt;
                        p_frame->width  = c->width;
                        p_frame->height = c->height;
                        if ( av_image_alloc( p_frame->data, p_frame->linesize, c->width, c->height, c->pix_fmt, 32 ) >= 0 ) {
 
                            // ---------------------------------------------
                            AVPacket pkt;
 
                            int got_output;
                            for ( int i = 0; /*i < 25 * 30 &&*/ !g_bStop; ++i ) {
                                av_init_packet( &pkt );
                                pkt.data = NULL; // packet data will be allocated by the encoder
                                pkt.size = 0;
 
                                /* Y */
                                for ( int y = 0; y < c->height; ++y ) {
                                    for ( int x = 0; x < c->width; ++x ) {
                                        p_frame->data[0][y * p_frame->linesize[0] + x] = x + y + i * 3;
                                    }
                                }
 
                                /* Cb and Cr */
                                for ( int y = 0; y < c->height / 2; ++y ) {
                                    for ( int x = 0; x < c->width / 2; ++x ) {
                                        p_frame->data[1][y * p_frame->linesize[1] + x] = 128 + y + i * 2;
                                        p_frame->data[2][y * p_frame->linesize[2] + x] =  64 + x + i * 5;
                                    }
                                }
 
                                p_frame->pts = i * 25 * 30;//21;
                                //p_frame->pts = av_rescale_q( i, (AVRational){ 1, 25 }, (AVRational){ 1, 25 * 25 * 30 } );
 
                                int ret = avcodec_encode_video2( c, &pkt, p_frame, &got_output );
                                if ( ret >= 0 && got_output ) {
                                    av_interleaved_write_frame( p_fmt_ctx, &pkt );
                                    avio_flush( p_fmt_ctx->pb );
                                    av_packet_unref( &pkt );
                                }
                            }
 
                            /* get the delayed frames */
                            do {
                                int ret = avcodec_encode_video2( c, &pkt, NULL, &got_output );
                                if ( ret >= 0 && got_output ) {
                                    av_interleaved_write_frame( p_fmt_ctx, &pkt );
                                    avio_flush( p_fmt_ctx->pb );
                                    av_packet_unref( &pkt );
                                }
                            } while ( got_output && !g_bStop );
 
                            av_freep( &p_frame->data[0] );
                        }
                        av_frame_free( &p_frame );
                    }
                    avcodec_close( c );
                }
 
                /// write trailer etc...
                av_write_trailer( p_fmt_ctx );
                avio_close( p_fmt_ctx->pb );
                avcodec_close( c );
            }
        }
    }
    avformat_free_context( p_fmt_ctx );
    g_bCanExit = TRUE;
    ::SetConsoleCtrlHandler( ctrl_handler, FALSE );
}

А вот при выключении ПК из розетки поток в любом случае останется поврежденным (недописанным).
Как вариант - делить выходной файл на сегменты. Вас это устроит?

Добавлено через 1 минуту
Цитата Сообщение от vxg Посмотреть сообщение
Да даже если прервать.
Мне даже интересно стало. Сейчас попробую проверить как это работает.

Добавлено через 9 минут
vxg, у меня тут кое что не складывается... Вы можете привести пример командной строки перекодирования файла в сегментном режиме?
vxg
Модератор
3057 / 1859 / 195
Регистрация: 13.01.2012
Сообщений: 7,069
08.02.2016, 19:02  [ТС]     Ffmpeg выдает moov atom not found если прервать процесс кодирования #11
По памяти вроде как -f segment -segment_time 30 для деления каждые 30 с (за второй минус не уверен)
castaway
Эксперт С++
4876 / 3015 / 370
Регистрация: 10.11.2010
Сообщений: 11,075
Записей в блоге: 10
Завершенные тесты: 1
08.02.2016, 19:18     Ffmpeg выдает moov atom not found если прервать процесс кодирования #12
Цитата Сообщение от vxg Посмотреть сообщение
Нет запись идёт одним файлом.
Вы что-то путаете. Эти опции как раз предназначены для того, чтобы на выходе получалось несколько файлов.
Именно такой результат получается с командной строкой: ffmpeg -i in.mp4 -f segment -segment_time 10 -segment_format_options movflags=+faststart out%03d.mp4
И именно такое поведение описано в документации к FFMPEG.
vxg
Модератор
3057 / 1859 / 195
Регистрация: 13.01.2012
Сообщений: 7,069
08.02.2016, 19:23  [ТС]     Ffmpeg выдает moov atom not found если прервать процесс кодирования #13
А вы пробовали оборвать процесс до завершения формирования сегмента?
castaway
Эксперт С++
4876 / 3015 / 370
Регистрация: 10.11.2010
Сообщений: 11,075
Записей в блоге: 10
Завершенные тесты: 1
08.02.2016, 19:31     Ffmpeg выдает moov atom not found если прервать процесс кодирования #14
Цитата Сообщение от vxg Посмотреть сообщение
А вы пробовали оборвать процесс до завершения формирования сегмента?
Да. Завершая процесс через диспетчер задач, ffprobe на последний сегмент говорит: moov atom not found
Что, на самом деле, вполне ожидаемо и логично.
vxg
Модератор
3057 / 1859 / 195
Регистрация: 13.01.2012
Сообщений: 7,069
08.02.2016, 22:25  [ТС]     Ffmpeg выдает moov atom not found если прервать процесс кодирования #15
Цитата Сообщение от castaway Посмотреть сообщение
ожидаемо и логично
каюсь, ошибался, действительно этот вариант так же повреждает файл при прерывании кодирования
вот пример файла который формировался программой умеющей обходить повреждения в момент отключения питания компьютера - я ничего необычного в нем не нашел кроме разве что некого [0x1e0] после маркировки потока может у вас что то выйдет?
Вложения
Тип файла: rar test.rar (1.18 Мб, 6 просмотров)
castaway
Эксперт С++
4876 / 3015 / 370
Регистрация: 10.11.2010
Сообщений: 11,075
Записей в блоге: 10
Завершенные тесты: 1
09.02.2016, 11:11     Ffmpeg выдает moov atom not found если прервать процесс кодирования #16
Цитата Сообщение от vxg Посмотреть сообщение
может у вас что то выйдет?
Может быть. Я подумаю.

Добавлено через 20 минут
vxg, как я и предполагал, тут нужен другой контейнер.
Это работает так: ffmpeg -i in.mp4 -f segment -segment_time 10 -segment_format mpegts out%03d.mp4
Осталось опробовать это в программе... но не сегодня.

Добавлено через 12 часов 12 минут
Пробуйте такой вариант.
Кликните здесь для просмотра всего текста
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
#include <windows.h>
#include <iostream>
 
extern "C" {
 #define __STDC_CONSTANT_MACROS
 #include <libavutil/opt.h>
 #include <libavutil/time.h>
 #include <libavutil/imgutils.h>
 #include <libavformat/avformat.h>
 #include <libavcodec/avcodec.h>
}
 
//#define CONSOLE_CTRL_HANDLER
 
#ifdef CONSOLE_CTRL_HANDLER
 
static BOOL g_bStop = FALSE;
static BOOL g_bCanExit = FALSE;
 
static BOOL WINAPI ctrl_handler( DWORD fdwCtrlType ) {
    switch ( fdwCtrlType ) {
        case CTRL_C_EVENT:
        case CTRL_CLOSE_EVENT:
        case CTRL_BREAK_EVENT:
        case CTRL_LOGOFF_EVENT:
        case CTRL_SHUTDOWN_EVENT:
            g_bStop = TRUE;
            while ( !g_bCanExit ) ::Sleep( 100 );
            return TRUE;
    }
    return FALSE;
}
#endif
 
int main()
{
#ifdef CONSOLE_CTRL_HANDLER
    ::SetConsoleCtrlHandler( ctrl_handler, TRUE );
#endif
 
    av_register_all();
 
    const char * filename = "out.ts";
 
    AVFormatContext * p_fmt_ctx;
    avformat_alloc_output_context2( &p_fmt_ctx, NULL, NULL, filename );
    if ( !p_fmt_ctx ) {
        std::cerr << "Could not deduce output format from file extension" << std::endl;
    } else {
        enum AVCodecID codec_id = AV_CODEC_ID_H264;
        AVCodec * p_codec = avcodec_find_encoder( codec_id );
        if ( !p_codec ) {
            std::cerr << "Could not find encoder for " << avcodec_get_name( codec_id ) << std::endl;
        } else {
            AVStream * p_stream = avformat_new_stream( p_fmt_ctx, p_codec );
            if ( !p_stream ) {
                std::cerr << "Could not allocate stream" << std::endl;
            } else {
                p_stream->id = p_fmt_ctx->nb_streams - 1;
 
                AVCodecContext * c = p_stream->codec;
                av_opt_set( c->priv_data, "preset", "slow", 0 );
 
                c->codec_id = codec_id;
 
                c->bit_rate = 1024 * 128;
                c->width    = 352;
                c->height   = 288;
 
                p_stream->time_base = (AVRational){ 1, 25 };
                c->time_base = p_stream->time_base;
 
                c->gop_size = 12; /* emit one intra frame every twelve frames at most */
                c->pix_fmt = AV_PIX_FMT_YUV420P;
 
                av_dump_format( p_fmt_ctx, 0, filename, 1 );
 
                /// open file
                avio_open2( &p_fmt_ctx->pb, filename, AVIO_FLAG_WRITE, NULL, NULL );
 
                /// write header
                if ( avformat_write_header( p_fmt_ctx, NULL ) != 0 ) {
                    std::cerr << "Could not write header" << std::endl;
                }
 
                /// open codec
                if ( avcodec_open2( c, p_codec, 0 ) >= 0 ) {
                    AVFrame * p_frame = av_frame_alloc();
                    if ( p_frame ) {
                        p_frame->format = c->pix_fmt;
                        p_frame->width  = c->width;
                        p_frame->height = c->height;
                        if ( av_image_alloc( p_frame->data, p_frame->linesize, c->width, c->height, c->pix_fmt, 32 ) >= 0 ) {
                            AVPacket pkt;
 
                            int got_output;
                            for ( int i = 0; /*i < 25 * 30*/
#ifdef CONSOLE_CTRL_HANDLER
                                    && !g_bStop
#endif
                                    ; ++i )
                            {
                                av_init_packet( &pkt );
                                pkt.data = NULL; // packet data will be allocated by the encoder
                                pkt.size = 0;
 
                                /* Y */
                                for ( int y = 0; y < c->height; ++y ) {
                                    for ( int x = 0; x < c->width; ++x ) {
                                        p_frame->data[0][y * p_frame->linesize[0] + x] = x + y + i * 3;
                                    }
                                }
 
                                /* Cb and Cr */
                                for ( int y = 0; y < c->height / 2; ++y ) {
                                    for ( int x = 0; x < c->width / 2; ++x ) {
                                        p_frame->data[1][y * p_frame->linesize[1] + x] = 128 + y + i * 2;
                                        p_frame->data[2][y * p_frame->linesize[2] + x] =  64 + x + i * 5;
                                    }
                                }
 
                                p_frame->pts = i * 25 * 30;//21;
                                //p_frame->pts = av_rescale_q( i, (AVRational){ 1, 25 }, (AVRational){ 1, 25 * 25 * 30 } );
 
                                int ret = avcodec_encode_video2( c, &pkt, p_frame, &got_output );
                                if ( ret >= 0 && got_output ) {
                                    av_interleaved_write_frame( p_fmt_ctx, &pkt );
                                    avio_flush( p_fmt_ctx->pb );
                                    av_packet_unref( &pkt );
                                }
                            }
 
                            /* get the delayed frames */
                            do {
                                int ret = avcodec_encode_video2( c, &pkt, NULL, &got_output );
                                if ( ret >= 0 && got_output ) {
                                    av_interleaved_write_frame( p_fmt_ctx, &pkt );
                                    avio_flush( p_fmt_ctx->pb );
                                    av_packet_unref( &pkt );
                                }
                            } while ( got_output
#ifdef CONSOLE_CTRL_HANDLER
                                && !g_bStop
#endif
                                );
 
                            av_freep( &p_frame->data[0] );
                        }
                        av_frame_free( &p_frame );
                    }
                    avcodec_close( c );
                }
 
                /// write trailer etc...
                av_write_trailer( p_fmt_ctx );
                avio_close( p_fmt_ctx->pb );
                avcodec_close( c );
            }
        }
    }
    avformat_free_context( p_fmt_ctx );
 
#ifdef CONSOLE_CTRL_HANDLER
    g_bCanExit = TRUE;
    ::SetConsoleCtrlHandler( ctrl_handler, FALSE );
#endif
}
Суть - другой контейнер - транспортный поток.
vxg
Модератор
3057 / 1859 / 195
Регистрация: 13.01.2012
Сообщений: 7,069
09.02.2016, 13:28  [ТС]     Ffmpeg выдает moov atom not found если прервать процесс кодирования #17
Цитата Сообщение от castaway Посмотреть сообщение
Пробуйте такой вариант
да, вроде работает! но как те люди сделали то же самое с mp4? или тот файл не mp4 на самом деле?
castaway
Эксперт С++
4876 / 3015 / 370
Регистрация: 10.11.2010
Сообщений: 11,075
Записей в блоге: 10
Завершенные тесты: 1
09.02.2016, 14:15     Ffmpeg выдает moov atom not found если прервать процесс кодирования #18
Цитата Сообщение от vxg Посмотреть сообщение
но как те люди сделали то же самое с mp4? или тот файл не mp4 на самом деле?
mp4 - всего лишь расширение файла.
Тут следует разделять понятия контейнера и формата видеопотока.
У них, как и у нас, внутренний видеоформат - H264. Контейнер у них - MPEG, у нас - MPEG-TS.
Если вы захотите поменять контейнер на MPEG, то я думаю это не составит труда. С расширением то же самое.
vxg
Модератор
3057 / 1859 / 195
Регистрация: 13.01.2012
Сообщений: 7,069
09.02.2016, 15:22  [ТС]     Ffmpeg выдает moov atom not found если прервать процесс кодирования #19
Цитата Сообщение от castaway Посмотреть сообщение
Если вы захотите поменять контейнер на MPEG, то я думаю это не составит труда
а как?
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
10.02.2016, 19:00     Ffmpeg выдает moov atom not found если прервать процесс кодирования
Еще ссылки по теме:

Как получить страницу, если сервер выдает ответ 408 Request timeout? C++
C++ Как организовать проверку введённого числа, если введена буква то выдает ошибку и просит ввести число снова
C++ Чтение формата atom
C++ WinAPI В случае если процесс не найден сделать что то
C++ WinAPI Процесс A в цикле просит пользователя ввести 5 чисел и затем передает их процессу B. Процесс B отображает на

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

Или воспользуйтесь поиском по форуму:
castaway
Эксперт С++
4876 / 3015 / 370
Регистрация: 10.11.2010
Сообщений: 11,075
Записей в блоге: 10
Завершенные тесты: 1
10.02.2016, 19:00     Ffmpeg выдает moov atom not found если прервать процесс кодирования #20
Сообщение было отмечено автором темы, экспертом или модератором как ответ
Цитата Сообщение от vxg Посмотреть сообщение
а как?
Самый простой вариант - поменять расширение на mpeg/mpg.
Но тут возникает небольшая проблема, о решении которой я сейчас думаю, как и про другие варианты...

Добавлено через 23 часа 35 минут
Цитата Сообщение от vxg Посмотреть сообщение
а как?
Независимо от имени файла:
C++
1
    avformat_alloc_output_context2( &p_fmt_ctx, NULL, "VOB", filename );
Yandex
Объявления
10.02.2016, 19:00     Ffmpeg выдает moov atom not found если прервать процесс кодирования
Ответ Создать тему
Опции темы

Текущее время: 09:52. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru