Hello I have a strange problem... I have a RTMP server, which is nginx, built so:
wget https://github.com/arut/nginx-rtmp-module/archive/master.zip ./configure --with-http_ssl_module --add-module=../nginx-rtmp-module-master Its config: #user nginx; worker_processes 1; error_log logs/nginx.log debug; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; server { listen 80; server_name cloud.wtport.ru; location / { fastcgi_pass 127.0.0.1:9000; include fastcgi_params; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } } } rtmp { server { listen 1935; chunk_size 10000; application webteleportstreamingrtmp { allow publish all; allow play all; live on; #wait_video on; meta copy; #wait_key on; on_publish http://localhost/webteleport/webnotify/on_publish_rtmp; on_play http://localhost/webteleport/webnotify/on_play_rtmp; on_play_done http://localhost/webteleport/webnotify/on_stop_rtmp; on_update http://localhost/webteleport/webnotify/on_update_rtmp; notify_method get; } application webteleportarchivertmp { allow publish all; allow play all; play /usr/local/videoscope/archive/motion; on_play http://localhost/webteleport/webnotify/on_playarchive_rtmp; on_play_done http://localhost/webteleport/webnotify/on_stoparchive_rtmp; notify_method get; } } } It's running on Ubuntu, based on ffmpeg and translates a video from a camera. I want to receive the video on Windows 7, this is the main circle of the client: void FramesThread::run() { av_register_all(); AVFormatContext* format_context = 0; int err = avformat_open_input(&format_context, url.toUtf8().data(), NULL, NULL); //открыть url if (err < 0) { WebTeleportCommon_Logprintf_error(QString("Unable to open url: %1").arg(url)); return; } //format_context->probesize = 10000000; //format_context->max_analyze_duration = 2 * AV_TIME_BASE; err = avformat_find_stream_info(format_context, NULL); if (err < 0) { WebTeleportCommon_Logprintf_error(QString("Unable to find stream info")); return; } AVStream* video_stream = 0; AVStream* audio_stream = 0; for (int i = 0; i < format_context->nb_streams; ++i) { if (format_context->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) video_stream = format_context->streams[i]; else if (format_context->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) audio_stream = format_context->streams[i]; } if (video_stream == 0) { WebTeleportCommon_Logprintf_error("Unable to find video stream"); return; } AVCodecContext* video_codec_context = 0; { QMutexLocker m(&player->frames_mutex); video_codec_context = format_context->streams[video_stream->index]->codec; player->video_codec_context = video_codec_context; } AVCodec* codec = avcodec_find_decoder(video_codec_context->codec_id); err = avcodec_open2(video_codec_context, codec, NULL); if (err < 0) { WebTeleportCommon_Logprintf_error("Unable to open codec"); return; } AVCodecContext* audio_codec_context = 0; if (audio_stream != 0) { QMutexLocker m(&player->frames_mutex); AVCodecContext* orig_context = format_context->streams[audio_stream->index]->codec; codec = avcodec_find_decoder(orig_context->codec_id); audio_codec_context = avcodec_alloc_context3(codec); avcodec_copy_context(audio_codec_context, orig_context); err = avcodec_open2(audio_codec_context, codec, NULL); if (err < 0) { WebTeleportCommon_Logprintf_error("Unable to open audio codec"); return; } player->audio_codec_context = audio_codec_context; } struct SwsContext* sws_ctx = sws_getContext(video_codec_context->width, video_codec_context->height, video_codec_context->pix_fmt, video_codec_context->width, video_codec_context->height, AV_PIX_FMT_YUV420P, SWS_BILINEAR, NULL, NULL, NULL); int y_plane_size = video_codec_context->width * video_codec_context->height; int uv_plane_size = video_codec_context->width * video_codec_context->height / 4; uint8_t* y_plane = (uint8_t*)malloc(y_plane_size); uint8_t* u_plane = (uint8_t*)malloc(uv_plane_size); uint8_t* v_plane = (uint8_t*)malloc(uv_plane_size); { QMutexLocker m(&player->frames_mutex); player->y_plane = (uint8_t*)malloc(y_plane_size); player->u_plane = (uint8_t*)malloc(uv_plane_size); player->v_plane = (uint8_t*)malloc(uv_plane_size); } SwrContext* audio_resample_context = 0; if (audio_codec_context) { audio_resample_context = swr_alloc_set_opts(NULL, AV_CH_LAYOUT_MONO, AV_SAMPLE_FMT_S16, audio_codec_context->sample_rate, audio_codec_context->channel_layout, audio_codec_context->sample_fmt, audio_codec_context->sample_rate, 0, NULL); if (audio_resample_context == NULL) { WebTeleportCommon_Logprintf_error("Unable to open audio context"); return; } if (swr_init(audio_resample_context) != 0) { WebTeleportCommon_Logprintf_error("Unable to init audio context"); return; } } AVPacket packet; int uv_pitch = video_codec_context->width / 2; int frame_finished = 0; AVFrame* frame = av_frame_alloc(); //поток чтения фреймов while (av_read_frame(format_context, &packet) >= 0 && !exit) { av_init_packet(&packet); if (packet.stream_index == video_stream->index) { WebTeleportCommon_Logprintf_debug("Video frame"); avcodec_decode_video2(video_codec_context, frame, &frame_finished, &packet); if (frame_finished) { AVPicture pict; pict.data[0] = y_plane; pict.data[1] = u_plane; pict.data[2] = v_plane; pict.linesize[0] = video_codec_context->width; pict.linesize[1] = uv_pitch; pict.linesize[2] = uv_pitch; //сконвертировать изображение в формат YUV который использует SDL sws_scale(sws_ctx, (uint8_t const * const *)frame->data, frame->linesize, 0, video_codec_context->height, pict.data, pict.linesize); //предоставить для отображения QMutexLocker m(&player->frames_mutex); memcpy(player->y_plane, pict.data[0], y_plane_size); memcpy(player->u_plane, pict.data[1], uv_plane_size); memcpy(player->v_plane, pict.data[2], uv_plane_size); player->new_video_frame = true; } } else if (packet.stream_index == audio_stream->index) { WebTeleportCommon_Logprintf_debug("Audio frame"); int res = 0; if ((res = avcodec_send_packet(audio_codec_context, &packet)) != 0) { av_packet_unref(&packet); av_free_packet(&packet); av_frame_unref(frame); continue; } if (avcodec_receive_frame(audio_codec_context, frame) != 0) { av_packet_unref(&packet); av_free_packet(&packet); av_frame_unref(frame); continue; } uint8_t* resampled_data; int resampled_data_size = 0; if (!ResampleAudioStream(audio_resample_context, frame, frame->nb_samples, &resampled_data, &resampled_data_size)) { av_packet_unref(&packet); av_free_packet(&packet); av_frame_unref(frame); av_freep(&resampled_data); continue; } QMutexLocker m(&player->frames_mutex); player->audio_data.clear(); std::vector<uint8_t> d(resampled_data, resampled_data + resampled_data_size); player->audio_data.push_back(d); av_freep(&resampled_data); av_packet_unref(&packet); while (swr_get_delay(audio_resample_context, 1) > 0) { uint8_t* flushed_data; int flushed_data_size; frame->extended_data = NULL; frame->nb_samples = 0; if (!ResampleAudioStream(audio_resample_context, frame, 1024, &flushed_data, &flushed_data_size)) { av_freep(&flushed_data); break; } d.assign(resampled_data, resampled_data + resampled_data_size); player->audio_data.push_back(d); av_freep(&flushed_data); } player->new_audio_frame = true; } av_free_packet(&packet); //Sleep(10); } av_frame_free(&frame); frame = 0; { QMutexLocker m(&player->frames_mutex); free(player->y_plane); player->y_plane = 0; free(player->u_plane); player->u_plane = 0; free(player->v_plane); player->v_plane = 0; } free(y_plane); free(u_plane); free(v_plane); avcodec_close(video_codec_context); if (audio_codec_context) avcodec_close(audio_codec_context); avformat_close_input(&format_context); } The problem is: if the server emits both video and audio packets, while (av_read_frame()) circle gives only audio packets. If the server emits only video packets, the circle gives them. I cannot give the both video and audio packets. The code above the while works well, I have both video_stream and audio_stream, I open both codecs. Wireshark shows me the both types of RTMP packets come. Windows 7 running in VirtualBox if it has meaning. _______________________________________________ Libav-user mailing list [email protected] http://ffmpeg.org/mailman/listinfo/libav-user
